pi-x-ide 1.4.2 → 1.5.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.md +24 -16
- package/README.zh.md +22 -16
- package/dist/package.json +31 -26
- package/package.json +38 -32
- package/nvim/bin/pi-x-ide-nvim-sidecar.cjs +0 -21
- package/nvim/doc/pi-x-ide.txt +0 -112
- package/nvim/lua/pi_x_ide/init.lua +0 -442
- package/nvim/plugin/pi-x-ide.lua +0 -15
package/README.md
CHANGED
|
@@ -46,11 +46,16 @@ See [Configuration Reference](#pi-side-environment-variables) for all available
|
|
|
46
46
|
|
|
47
47
|
No extension installation is needed. Pi automatically detects Zed when running inside a Zed terminal (`ZED_TERM=true` or `TERM_PROGRAM=zed`). Pi reads Zed's local state database to discover the active editor file and selection.
|
|
48
48
|
|
|
49
|
-
Requires Node.js ≥ 26 and Zed running on the same machine.
|
|
50
|
-
|
|
51
49
|
#### Neovim
|
|
52
50
|
|
|
53
|
-
Neovim support uses a Lua plugin plus a
|
|
51
|
+
Neovim support uses a Lua plugin plus a sidecar process. On first start the
|
|
52
|
+
plugin downloads a standalone binary for your platform (Linux / macOS / Windows,
|
|
53
|
+
x64 or arm64) from GitHub Releases. If the download fails, or no binary matches
|
|
54
|
+
your platform, the plugin falls back to the bundled Node.js sidecar — Node.js is
|
|
55
|
+
then required on PATH.
|
|
56
|
+
|
|
57
|
+
The binary is cached under `stdpath("cache")/pi-x-ide/` and reused on subsequent
|
|
58
|
+
starts. Plugin updates trigger a one-time re-download.
|
|
54
59
|
|
|
55
60
|
**lazy.nvim:**
|
|
56
61
|
|
|
@@ -151,11 +156,14 @@ require("pi_x_ide").setup({
|
|
|
151
156
|
range_format = "comma", -- or "dash"
|
|
152
157
|
debounce_ms = 150,
|
|
153
158
|
-- sidecar_cmd = { "node", "/absolute/path/to/pi-x-ide-nvim-sidecar.cjs" },
|
|
159
|
+
-- (defaults to the platform binary; falls back to node + cjs if no binary found)
|
|
154
160
|
-- workspace_folders = { "/path/to/project" },
|
|
155
161
|
})
|
|
156
162
|
```
|
|
157
163
|
|
|
158
|
-
If the sidecar does not start, run `:PiXIdeStatus`,
|
|
164
|
+
If the sidecar does not start, run `:PiXIdeStatus`, or set `sidecar_cmd` to a
|
|
165
|
+
custom command. The plugin prefers the platform binary but falls back to Node.js
|
|
166
|
+
when no binary matches.
|
|
159
167
|
|
|
160
168
|
**Commands:**
|
|
161
169
|
|
|
@@ -203,7 +211,7 @@ See [docs/specs/ide-protocol.md](docs/specs/ide-protocol.md) for protocol detail
|
|
|
203
211
|
### Prerequisites
|
|
204
212
|
|
|
205
213
|
- Node.js ≥ 26
|
|
206
|
-
-
|
|
214
|
+
- bun ≥ 1.3 (`packageManager` declared as `bun@1.3.14`)
|
|
207
215
|
- VS Code ≥ 1.90 (VS Code extension only)
|
|
208
216
|
- Neovim ≥ 0.9 (Neovim plugin only)
|
|
209
217
|
|
|
@@ -214,8 +222,8 @@ Clone the repository, then build:
|
|
|
214
222
|
```bash
|
|
215
223
|
git clone https://github.com/balaenis/pi-x-ide.git
|
|
216
224
|
cd pi-x-ide
|
|
217
|
-
|
|
218
|
-
|
|
225
|
+
bun install
|
|
226
|
+
bun run build
|
|
219
227
|
```
|
|
220
228
|
|
|
221
229
|
To load the local build without installing globally:
|
|
@@ -226,13 +234,13 @@ pi -e ./src/pi/index.ts
|
|
|
226
234
|
|
|
227
235
|
Common commands:
|
|
228
236
|
|
|
229
|
-
| Command
|
|
230
|
-
|
|
|
231
|
-
| `
|
|
232
|
-
| `
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
237
|
+
| Command | Description |
|
|
238
|
+
| ------------------------ | -------------------------------------------------------------------------------------------------- |
|
|
239
|
+
| `bun run build` | Build Pi-side TypeScript → `dist/` + Neovim sidecar → `nvim/bin/` + VS Code bundle → `vscode/out/` |
|
|
240
|
+
| `bun run typecheck` | Type-check only (no output files) |
|
|
241
|
+
| `bun run test` | Build + run unit tests |
|
|
242
|
+
| `bun run package:vscode` | Package VS Code extension as VSIX |
|
|
243
|
+
| `bun run vsix` | Alias for `bun run package:vscode` |
|
|
236
244
|
|
|
237
245
|
### Testing the VS Code Extension Locally
|
|
238
246
|
|
|
@@ -242,13 +250,13 @@ Common commands:
|
|
|
242
250
|
2. Go to the **Run and Debug** panel (`Ctrl+Shift+D`).
|
|
243
251
|
3. Select **Run Pi x IDE VS Code Extension**.
|
|
244
252
|
4. Press **F5**:
|
|
245
|
-
- The `preLaunchTask` automatically runs `
|
|
253
|
+
- The `preLaunchTask` automatically runs `bun run build`.
|
|
246
254
|
- A new VS Code window titled `[Extension Development Host]` opens.
|
|
247
255
|
|
|
248
256
|
#### Option 2: Package VSIX and Install
|
|
249
257
|
|
|
250
258
|
```bash
|
|
251
|
-
|
|
259
|
+
bun run package:vscode
|
|
252
260
|
code --install-extension './vscode'-0.1.0.vsix
|
|
253
261
|
```
|
|
254
262
|
|
package/README.zh.md
CHANGED
|
@@ -46,11 +46,15 @@ PI_X_IDE_AUTO_INSTALL=0
|
|
|
46
46
|
|
|
47
47
|
无需安装任何扩展。Pi 在 Zed 终端中运行时(`ZED_TERM=true` 或 `TERM_PROGRAM=zed`)会自动检测并连接。Pi 通过读取 Zed 本地状态数据库获取活跃编辑器和选区信息。
|
|
48
48
|
|
|
49
|
-
需要 Node.js ≥ 26,Zed 在同一台机器上运行。
|
|
50
|
-
|
|
51
49
|
#### Neovim
|
|
52
50
|
|
|
53
|
-
Neovim 支持由一个 Lua
|
|
51
|
+
Neovim 支持由一个 Lua 插件和一个 sidecar 进程组成。首次启动时插件会自动从
|
|
52
|
+
GitHub Releases 下载适合当前平台的独立二进制文件(Linux/macOS/Windows,
|
|
53
|
+
x64 或 arm64)。下载失败或无匹配二进制时,插件降级到内置的 Node.js sidecar —
|
|
54
|
+
此时需要 PATH 中有 Node.js。
|
|
55
|
+
|
|
56
|
+
二进制文件缓存在 `stdpath("cache")/pi-x-ide/` 目录,后续启动直接复用。插件
|
|
57
|
+
更新后会触发一次重新下载。
|
|
54
58
|
|
|
55
59
|
**lazy.nvim:**
|
|
56
60
|
|
|
@@ -151,11 +155,13 @@ require("pi_x_ide").setup({
|
|
|
151
155
|
range_format = "comma", -- 或 "dash"
|
|
152
156
|
debounce_ms = 150,
|
|
153
157
|
-- sidecar_cmd = { "node", "/absolute/path/to/pi-x-ide-nvim-sidecar.cjs" },
|
|
158
|
+
-- (默认使用平台二进制文件;找不到时降级到 node + cjs)
|
|
154
159
|
-- workspace_folders = { "/path/to/project" },
|
|
155
160
|
})
|
|
156
161
|
```
|
|
157
162
|
|
|
158
|
-
如果 sidecar 无法启动,请运行 `:PiXIdeStatus
|
|
163
|
+
如果 sidecar 无法启动,请运行 `:PiXIdeStatus`,或设置 `sidecar_cmd` 为自定义
|
|
164
|
+
命令。插件优先使用平台二进制文件,找不到匹配项时降级到 Node.js。
|
|
159
165
|
|
|
160
166
|
**命令:**
|
|
161
167
|
|
|
@@ -203,7 +209,7 @@ Pi 通过 `ctx.cwd` 与 lock file 中的 `workspaceFolders` 做最长路径匹
|
|
|
203
209
|
### 环境依赖
|
|
204
210
|
|
|
205
211
|
- Node.js ≥ 26
|
|
206
|
-
-
|
|
212
|
+
- bun ≥ 1.3(`packageManager` 声明为 `bun@1.3.14`)
|
|
207
213
|
- VS Code ≥ 1.90(仅 VS Code 扩展需要)
|
|
208
214
|
- Neovim ≥ 0.9(仅 Neovim 插件需要)
|
|
209
215
|
|
|
@@ -214,8 +220,8 @@ Clone 仓库后构建:
|
|
|
214
220
|
```bash
|
|
215
221
|
git clone https://github.com/balaenis/pi-x-ide.git
|
|
216
222
|
cd pi-x-ide
|
|
217
|
-
|
|
218
|
-
|
|
223
|
+
bun install
|
|
224
|
+
bun run build
|
|
219
225
|
```
|
|
220
226
|
|
|
221
227
|
加载本地构建(无需全局安装):
|
|
@@ -226,13 +232,13 @@ pi -e ./src/pi/index.ts
|
|
|
226
232
|
|
|
227
233
|
常用命令:
|
|
228
234
|
|
|
229
|
-
| 命令
|
|
230
|
-
|
|
|
231
|
-
| `
|
|
232
|
-
| `
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
235
|
+
| 命令 | 说明 |
|
|
236
|
+
| ------------------------ | ----------------------------------------------------------------------------------------------- |
|
|
237
|
+
| `bun run build` | 编译 Pi 侧 TypeScript → `dist/` + Neovim sidecar → `nvim/bin/` + VS Code bundle → `vscode/out/` |
|
|
238
|
+
| `bun run typecheck` | 类型检查(不产出文件) |
|
|
239
|
+
| `bun run test` | 编译 + 运行单元测试 |
|
|
240
|
+
| `bun run package:vscode` | 打包 VS Code 扩展为 VSIX |
|
|
241
|
+
| `bun run vsix` | `bun run package:vscode` 的别名 |
|
|
236
242
|
|
|
237
243
|
### 本地测试 VS Code 扩展
|
|
238
244
|
|
|
@@ -242,13 +248,13 @@ pi -e ./src/pi/index.ts
|
|
|
242
248
|
2. 进入 **Run and Debug** 面板(`Ctrl+Shift+D`)。
|
|
243
249
|
3. 选择 **Run Pi x IDE VS Code Extension**。
|
|
244
250
|
4. 按 **F5**:
|
|
245
|
-
- preLaunchTask 会自动执行 `
|
|
251
|
+
- preLaunchTask 会自动执行 `bun run build`。
|
|
246
252
|
- 打开一个标题包含 `[Extension Development Host]` 的新 VS Code 窗口。
|
|
247
253
|
|
|
248
254
|
#### 方式二:打包 VSIX 后安装
|
|
249
255
|
|
|
250
256
|
```bash
|
|
251
|
-
|
|
257
|
+
bun run package:vscode
|
|
252
258
|
code --install-extension './vscode'-0.1.0.vsix
|
|
253
259
|
```
|
|
254
260
|
|
package/dist/package.json
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-x-ide",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Pi extension package for IDE selection context integration.",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
7
|
"schemas",
|
|
8
|
-
"src"
|
|
9
|
-
"nvim/lua",
|
|
10
|
-
"nvim/plugin",
|
|
11
|
-
"nvim/doc",
|
|
12
|
-
"nvim/bin"
|
|
8
|
+
"src"
|
|
13
9
|
],
|
|
14
10
|
"keywords": [
|
|
15
11
|
"pi-package",
|
|
@@ -23,52 +19,61 @@
|
|
|
23
19
|
"license": "Apache-2.0",
|
|
24
20
|
"repository": {
|
|
25
21
|
"type": "git",
|
|
26
|
-
"url": "https://github.com/balaenis/pi-x-ide"
|
|
22
|
+
"url": "git+https://github.com/balaenis/pi-x-ide.git"
|
|
27
23
|
},
|
|
28
24
|
"bugs": {
|
|
29
25
|
"url": "https://github.com/balaenis/pi-x-ide/issues"
|
|
30
26
|
},
|
|
31
27
|
"homepage": "https://github.com/balaenis/pi-x-ide#readme",
|
|
32
|
-
"
|
|
28
|
+
"workspaces": [
|
|
29
|
+
"vscode"
|
|
30
|
+
],
|
|
31
|
+
"packageManager": "bun@1.3.14",
|
|
33
32
|
"engines": {
|
|
34
33
|
"node": ">=26"
|
|
35
34
|
},
|
|
36
35
|
"type": "commonjs",
|
|
37
36
|
"main": "./dist/src/pi/index.js",
|
|
38
37
|
"scripts": {
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"check:config-schema
|
|
43
|
-
"test": "pnpm check:config-schema && pnpm build && node --test dist/test/*.test.js",
|
|
38
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && bun run --filter './vscode' typecheck",
|
|
39
|
+
"generate:config-schema": "bun run scripts/generate-config-schema.cjs",
|
|
40
|
+
"check:config-schema": "bun run scripts/generate-config-schema.cjs --check",
|
|
41
|
+
"test": "bun run check:config-schema && bun run compile && node --test dist/test/*.test.js",
|
|
44
42
|
"lint": "eslint .",
|
|
45
43
|
"lint:fix": "eslint . --fix",
|
|
46
44
|
"format": "prettier --write .",
|
|
47
45
|
"format:check": "prettier --check .",
|
|
48
|
-
"compile
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"vsix": "
|
|
46
|
+
"compile": "tsc -p tsconfig.json",
|
|
47
|
+
"compile:vsix": "bun run --filter './vscode' compile",
|
|
48
|
+
"sync:vsix-assets": "bun run --filter './vscode' sync:assets",
|
|
49
|
+
"package:vsix": "bun run --filter './vscode' package",
|
|
50
|
+
"package:nvim-sidecar": "bun run scripts/build-nvim-sidecar.mjs --production",
|
|
51
|
+
"package:nvim-sidecar:all": "bun run scripts/build-nvim-sidecar.mjs --production --target=all",
|
|
52
|
+
"build": "bun run compile && bun run compile:vsix && bun run package:nvim-sidecar",
|
|
53
|
+
"build:all": "bun run compile && bun run compile:vsix && bun run package:nvim-sidecar:all"
|
|
52
54
|
},
|
|
53
55
|
"dependencies": {
|
|
54
|
-
"ws": "^8.
|
|
56
|
+
"ws": "^8.21.0"
|
|
55
57
|
},
|
|
56
58
|
"peerDependencies": {
|
|
57
59
|
"@earendil-works/pi-coding-agent": "*"
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
60
|
-
"@earendil-works/pi-coding-agent": "^0.79.
|
|
62
|
+
"@earendil-works/pi-coding-agent": "^0.79.1",
|
|
61
63
|
"@eslint/js": "^10.0.1",
|
|
62
|
-
"@types/node": "^25.9.
|
|
63
|
-
"@types/ws": "^8.
|
|
64
|
-
"@vscode/vsce": "^3.
|
|
65
|
-
"esbuild": "^0.
|
|
64
|
+
"@types/node": "^25.9.3",
|
|
65
|
+
"@types/ws": "^8.18.1",
|
|
66
|
+
"@vscode/vsce": "^3.9.2",
|
|
67
|
+
"esbuild": "^0.28.0",
|
|
66
68
|
"eslint": "^10.4.1",
|
|
67
69
|
"eslint-config-prettier": "^10.1.8",
|
|
68
|
-
"prettier": "^3.8.
|
|
69
|
-
"typescript": "^
|
|
70
|
-
"typescript-eslint": "^8.
|
|
70
|
+
"prettier": "^3.8.4",
|
|
71
|
+
"typescript": "^6.0.3",
|
|
72
|
+
"typescript-eslint": "^8.61.0"
|
|
71
73
|
},
|
|
74
|
+
"trustedDependencies": [
|
|
75
|
+
"esbuild"
|
|
76
|
+
],
|
|
72
77
|
"pi": {
|
|
73
78
|
"image": "https://fastly.jsdelivr.net/gh/balaenis/pi-x-ide@main/assets/icons/pi-x-ide.png",
|
|
74
79
|
"extensions": [
|
package/package.json
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-x-ide",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Pi extension package for IDE selection context integration.",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
7
|
"schemas",
|
|
8
|
-
"src"
|
|
9
|
-
"nvim/lua",
|
|
10
|
-
"nvim/plugin",
|
|
11
|
-
"nvim/doc",
|
|
12
|
-
"nvim/bin"
|
|
8
|
+
"src"
|
|
13
9
|
],
|
|
14
10
|
"keywords": [
|
|
15
11
|
"pi-package",
|
|
@@ -23,55 +19,65 @@
|
|
|
23
19
|
"license": "Apache-2.0",
|
|
24
20
|
"repository": {
|
|
25
21
|
"type": "git",
|
|
26
|
-
"url": "https://github.com/balaenis/pi-x-ide"
|
|
22
|
+
"url": "git+https://github.com/balaenis/pi-x-ide.git"
|
|
27
23
|
},
|
|
28
24
|
"bugs": {
|
|
29
25
|
"url": "https://github.com/balaenis/pi-x-ide/issues"
|
|
30
26
|
},
|
|
31
27
|
"homepage": "https://github.com/balaenis/pi-x-ide#readme",
|
|
28
|
+
"workspaces": [
|
|
29
|
+
"vscode"
|
|
30
|
+
],
|
|
31
|
+
"packageManager": "bun@1.3.14",
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=26"
|
|
34
34
|
},
|
|
35
35
|
"type": "commonjs",
|
|
36
36
|
"main": "./dist/src/pi/index.js",
|
|
37
|
+
"scripts": {
|
|
38
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && bun run --filter './vscode' typecheck",
|
|
39
|
+
"generate:config-schema": "bun run scripts/generate-config-schema.cjs",
|
|
40
|
+
"check:config-schema": "bun run scripts/generate-config-schema.cjs --check",
|
|
41
|
+
"test": "bun run check:config-schema && bun run compile && node --test dist/test/*.test.js",
|
|
42
|
+
"lint": "eslint .",
|
|
43
|
+
"lint:fix": "eslint . --fix",
|
|
44
|
+
"format": "prettier --write .",
|
|
45
|
+
"format:check": "prettier --check .",
|
|
46
|
+
"compile": "tsc -p tsconfig.json",
|
|
47
|
+
"compile:vsix": "bun run --filter './vscode' compile",
|
|
48
|
+
"sync:vsix-assets": "bun run --filter './vscode' sync:assets",
|
|
49
|
+
"package:vsix": "bun run --filter './vscode' package",
|
|
50
|
+
"package:nvim-sidecar": "bun run scripts/build-nvim-sidecar.mjs --production",
|
|
51
|
+
"package:nvim-sidecar:all": "bun run scripts/build-nvim-sidecar.mjs --production --target=all",
|
|
52
|
+
"build": "bun run compile && bun run compile:vsix && bun run package:nvim-sidecar",
|
|
53
|
+
"build:all": "bun run compile && bun run compile:vsix && bun run package:nvim-sidecar:all"
|
|
54
|
+
},
|
|
37
55
|
"dependencies": {
|
|
38
|
-
"ws": "^8.
|
|
56
|
+
"ws": "^8.21.0"
|
|
39
57
|
},
|
|
40
58
|
"peerDependencies": {
|
|
41
59
|
"@earendil-works/pi-coding-agent": "*"
|
|
42
60
|
},
|
|
43
61
|
"devDependencies": {
|
|
44
|
-
"@earendil-works/pi-coding-agent": "^0.79.
|
|
62
|
+
"@earendil-works/pi-coding-agent": "^0.79.1",
|
|
45
63
|
"@eslint/js": "^10.0.1",
|
|
46
|
-
"@types/node": "^25.9.
|
|
47
|
-
"@types/ws": "^8.
|
|
48
|
-
"@vscode/vsce": "^3.
|
|
49
|
-
"esbuild": "^0.
|
|
64
|
+
"@types/node": "^25.9.3",
|
|
65
|
+
"@types/ws": "^8.18.1",
|
|
66
|
+
"@vscode/vsce": "^3.9.2",
|
|
67
|
+
"esbuild": "^0.28.0",
|
|
50
68
|
"eslint": "^10.4.1",
|
|
51
69
|
"eslint-config-prettier": "^10.1.8",
|
|
52
|
-
"prettier": "^3.8.
|
|
53
|
-
"typescript": "^
|
|
54
|
-
"typescript-eslint": "^8.
|
|
70
|
+
"prettier": "^3.8.4",
|
|
71
|
+
"typescript": "^6.0.3",
|
|
72
|
+
"typescript-eslint": "^8.61.0"
|
|
55
73
|
},
|
|
74
|
+
"trustedDependencies": [
|
|
75
|
+
"esbuild"
|
|
76
|
+
],
|
|
56
77
|
"pi": {
|
|
57
78
|
"image": "https://fastly.jsdelivr.net/gh/balaenis/pi-x-ide@main/assets/icons/pi-x-ide.png",
|
|
58
79
|
"extensions": [
|
|
59
80
|
"./src/pi/index.ts"
|
|
60
81
|
]
|
|
61
|
-
},
|
|
62
|
-
"scripts": {
|
|
63
|
-
"build": "tsc -p tsconfig.json && node scripts/build-nvim-sidecar.mjs --production && pnpm --filter './vscode' compile",
|
|
64
|
-
"typecheck": "tsc -p tsconfig.json --noEmit && pnpm --filter './vscode' typecheck",
|
|
65
|
-
"generate:config-schema": "node scripts/generate-config-schema.cjs",
|
|
66
|
-
"check:config-schema": "node scripts/generate-config-schema.cjs --check",
|
|
67
|
-
"test": "pnpm check:config-schema && pnpm build && node --test dist/test/*.test.js",
|
|
68
|
-
"lint": "eslint .",
|
|
69
|
-
"lint:fix": "eslint . --fix",
|
|
70
|
-
"format": "prettier --write .",
|
|
71
|
-
"format:check": "prettier --check .",
|
|
72
|
-
"compile:vscode": "pnpm --filter './vscode' compile",
|
|
73
|
-
"sync:vscode-assets": "pnpm --filter './vscode' sync:assets",
|
|
74
|
-
"package:vscode": "pnpm --filter './vscode' package",
|
|
75
|
-
"vsix": "pnpm package:vscode"
|
|
76
82
|
}
|
|
77
|
-
}
|
|
83
|
+
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";var qr=Object.create;var ce=Object.defineProperty;var Gr=Object.getOwnPropertyDescriptor;var zr=Object.getOwnPropertyNames;var Hr=Object.getPrototypeOf,Jr=Object.prototype.hasOwnProperty;var y=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Yr=(t,e)=>{for(var r in e)ce(t,r,{get:e[r],enumerable:!0})},nt=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of zr(e))!Jr.call(t,s)&&s!==r&&ce(t,s,{get:()=>e[s],enumerable:!(n=Gr(e,s))||n.enumerable});return t};var N=(t,e,r)=>(r=t!=null?qr(Hr(t)):{},nt(e||!t||!t.__esModule?ce(r,"default",{value:t,enumerable:!0}):r,t)),Kr=t=>nt(ce({},"__esModule",{value:!0}),t);var C=y((Hs,gt)=>{"use strict";var mt=["nodebuffer","arraybuffer","fragments"],_t=typeof Blob<"u";_t&&mt.push("blob");gt.exports={BINARY_TYPES:mt,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:_t,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var ee=y((Js,le)=>{"use strict";var{EMPTY_BUFFER:sn}=C(),Te=Buffer[Symbol.species];function on(t,e){if(t.length===0)return sn;if(t.length===1)return t[0];let r=Buffer.allocUnsafe(e),n=0;for(let s=0;s<t.length;s++){let i=t[s];r.set(i,n),n+=i.length}return n<e?new Te(r.buffer,r.byteOffset,n):r}function St(t,e,r,n,s){for(let i=0;i<s;i++)r[n+i]=t[i]^e[i&3]}function yt(t,e){for(let r=0;r<t.length;r++)t[r]^=e[r&3]}function an(t){return t.length===t.buffer.byteLength?t.buffer:t.buffer.slice(t.byteOffset,t.byteOffset+t.length)}function Pe(t){if(Pe.readOnly=!0,Buffer.isBuffer(t))return t;let e;return t instanceof ArrayBuffer?e=new Te(t):ArrayBuffer.isView(t)?e=new Te(t.buffer,t.byteOffset,t.byteLength):(e=Buffer.from(t),Pe.readOnly=!1),e}le.exports={concat:on,mask:St,toArrayBuffer:an,toBuffer:Pe,unmask:yt};if(!process.env.WS_NO_BUFFER_UTIL)try{let t=require("bufferutil");le.exports.mask=function(e,r,n,s,i){i<48?St(e,r,n,s,i):t.mask(e,r,n,s,i)},le.exports.unmask=function(e,r){e.length<32?yt(e,r):t.unmask(e,r)}}catch{}});var kt=y((Ys,Et)=>{"use strict";var xt=Symbol("kDone"),Le=Symbol("kRun"),Ne=class{constructor(e){this[xt]=()=>{this.pending--,this[Le]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[Le]()}[Le](){if(this.pending!==this.concurrency&&this.jobs.length){let e=this.jobs.shift();this.pending++,e(this[xt])}}};Et.exports=Ne});var q=y((Ks,Ot)=>{"use strict";var te=require("zlib"),wt=ee(),cn=kt(),{kStatusCode:vt}=C(),ln=Buffer[Symbol.species],fn=Buffer.from([0,0,255,255]),de=Symbol("permessage-deflate"),T=Symbol("total-length"),V=Symbol("callback"),I=Symbol("buffers"),j=Symbol("error"),fe,Ie=class{constructor(e){if(this._options=e||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._maxPayload=this._options.maxPayload|0,this._isServer=!!this._options.isServer,this._deflate=null,this._inflate=null,this.params=null,!fe){let r=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;fe=new cn(r)}}static get extensionName(){return"permessage-deflate"}offer(){let e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let e=this._deflate[V];this._deflate.close(),this._deflate=null,e&&e(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(e){let r=this._options,n=e.find(s=>!(r.serverNoContextTakeover===!1&&s.server_no_context_takeover||s.server_max_window_bits&&(r.serverMaxWindowBits===!1||typeof r.serverMaxWindowBits=="number"&&r.serverMaxWindowBits>s.server_max_window_bits)||typeof r.clientMaxWindowBits=="number"&&!s.client_max_window_bits));if(!n)throw new Error("None of the extension offers can be accepted");return r.serverNoContextTakeover&&(n.server_no_context_takeover=!0),r.clientNoContextTakeover&&(n.client_no_context_takeover=!0),typeof r.serverMaxWindowBits=="number"&&(n.server_max_window_bits=r.serverMaxWindowBits),typeof r.clientMaxWindowBits=="number"?n.client_max_window_bits=r.clientMaxWindowBits:(n.client_max_window_bits===!0||r.clientMaxWindowBits===!1)&&delete n.client_max_window_bits,n}acceptAsClient(e){let r=e[0];if(this._options.clientNoContextTakeover===!1&&r.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!r.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(r.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&r.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return r}normalizeParams(e){return e.forEach(r=>{Object.keys(r).forEach(n=>{let s=r[n];if(s.length>1)throw new Error(`Parameter "${n}" must have only a single value`);if(s=s[0],n==="client_max_window_bits"){if(s!==!0){let i=+s;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${n}": ${s}`);s=i}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${n}": ${s}`)}else if(n==="server_max_window_bits"){let i=+s;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${n}": ${s}`);s=i}else if(n==="client_no_context_takeover"||n==="server_no_context_takeover"){if(s!==!0)throw new TypeError(`Invalid value for parameter "${n}": ${s}`)}else throw new Error(`Unknown parameter "${n}"`);r[n]=s})}),e}decompress(e,r,n){fe.add(s=>{this._decompress(e,r,(i,o)=>{s(),n(i,o)})})}compress(e,r,n){fe.add(s=>{this._compress(e,r,(i,o)=>{s(),n(i,o)})})}_decompress(e,r,n){let s=this._isServer?"client":"server";if(!this._inflate){let i=`${s}_max_window_bits`,o=typeof this.params[i]!="number"?te.Z_DEFAULT_WINDOWBITS:this.params[i];this._inflate=te.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[de]=this,this._inflate[T]=0,this._inflate[I]=[],this._inflate.on("error",hn),this._inflate.on("data",bt)}this._inflate[V]=n,this._inflate.write(e),r&&this._inflate.write(fn),this._inflate.flush(()=>{let i=this._inflate[j];if(i){this._inflate.close(),this._inflate=null,n(i);return}let o=wt.concat(this._inflate[I],this._inflate[T]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[T]=0,this._inflate[I]=[],r&&this.params[`${s}_no_context_takeover`]&&this._inflate.reset()),n(null,o)})}_compress(e,r,n){let s=this._isServer?"server":"client";if(!this._deflate){let i=`${s}_max_window_bits`,o=typeof this.params[i]!="number"?te.Z_DEFAULT_WINDOWBITS:this.params[i];this._deflate=te.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[T]=0,this._deflate[I]=[],this._deflate.on("data",dn)}this._deflate[V]=n,this._deflate.write(e),this._deflate.flush(te.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let i=wt.concat(this._deflate[I],this._deflate[T]);r&&(i=new ln(i.buffer,i.byteOffset,i.length-4)),this._deflate[V]=null,this._deflate[T]=0,this._deflate[I]=[],r&&this.params[`${s}_no_context_takeover`]&&this._deflate.reset(),n(null,i)})}};Ot.exports=Ie;function dn(t){this[I].push(t),this[T]+=t.length}function bt(t){if(this[T]+=t.length,this[de]._maxPayload<1||this[T]<=this[de]._maxPayload){this[I].push(t);return}this[j]=new RangeError("Max payload size exceeded"),this[j].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[j][vt]=1009,this.removeListener("data",bt),this.reset()}function hn(t){if(this[de]._inflate=null,this[j]){this[V](this[j]);return}t[vt]=1007,this[V](t)}});var G=y((Zs,he)=>{"use strict";var{isUtf8:Ct}=require("buffer"),{hasBlob:un}=C(),pn=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function mn(t){return t>=1e3&&t<=1014&&t!==1004&&t!==1005&&t!==1006||t>=3e3&&t<=4999}function Re(t){let e=t.length,r=0;for(;r<e;)if((t[r]&128)===0)r++;else if((t[r]&224)===192){if(r+1===e||(t[r+1]&192)!==128||(t[r]&254)===192)return!1;r+=2}else if((t[r]&240)===224){if(r+2>=e||(t[r+1]&192)!==128||(t[r+2]&192)!==128||t[r]===224&&(t[r+1]&224)===128||t[r]===237&&(t[r+1]&224)===160)return!1;r+=3}else if((t[r]&248)===240){if(r+3>=e||(t[r+1]&192)!==128||(t[r+2]&192)!==128||(t[r+3]&192)!==128||t[r]===240&&(t[r+1]&240)===128||t[r]===244&&t[r+1]>143||t[r]>244)return!1;r+=4}else return!1;return!0}function _n(t){return un&&typeof t=="object"&&typeof t.arrayBuffer=="function"&&typeof t.type=="string"&&typeof t.stream=="function"&&(t[Symbol.toStringTag]==="Blob"||t[Symbol.toStringTag]==="File")}he.exports={isBlob:_n,isValidStatusCode:mn,isValidUTF8:Re,tokenChars:pn};if(Ct)he.exports.isValidUTF8=function(t){return t.length<24?Re(t):Ct(t)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let t=require("utf-8-validate");he.exports.isValidUTF8=function(e){return e.length<32?Re(e):t(e)}}catch{}});var Me=y((Xs,Ft)=>{"use strict";var{Writable:gn}=require("stream"),Tt=q(),{BINARY_TYPES:Sn,EMPTY_BUFFER:Pt,kStatusCode:yn,kWebSocket:xn}=C(),{concat:Fe,toArrayBuffer:En,unmask:kn}=ee(),{isValidStatusCode:wn,isValidUTF8:Lt}=G(),ue=Buffer[Symbol.species],E=0,Nt=1,It=2,Rt=3,De=4,Ae=5,pe=6,Be=class extends gn{constructor(e={}){super(),this._allowSynchronousEvents=e.allowSynchronousEvents!==void 0?e.allowSynchronousEvents:!0,this._binaryType=e.binaryType||Sn[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxBufferedChunks=e.maxBufferedChunks|0,this._maxFragments=e.maxFragments|0,this._maxPayload=e.maxPayload|0,this._skipUTF8Validation=!!e.skipUTF8Validation,this[xn]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=E}_write(e,r,n){if(this._opcode===8&&this._state==E)return n();if(this._maxBufferedChunks>0&&this._buffers.length>=this._maxBufferedChunks){n(this.createError(RangeError,"Too many buffered chunks",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS"));return}this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(n)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e<this._buffers[0].length){let n=this._buffers[0];return this._buffers[0]=new ue(n.buffer,n.byteOffset+e,n.length-e),new ue(n.buffer,n.byteOffset,e)}let r=Buffer.allocUnsafe(e);do{let n=this._buffers[0],s=r.length-e;e>=n.length?r.set(this._buffers.shift(),s):(r.set(new Uint8Array(n.buffer,n.byteOffset,e),s),this._buffers[0]=new ue(n.buffer,n.byteOffset+e,n.length-e)),e-=n.length}while(e>0);return r}startLoop(e){this._loop=!0;do switch(this._state){case E:this.getInfo(e);break;case Nt:this.getPayloadLength16(e);break;case It:this.getPayloadLength64(e);break;case Rt:this.getMask();break;case De:this.getData(e);break;case Ae:case pe:this._loop=!1;return}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2){this._loop=!1;return}let r=this.consume(2);if((r[0]&48)!==0){let s=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");e(s);return}let n=(r[0]&64)===64;if(n&&!this._extensions[Tt.extensionName]){let s=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(s);return}if(this._fin=(r[0]&128)===128,this._opcode=r[0]&15,this._payloadLength=r[1]&127,this._opcode===0){if(n){let s=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(s);return}if(!this._fragmented){let s=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");e(s);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let s=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(s);return}this._compressed=n}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let s=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");e(s);return}if(n){let s=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(s);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let s=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");e(s);return}}else{let s=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(s);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(r[1]&128)===128,this._isServer){if(!this._masked){let s=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");e(s);return}}else if(this._masked){let s=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");e(s);return}this._payloadLength===126?this._state=Nt:this._payloadLength===127?this._state=It:this.haveLength(e)}getPayloadLength16(e){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e)}getPayloadLength64(e){if(this._bufferedBytes<8){this._loop=!1;return}let r=this.consume(8),n=r.readUInt32BE(0);if(n>Math.pow(2,21)-1){let s=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");e(s);return}this._payloadLength=n*Math.pow(2,32)+r.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){let r=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");e(r);return}this._masked?this._state=Rt:this._state=De}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=De}getData(e){let r=Pt;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength){this._loop=!1;return}r=this.consume(this._payloadLength),this._masked&&(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])!==0&&kn(r,this._mask)}if(this._opcode>7){this.controlMessage(r,e);return}if(this._compressed){this._state=Ae,this.decompress(r,e);return}if(r.length){if(this._maxFragments>0&&this._fragments.length>=this._maxFragments){let n=this.createError(RangeError,"Too many message fragments",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS");e(n);return}this._messageLength=this._totalPayloadLength,this._fragments.push(r)}this.dataMessage(e)}decompress(e,r){this._extensions[Tt.extensionName].decompress(e,this._fin,(s,i)=>{if(s)return r(s);if(i.length){if(this._messageLength+=i.length,this._messageLength>this._maxPayload&&this._maxPayload>0){let o=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");r(o);return}if(this._maxFragments>0&&this._fragments.length>=this._maxFragments){let o=this.createError(RangeError,"Too many message fragments",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS");r(o);return}this._fragments.push(i)}this.dataMessage(r),this._state===E&&this.startLoop(r)})}dataMessage(e){if(!this._fin){this._state=E;return}let r=this._messageLength,n=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let s;this._binaryType==="nodebuffer"?s=Fe(n,r):this._binaryType==="arraybuffer"?s=En(Fe(n,r)):this._binaryType==="blob"?s=new Blob(n):s=n,this._allowSynchronousEvents?(this.emit("message",s,!0),this._state=E):(this._state=pe,setImmediate(()=>{this.emit("message",s,!0),this._state=E,this.startLoop(e)}))}else{let s=Fe(n,r);if(!this._skipUTF8Validation&&!Lt(s)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");e(i);return}this._state===Ae||this._allowSynchronousEvents?(this.emit("message",s,!1),this._state=E):(this._state=pe,setImmediate(()=>{this.emit("message",s,!1),this._state=E,this.startLoop(e)}))}}controlMessage(e,r){if(this._opcode===8){if(e.length===0)this._loop=!1,this.emit("conclude",1005,Pt),this.end();else{let n=e.readUInt16BE(0);if(!wn(n)){let i=this.createError(RangeError,`invalid status code ${n}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");r(i);return}let s=new ue(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!Lt(s)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");r(i);return}this._loop=!1,this.emit("conclude",n,s),this.end()}this._state=E;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",e),this._state=E):(this._state=pe,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",e),this._state=E,this.startLoop(r)}))}createError(e,r,n,s,i){this._loop=!1,this._errored=!0;let o=new e(n?`Invalid WebSocket frame: ${r}`:r);return Error.captureStackTrace(o,this.createError),o.code=i,o[yn]=s,o}};Ft.exports=Be});var $e=y((ei,Bt)=>{"use strict";var{Duplex:Qs}=require("stream"),{randomFillSync:vn}=require("crypto"),{types:{isUint8Array:bn}}=require("util"),Dt=q(),{EMPTY_BUFFER:On,kWebSocket:Cn,NOOP:Tn}=C(),{isBlob:z,isValidStatusCode:Pn}=G(),{mask:At,toBuffer:D}=ee(),k=Symbol("kByteLength"),Ln=Buffer.alloc(4),me=8*1024,A,H=me,v=0,Nn=1,In=2,Ue=class t{constructor(e,r,n){this._extensions=r||{},n&&(this._generateMask=n,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=v,this.onerror=Tn,this[Cn]=void 0}static frame(e,r){let n,s=!1,i=2,o=!1;r.mask&&(n=r.maskBuffer||Ln,r.generateMask?r.generateMask(n):(H===me&&(A===void 0&&(A=Buffer.alloc(me)),vn(A,0,me),H=0),n[0]=A[H++],n[1]=A[H++],n[2]=A[H++],n[3]=A[H++]),o=(n[0]|n[1]|n[2]|n[3])===0,i=6);let c;typeof e=="string"?(!r.mask||o)&&r[k]!==void 0?c=r[k]:(e=Buffer.from(e),c=e.length):(c=e.length,s=r.mask&&r.readOnly&&!o);let l=c;c>=65536?(i+=8,l=127):c>125&&(i+=2,l=126);let a=Buffer.allocUnsafe(s?c+i:i);return a[0]=r.fin?r.opcode|128:r.opcode,r.rsv1&&(a[0]|=64),a[1]=l,l===126?a.writeUInt16BE(c,2):l===127&&(a[2]=a[3]=0,a.writeUIntBE(c,4,6)),r.mask?(a[1]|=128,a[i-4]=n[0],a[i-3]=n[1],a[i-2]=n[2],a[i-1]=n[3],o?[a,e]:s?(At(e,n,a,i,c),[a]):(At(e,n,e,0,c),[a,e])):[a,e]}close(e,r,n,s){let i;if(e===void 0)i=On;else{if(typeof e!="number"||!Pn(e))throw new TypeError("First argument must be a valid error code number");if(r===void 0||!r.length)i=Buffer.allocUnsafe(2),i.writeUInt16BE(e,0);else{let c=Buffer.byteLength(r);if(c>123)throw new RangeError("The message must not be greater than 123 bytes");if(i=Buffer.allocUnsafe(2+c),i.writeUInt16BE(e,0),typeof r=="string")i.write(r,2);else if(bn(r))i.set(r,2);else throw new TypeError("Second argument must be a string or a Uint8Array")}}let o={[k]:i.length,fin:!0,generateMask:this._generateMask,mask:n,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==v?this.enqueue([this.dispatch,i,!1,o,s]):this.sendFrame(t.frame(i,o),s)}ping(e,r,n){let s,i;if(typeof e=="string"?(s=Buffer.byteLength(e),i=!1):z(e)?(s=e.size,i=!1):(e=D(e),s=e.length,i=D.readOnly),s>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[k]:s,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:9,readOnly:i,rsv1:!1};z(e)?this._state!==v?this.enqueue([this.getBlobData,e,!1,o,n]):this.getBlobData(e,!1,o,n):this._state!==v?this.enqueue([this.dispatch,e,!1,o,n]):this.sendFrame(t.frame(e,o),n)}pong(e,r,n){let s,i;if(typeof e=="string"?(s=Buffer.byteLength(e),i=!1):z(e)?(s=e.size,i=!1):(e=D(e),s=e.length,i=D.readOnly),s>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[k]:s,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:10,readOnly:i,rsv1:!1};z(e)?this._state!==v?this.enqueue([this.getBlobData,e,!1,o,n]):this.getBlobData(e,!1,o,n):this._state!==v?this.enqueue([this.dispatch,e,!1,o,n]):this.sendFrame(t.frame(e,o),n)}send(e,r,n){let s=this._extensions[Dt.extensionName],i=r.binary?2:1,o=r.compress,c,l;typeof e=="string"?(c=Buffer.byteLength(e),l=!1):z(e)?(c=e.size,l=!1):(e=D(e),c=e.length,l=D.readOnly),this._firstFragment?(this._firstFragment=!1,o&&s&&s.params[s._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(o=c>=s._threshold),this._compress=o):(o=!1,i=0),r.fin&&(this._firstFragment=!0);let a={[k]:c,fin:r.fin,generateMask:this._generateMask,mask:r.mask,maskBuffer:this._maskBuffer,opcode:i,readOnly:l,rsv1:o};z(e)?this._state!==v?this.enqueue([this.getBlobData,e,this._compress,a,n]):this.getBlobData(e,this._compress,a,n):this._state!==v?this.enqueue([this.dispatch,e,this._compress,a,n]):this.dispatch(e,this._compress,a,n)}getBlobData(e,r,n,s){this._bufferedBytes+=n[k],this._state=In,e.arrayBuffer().then(i=>{if(this._socket.destroyed){let c=new Error("The socket was closed while the blob was being read");process.nextTick(We,this,c,s);return}this._bufferedBytes-=n[k];let o=D(i);r?this.dispatch(o,r,n,s):(this._state=v,this.sendFrame(t.frame(o,n),s),this.dequeue())}).catch(i=>{process.nextTick(Rn,this,i,s)})}dispatch(e,r,n,s){if(!r){this.sendFrame(t.frame(e,n),s);return}let i=this._extensions[Dt.extensionName];this._bufferedBytes+=n[k],this._state=Nn,i.compress(e,n.fin,(o,c)=>{if(this._socket.destroyed){let l=new Error("The socket was closed while data was being compressed");We(this,l,s);return}this._bufferedBytes-=n[k],this._state=v,n.readOnly=!1,this.sendFrame(t.frame(c,n),s),this.dequeue()})}dequeue(){for(;this._state===v&&this._queue.length;){let e=this._queue.shift();this._bufferedBytes-=e[3][k],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][k],this._queue.push(e)}sendFrame(e,r){e.length===2?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],r),this._socket.uncork()):this._socket.write(e[0],r)}};Bt.exports=Ue;function We(t,e,r){typeof r=="function"&&r(e);for(let n=0;n<t._queue.length;n++){let s=t._queue[n],i=s[s.length-1];typeof i=="function"&&i(e)}}function Rn(t,e,r){We(t,e,r),t.onerror(e)}});var zt=y((ti,Gt)=>{"use strict";var{kForOnEventAttribute:re,kListener:Ve}=C(),Mt=Symbol("kCode"),Ut=Symbol("kData"),Wt=Symbol("kError"),$t=Symbol("kMessage"),Vt=Symbol("kReason"),J=Symbol("kTarget"),jt=Symbol("kType"),qt=Symbol("kWasClean"),P=class{constructor(e){this[J]=null,this[jt]=e}get target(){return this[J]}get type(){return this[jt]}};Object.defineProperty(P.prototype,"target",{enumerable:!0});Object.defineProperty(P.prototype,"type",{enumerable:!0});var B=class extends P{constructor(e,r={}){super(e),this[Mt]=r.code===void 0?0:r.code,this[Vt]=r.reason===void 0?"":r.reason,this[qt]=r.wasClean===void 0?!1:r.wasClean}get code(){return this[Mt]}get reason(){return this[Vt]}get wasClean(){return this[qt]}};Object.defineProperty(B.prototype,"code",{enumerable:!0});Object.defineProperty(B.prototype,"reason",{enumerable:!0});Object.defineProperty(B.prototype,"wasClean",{enumerable:!0});var Y=class extends P{constructor(e,r={}){super(e),this[Wt]=r.error===void 0?null:r.error,this[$t]=r.message===void 0?"":r.message}get error(){return this[Wt]}get message(){return this[$t]}};Object.defineProperty(Y.prototype,"error",{enumerable:!0});Object.defineProperty(Y.prototype,"message",{enumerable:!0});var ne=class extends P{constructor(e,r={}){super(e),this[Ut]=r.data===void 0?null:r.data}get data(){return this[Ut]}};Object.defineProperty(ne.prototype,"data",{enumerable:!0});var Fn={addEventListener(t,e,r={}){for(let s of this.listeners(t))if(!r[re]&&s[Ve]===e&&!s[re])return;let n;if(t==="message")n=function(i,o){let c=new ne("message",{data:o?i:i.toString()});c[J]=this,_e(e,this,c)};else if(t==="close")n=function(i,o){let c=new B("close",{code:i,reason:o.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});c[J]=this,_e(e,this,c)};else if(t==="error")n=function(i){let o=new Y("error",{error:i,message:i.message});o[J]=this,_e(e,this,o)};else if(t==="open")n=function(){let i=new P("open");i[J]=this,_e(e,this,i)};else return;n[re]=!!r[re],n[Ve]=e,r.once?this.once(t,n):this.on(t,n)},removeEventListener(t,e){for(let r of this.listeners(t))if(r[Ve]===e&&!r[re]){this.removeListener(t,r);break}}};Gt.exports={CloseEvent:B,ErrorEvent:Y,Event:P,EventTarget:Fn,MessageEvent:ne};function _e(t,e,r){typeof t=="object"&&t.handleEvent?t.handleEvent.call(t,r):t.call(e,r)}});var ge=y((ri,Ht)=>{"use strict";var{tokenChars:se}=G();function b(t,e,r){t[e]===void 0?t[e]=[r]:t[e].push(r)}function Dn(t){let e=Object.create(null),r=Object.create(null),n=!1,s=!1,i=!1,o,c,l=-1,a=-1,f=-1,d=0;for(;d<t.length;d++)if(a=t.charCodeAt(d),o===void 0)if(f===-1&&se[a]===1)l===-1&&(l=d);else if(d!==0&&(a===32||a===9))f===-1&&l!==-1&&(f=d);else if(a===59||a===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let _=t.slice(l,f);a===44?(b(e,_,r),r=Object.create(null)):o=_,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);else if(c===void 0)if(f===-1&&se[a]===1)l===-1&&(l=d);else if(a===32||a===9)f===-1&&l!==-1&&(f=d);else if(a===59||a===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d),b(r,t.slice(l,f),!0),a===44&&(b(e,o,r),r=Object.create(null),o=void 0),l=f=-1}else if(a===61&&l!==-1&&f===-1)c=t.slice(l,d),l=f=-1;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(s){if(se[a]!==1)throw new SyntaxError(`Unexpected character at index ${d}`);l===-1?l=d:n||(n=!0),s=!1}else if(i)if(se[a]===1)l===-1&&(l=d);else if(a===34&&l!==-1)i=!1,f=d;else if(a===92)s=!0;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(a===34&&t.charCodeAt(d-1)===61)i=!0;else if(f===-1&&se[a]===1)l===-1&&(l=d);else if(l!==-1&&(a===32||a===9))f===-1&&(f=d);else if(a===59||a===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let _=t.slice(l,f);n&&(_=_.replace(/\\/g,""),n=!1),b(r,c,_),a===44&&(b(e,o,r),r=Object.create(null),o=void 0),c=void 0,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);if(l===-1||i||a===32||a===9)throw new SyntaxError("Unexpected end of input");f===-1&&(f=d);let u=t.slice(l,f);return o===void 0?b(e,u,r):(c===void 0?b(r,u,!0):n?b(r,c,u.replace(/\\/g,"")):b(r,c,u),b(e,o,r)),e}function An(t){return Object.keys(t).map(e=>{let r=t[e];return Array.isArray(r)||(r=[r]),r.map(n=>[e].concat(Object.keys(n).map(s=>{let i=n[s];return Array.isArray(i)||(i=[i]),i.map(o=>o===!0?s:`${s}=${o}`).join("; ")})).join("; ")).join(", ")}).join(", ")}Ht.exports={format:An,parse:Dn}});var Ee=y((ii,ir)=>{"use strict";var Bn=require("events"),Mn=require("https"),Un=require("http"),Kt=require("net"),Wn=require("tls"),{randomBytes:$n,createHash:Vn}=require("crypto"),{Duplex:ni,Readable:si}=require("stream"),{URL:je}=require("url"),R=q(),jn=Me(),qn=$e(),{isBlob:Gn}=G(),{BINARY_TYPES:Jt,CLOSE_TIMEOUT:zn,EMPTY_BUFFER:Se,GUID:Hn,kForOnEventAttribute:qe,kListener:Jn,kStatusCode:Yn,kWebSocket:S,NOOP:Zt}=C(),{EventTarget:{addEventListener:Kn,removeEventListener:Zn}}=zt(),{format:Xn,parse:Qn}=ge(),{toBuffer:es}=ee(),Xt=Symbol("kAborted"),Ge=[8,13],L=["CONNECTING","OPEN","CLOSING","CLOSED"],ts=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,m=class t extends Bn{constructor(e,r,n){super(),this._binaryType=Jt[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=Se,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=t.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,e!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,r===void 0?r=[]:Array.isArray(r)||(typeof r=="object"&&r!==null?(n=r,r=[]):r=[r]),Qt(this,e,r,n)):(this._autoPong=n.autoPong,this._closeTimeout=n.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(e){Jt.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(e,r,n){let s=new jn({allowSynchronousEvents:n.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxBufferedChunks:n.maxBufferedChunks,maxFragments:n.maxFragments,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation}),i=new qn(e,this._extensions,n.generateMask);this._receiver=s,this._sender=i,this._socket=e,s[S]=this,i[S]=this,e[S]=this,s.on("conclude",ss),s.on("drain",is),s.on("error",os),s.on("message",as),s.on("ping",cs),s.on("pong",ls),i.onerror=fs,e.setTimeout&&e.setTimeout(0),e.setNoDelay&&e.setNoDelay(),r.length>0&&e.unshift(r),e.on("close",rr),e.on("data",xe),e.on("end",nr),e.on("error",sr),this._readyState=t.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[R.extensionName]&&this._extensions[R.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(e,r){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){x(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===t.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=t.CLOSING,this._sender.close(e,r,!this._isServer,n=>{n||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),tr(this)}}pause(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!0,this._socket.pause())}ping(e,r,n){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(n=e,e=r=void 0):typeof r=="function"&&(n=r,r=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){ze(this,e,n);return}r===void 0&&(r=!this._isServer),this._sender.ping(e||Se,r,n)}pong(e,r,n){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(n=e,e=r=void 0):typeof r=="function"&&(n=r,r=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){ze(this,e,n);return}r===void 0&&(r=!this._isServer),this._sender.pong(e||Se,r,n)}resume(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(e,r,n){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof r=="function"&&(n=r,r={}),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){ze(this,e,n);return}let s={binary:typeof e!="string",mask:!this._isServer,compress:!0,fin:!0,...r};this._extensions[R.extensionName]||(s.compress=!1),this._sender.send(e||Se,s,n)}terminate(){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){x(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=t.CLOSING,this._socket.destroy())}}};Object.defineProperty(m,"CONNECTING",{enumerable:!0,value:L.indexOf("CONNECTING")});Object.defineProperty(m.prototype,"CONNECTING",{enumerable:!0,value:L.indexOf("CONNECTING")});Object.defineProperty(m,"OPEN",{enumerable:!0,value:L.indexOf("OPEN")});Object.defineProperty(m.prototype,"OPEN",{enumerable:!0,value:L.indexOf("OPEN")});Object.defineProperty(m,"CLOSING",{enumerable:!0,value:L.indexOf("CLOSING")});Object.defineProperty(m.prototype,"CLOSING",{enumerable:!0,value:L.indexOf("CLOSING")});Object.defineProperty(m,"CLOSED",{enumerable:!0,value:L.indexOf("CLOSED")});Object.defineProperty(m.prototype,"CLOSED",{enumerable:!0,value:L.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(t=>{Object.defineProperty(m.prototype,t,{enumerable:!0})});["open","error","close","message"].forEach(t=>{Object.defineProperty(m.prototype,`on${t}`,{enumerable:!0,get(){for(let e of this.listeners(t))if(e[qe])return e[Jn];return null},set(e){for(let r of this.listeners(t))if(r[qe]){this.removeListener(t,r);break}typeof e=="function"&&this.addEventListener(t,e,{[qe]:!0})}})});m.prototype.addEventListener=Kn;m.prototype.removeEventListener=Zn;ir.exports=m;function Qt(t,e,r,n){let s={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:zn,protocolVersion:Ge[1],maxBufferedChunks:1048576,maxFragments:131072,maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...n,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(t._autoPong=s.autoPong,t._closeTimeout=s.closeTimeout,!Ge.includes(s.protocolVersion))throw new RangeError(`Unsupported protocol version: ${s.protocolVersion} (supported versions: ${Ge.join(", ")})`);let i;if(e instanceof je)i=e;else try{i=new je(e)}catch{throw new SyntaxError(`Invalid URL: ${e}`)}i.protocol==="http:"?i.protocol="ws:":i.protocol==="https:"&&(i.protocol="wss:"),t._url=i.href;let o=i.protocol==="wss:",c=i.protocol==="ws+unix:",l;if(i.protocol!=="ws:"&&!o&&!c?l=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:c&&!i.pathname?l="The URL's pathname is empty":i.hash&&(l="The URL contains a fragment identifier"),l){let h=new SyntaxError(l);if(t._redirects===0)throw h;ye(t,h);return}let a=o?443:80,f=$n(16).toString("base64"),d=o?Mn.request:Un.request,u=new Set,_;if(s.createConnection=s.createConnection||(o?ns:rs),s.defaultPort=s.defaultPort||a,s.port=i.port||a,s.host=i.hostname.startsWith("[")?i.hostname.slice(1,-1):i.hostname,s.headers={...s.headers,"Sec-WebSocket-Version":s.protocolVersion,"Sec-WebSocket-Key":f,Connection:"Upgrade",Upgrade:"websocket"},s.path=i.pathname+i.search,s.timeout=s.handshakeTimeout,s.perMessageDeflate&&(_=new R({...s.perMessageDeflate,isServer:!1,maxPayload:s.maxPayload}),s.headers["Sec-WebSocket-Extensions"]=Xn({[R.extensionName]:_.offer()})),r.length){for(let h of r){if(typeof h!="string"||!ts.test(h)||u.has(h))throw new SyntaxError("An invalid or duplicated subprotocol was specified");u.add(h)}s.headers["Sec-WebSocket-Protocol"]=r.join(",")}if(s.origin&&(s.protocolVersion<13?s.headers["Sec-WebSocket-Origin"]=s.origin:s.headers.Origin=s.origin),(i.username||i.password)&&(s.auth=`${i.username}:${i.password}`),c){let h=s.path.split(":");s.socketPath=h[0],s.path=h[1]}let p;if(s.followRedirects){if(t._redirects===0){t._originalIpc=c,t._originalSecure=o,t._originalHostOrSocketPath=c?s.socketPath:i.host;let h=n&&n.headers;if(n={...n,headers:{}},h)for(let[g,W]of Object.entries(h))n.headers[g.toLowerCase()]=W}else if(t.listenerCount("redirect")===0){let h=c?t._originalIpc?s.socketPath===t._originalHostOrSocketPath:!1:t._originalIpc?!1:i.host===t._originalHostOrSocketPath;(!h||t._originalSecure&&!o)&&(delete s.headers.authorization,delete s.headers.cookie,h||delete s.headers.host,s.auth=void 0)}s.auth&&!n.headers.authorization&&(n.headers.authorization="Basic "+Buffer.from(s.auth).toString("base64")),p=t._req=d(s),t._redirects&&t.emit("redirect",t.url,p)}else p=t._req=d(s);s.timeout&&p.on("timeout",()=>{x(t,p,"Opening handshake has timed out")}),p.on("error",h=>{p===null||p[Xt]||(p=t._req=null,ye(t,h))}),p.on("response",h=>{let g=h.headers.location,W=h.statusCode;if(g&&s.followRedirects&&W>=300&&W<400){if(++t._redirects>s.maxRedirects){x(t,p,"Maximum redirects exceeded");return}p.abort();let X;try{X=new je(g,e)}catch{let $=new SyntaxError(`Invalid URL: ${g}`);ye(t,$);return}Qt(t,X,r,n)}else t.emit("unexpected-response",p,h)||x(t,p,`Unexpected server response: ${h.statusCode}`)}),p.on("upgrade",(h,g,W)=>{if(t.emit("upgrade",h),t.readyState!==m.CONNECTING)return;p=t._req=null;let X=h.headers.upgrade;if(X===void 0||X.toLowerCase()!=="websocket"){x(t,g,"Invalid Upgrade header");return}let et=Vn("sha1").update(f+Hn).digest("base64");if(h.headers["sec-websocket-accept"]!==et){x(t,g,"Invalid Sec-WebSocket-Accept header");return}let $=h.headers["sec-websocket-protocol"],Q;if($!==void 0?u.size?u.has($)||(Q="Server sent an invalid subprotocol"):Q="Server sent a subprotocol but none was requested":u.size&&(Q="Server sent no subprotocol"),Q){x(t,g,Q);return}$&&(t._protocol=$);let tt=h.headers["sec-websocket-extensions"];if(tt!==void 0){if(!_){x(t,g,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let be;try{be=Qn(tt)}catch{x(t,g,"Invalid Sec-WebSocket-Extensions header");return}let rt=Object.keys(be);if(rt.length!==1||rt[0]!==R.extensionName){x(t,g,"Server indicated an extension that was not requested");return}try{_.accept(be[R.extensionName])}catch{x(t,g,"Invalid Sec-WebSocket-Extensions header");return}t._extensions[R.extensionName]=_}t.setSocket(g,W,{allowSynchronousEvents:s.allowSynchronousEvents,generateMask:s.generateMask,maxBufferedChunks:s.maxBufferedChunks,maxFragments:s.maxFragments,maxPayload:s.maxPayload,skipUTF8Validation:s.skipUTF8Validation})}),s.finishRequest?s.finishRequest(p,t):p.end()}function ye(t,e){t._readyState=m.CLOSING,t._errorEmitted=!0,t.emit("error",e),t.emitClose()}function rs(t){return t.path=t.socketPath,Kt.connect(t)}function ns(t){return t.path=void 0,!t.servername&&t.servername!==""&&(t.servername=Kt.isIP(t.host)?"":t.host),Wn.connect(t)}function x(t,e,r){t._readyState=m.CLOSING;let n=new Error(r);Error.captureStackTrace(n,x),e.setHeader?(e[Xt]=!0,e.abort(),e.socket&&!e.socket.destroyed&&e.socket.destroy(),process.nextTick(ye,t,n)):(e.destroy(n),e.once("error",t.emit.bind(t,"error")),e.once("close",t.emitClose.bind(t)))}function ze(t,e,r){if(e){let n=Gn(e)?e.size:es(e).length;t._socket?t._sender._bufferedBytes+=n:t._bufferedAmount+=n}if(r){let n=new Error(`WebSocket is not open: readyState ${t.readyState} (${L[t.readyState]})`);process.nextTick(r,n)}}function ss(t,e){let r=this[S];r._closeFrameReceived=!0,r._closeMessage=e,r._closeCode=t,r._socket[S]!==void 0&&(r._socket.removeListener("data",xe),process.nextTick(er,r._socket),t===1005?r.close():r.close(t,e))}function is(){let t=this[S];t.isPaused||t._socket.resume()}function os(t){let e=this[S];e._socket[S]!==void 0&&(e._socket.removeListener("data",xe),process.nextTick(er,e._socket),e.close(t[Yn])),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t))}function Yt(){this[S].emitClose()}function as(t,e){this[S].emit("message",t,e)}function cs(t){let e=this[S];e._autoPong&&e.pong(t,!this._isServer,Zt),e.emit("ping",t)}function ls(t){this[S].emit("pong",t)}function er(t){t.resume()}function fs(t){let e=this[S];e.readyState!==m.CLOSED&&(e.readyState===m.OPEN&&(e._readyState=m.CLOSING,tr(e)),this._socket.end(),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t)))}function tr(t){t._closeTimer=setTimeout(t._socket.destroy.bind(t._socket),t._closeTimeout)}function rr(){let t=this[S];if(this.removeListener("close",rr),this.removeListener("data",xe),this.removeListener("end",nr),t._readyState=m.CLOSING,!this._readableState.endEmitted&&!t._closeFrameReceived&&!t._receiver._writableState.errorEmitted&&this._readableState.length!==0){let e=this.read(this._readableState.length);t._receiver.write(e)}t._receiver.end(),this[S]=void 0,clearTimeout(t._closeTimer),t._receiver._writableState.finished||t._receiver._writableState.errorEmitted?t.emitClose():(t._receiver.on("error",Yt),t._receiver.on("finish",Yt))}function xe(t){this[S]._receiver.write(t)||this.pause()}function nr(){let t=this[S];t._readyState=m.CLOSING,t._receiver.end(),this.end()}function sr(){let t=this[S];this.removeListener("error",sr),this.on("error",Zt),t&&(t._readyState=m.CLOSING,this.destroy())}});var lr=y((ai,cr)=>{"use strict";var oi=Ee(),{Duplex:ds}=require("stream");function or(t){t.emit("close")}function hs(){!this.destroyed&&this._writableState.finished&&this.destroy()}function ar(t){this.removeListener("error",ar),this.destroy(),this.listenerCount("error")===0&&this.emit("error",t)}function us(t,e){let r=!0,n=new ds({...e,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return t.on("message",function(i,o){let c=!o&&n._readableState.objectMode?i.toString():i;n.push(c)||t.pause()}),t.once("error",function(i){n.destroyed||(r=!1,n.destroy(i))}),t.once("close",function(){n.destroyed||n.push(null)}),n._destroy=function(s,i){if(t.readyState===t.CLOSED){i(s),process.nextTick(or,n);return}let o=!1;t.once("error",function(l){o=!0,i(l)}),t.once("close",function(){o||i(s),process.nextTick(or,n)}),r&&t.terminate()},n._final=function(s){if(t.readyState===t.CONNECTING){t.once("open",function(){n._final(s)});return}t._socket!==null&&(t._socket._writableState.finished?(s(),n._readableState.endEmitted&&n.destroy()):(t._socket.once("finish",function(){s()}),t.close()))},n._read=function(){t.isPaused&&t.resume()},n._write=function(s,i,o){if(t.readyState===t.CONNECTING){t.once("open",function(){n._write(s,i,o)});return}t.send(s,o)},n.on("end",hs),n.on("error",ar),n}cr.exports=us});var He=y((ci,fr)=>{"use strict";var{tokenChars:ps}=G();function ms(t){let e=new Set,r=-1,n=-1,s=0;for(s;s<t.length;s++){let o=t.charCodeAt(s);if(n===-1&&ps[o]===1)r===-1&&(r=s);else if(s!==0&&(o===32||o===9))n===-1&&r!==-1&&(n=s);else if(o===44){if(r===-1)throw new SyntaxError(`Unexpected character at index ${s}`);n===-1&&(n=s);let c=t.slice(r,n);if(e.has(c))throw new SyntaxError(`The "${c}" subprotocol is duplicated`);e.add(c),r=n=-1}else throw new SyntaxError(`Unexpected character at index ${s}`)}if(r===-1||n!==-1)throw new SyntaxError("Unexpected end of input");let i=t.slice(r,s);if(e.has(i))throw new SyntaxError(`The "${i}" subprotocol is duplicated`);return e.add(i),e}fr.exports={parse:ms}});var gr=y((fi,_r)=>{"use strict";var _s=require("events"),ke=require("http"),{Duplex:li}=require("stream"),{createHash:gs}=require("crypto"),dr=ge(),M=q(),Ss=He(),ys=Ee(),{CLOSE_TIMEOUT:xs,GUID:Es,kWebSocket:ks}=C(),ws=/^[+/0-9A-Za-z]{22}==$/,hr=0,ur=1,mr=2,Je=class extends _s{constructor(e,r){if(super(),e={allowSynchronousEvents:!0,autoPong:!0,maxBufferedChunks:1024*1024,maxFragments:128*1024,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:xs,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:ys,...e},e.port==null&&!e.server&&!e.noServer||e.port!=null&&(e.server||e.noServer)||e.server&&e.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(e.port!=null?(this._server=ke.createServer((n,s)=>{let i=ke.STATUS_CODES[426];s.writeHead(426,{"Content-Length":i.length,"Content-Type":"text/plain"}),s.end(i)}),this._server.listen(e.port,e.host,e.backlog,r)):e.server&&(this._server=e.server),this._server){let n=this.emit.bind(this,"connection");this._removeListeners=vs(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(s,i,o)=>{this.handleUpgrade(s,i,o,n)}})}e.perMessageDeflate===!0&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=hr}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(e){if(this._state===mr){e&&this.once("close",()=>{e(new Error("The server is not running"))}),process.nextTick(ie,this);return}if(e&&this.once("close",e),this._state!==ur)if(this._state=ur,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients?this.clients.size?this._shouldEmitClose=!0:process.nextTick(ie,this):process.nextTick(ie,this);else{let r=this._server;this._removeListeners(),this._removeListeners=this._server=null,r.close(()=>{ie(this)})}}shouldHandle(e){if(this.options.path){let r=e.url.indexOf("?");if((r!==-1?e.url.slice(0,r):e.url)!==this.options.path)return!1}return!0}handleUpgrade(e,r,n,s){r.on("error",pr);let i=e.headers["sec-websocket-key"],o=e.headers.upgrade,c=+e.headers["sec-websocket-version"];if(e.method!=="GET"){U(this,e,r,405,"Invalid HTTP method");return}if(o===void 0||o.toLowerCase()!=="websocket"){U(this,e,r,400,"Invalid Upgrade header");return}if(i===void 0||!ws.test(i)){U(this,e,r,400,"Missing or invalid Sec-WebSocket-Key header");return}if(c!==13&&c!==8){U(this,e,r,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(e)){oe(r,400);return}let l=e.headers["sec-websocket-protocol"],a=new Set;if(l!==void 0)try{a=Ss.parse(l)}catch{U(this,e,r,400,"Invalid Sec-WebSocket-Protocol header");return}let f=e.headers["sec-websocket-extensions"],d={};if(this.options.perMessageDeflate&&f!==void 0){let u=new M({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let _=dr.parse(f);_[M.extensionName]&&(u.accept(_[M.extensionName]),d[M.extensionName]=u)}catch{U(this,e,r,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let u={origin:e.headers[`${c===8?"sec-websocket-origin":"origin"}`],secure:!!(e.socket.authorized||e.socket.encrypted),req:e};if(this.options.verifyClient.length===2){this.options.verifyClient(u,(_,p,h,g)=>{if(!_)return oe(r,p||401,h,g);this.completeUpgrade(d,i,a,e,r,n,s)});return}if(!this.options.verifyClient(u))return oe(r,401)}this.completeUpgrade(d,i,a,e,r,n,s)}completeUpgrade(e,r,n,s,i,o,c){if(!i.readable||!i.writable)return i.destroy();if(i[ks])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>hr)return oe(i,503);let a=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${gs("sha1").update(r+Es).digest("base64")}`],f=new this.options.WebSocket(null,void 0,this.options);if(n.size){let d=this.options.handleProtocols?this.options.handleProtocols(n,s):n.values().next().value;d&&(a.push(`Sec-WebSocket-Protocol: ${d}`),f._protocol=d)}if(e[M.extensionName]){let d=e[M.extensionName].params,u=dr.format({[M.extensionName]:[d]});a.push(`Sec-WebSocket-Extensions: ${u}`),f._extensions=e}this.emit("headers",a,s),i.write(a.concat(`\r
|
|
3
|
-
`).join(`\r
|
|
4
|
-
`)),i.removeListener("error",pr),f.setSocket(i,o,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxBufferedChunks:this.options.maxBufferedChunks,maxFragments:this.options.maxFragments,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(f),f.on("close",()=>{this.clients.delete(f),this._shouldEmitClose&&!this.clients.size&&process.nextTick(ie,this)})),c(f,s)}};_r.exports=Je;function vs(t,e){for(let r of Object.keys(e))t.on(r,e[r]);return function(){for(let n of Object.keys(e))t.removeListener(n,e[n])}}function ie(t){t._state=mr,t.emit("close")}function pr(){this.destroy()}function oe(t,e,r,n){r=r||ke.STATUS_CODES[e],n={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(r),...n},t.once("finish",t.destroy),t.end(`HTTP/1.1 ${e} ${ke.STATUS_CODES[e]}\r
|
|
5
|
-
`+Object.keys(n).map(s=>`${s}: ${n[s]}`).join(`\r
|
|
6
|
-
`)+`\r
|
|
7
|
-
\r
|
|
8
|
-
`+r)}function U(t,e,r,n,s,i){if(t.listenerCount("wsClientError")){let o=new Error(s);Error.captureStackTrace(o,U),t.emit("wsClientError",o,r,e)}else oe(r,n,s,i)}});var As={};Yr(As,{startNvimSidecar:()=>Ur});module.exports=Kr(As);var Mr=require("node:readline");var F="PI_X_IDE_LOCK_DIR",st="x-pi-x-ide-authorization",it=".lock";var ht=require("node:os"),O=require("node:path");var ct=require("node:fs"),lt=require("node:os"),ft=require("node:path");var Zr=["string","number","boolean"];function ot(t){return Zr.some(e=>typeof t===e)}var Xr="config.json",Qr=new WeakSet;function en(t=(0,lt.homedir)()){return(0,ft.resolve)(t,".pi",Xr)}function tn(t=en()){let e;try{e=JSON.parse((0,ct.readFileSync)(t,"utf8"))}catch{return{}}return!at(e)||!at(e.env)?{}:Object.fromEntries(Object.entries(e.env).filter(r=>{let[n,s]=r;return n.length>0&&ot(s)}).map(([r,n])=>[r,String(n)]))}function dt(t=process.env,e={}){if(t!==process.env&&!e.configPath)return t;let r=tn(e.configPath);if(Object.keys(r).length===0)return t;let n={...r,...t};return t===process.env&&Qr.add(n),n}function at(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Ce(t=process.env){let r=dt(t)[F]?.trim();return r?(0,O.resolve)(r):(0,O.resolve)((0,ht.homedir)(),".pi","pi-x-ide","lock")}function ut(t,e,r){let n=e??r;if(!n)return t;let s=(0,O.relative)(n,t);return!s||s.startsWith("..")||(0,O.isAbsolute)(s)?t:s.split(O.sep).join("/")}function rn(t){return{startLine:t.selection.start.line+1,endLine:t.selection.end.line+1}}function nn(t,e="comma"){let{startLine:r,endLine:n}=rn(t);return r===n?`#L${r}`:e==="dash"?`#L${r}-L${n}`:`#L${r},${n}`}function pt(t,e={}){let r=ut(t.filePath,t.workspaceFolder,e.cwd),n=t.ranges[0];return n?`@${r}${nn(n,e.format)}`:`@${r}`}var Or=require("node:http");var bs=N(lr(),1),Os=N(ge(),1),Cs=N(q(),1),Ts=N(Me(),1),Ps=N($e(),1),Ls=N(He(),1),Sr=N(Ee(),1),Ye=N(gr(),1);var yr=Sr.default;function K(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Z(t){return typeof t=="string"}function ae(t){return typeof t=="number"&&Number.isFinite(t)}function Er(t){return t==="vscode"||t==="zed"||t==="nvim"||t==="unknown"}function xr(t){return K(t)&&ae(t.line)&&ae(t.character)&&t.line>=0&&t.character>=0}function Ns(t){return!K(t)||!Z(t.text)||!K(t.selection)?!1:xr(t.selection.start)&&xr(t.selection.end)}function Ke(t){return K(t)?Er(t.source)&&Z(t.filePath)&&(t.workspaceFolder===void 0||Z(t.workspaceFolder))&&Array.isArray(t.ranges)&&t.ranges.every(Ns)&&(t.receivedAt===void 0||ae(t.receivedAt)):!1}function kr(t){return K(t)&&Er(t.source)&&t.reason==="no-active-editor"&&(t.receivedAt===void 0||ae(t.receivedAt))}function wr(t){return Ke(t)&&Z(t.rangeText)}function vr(t){return K(t)&&t.jsonrpc==="2.0"&&(Z(t.id)||ae(t.id))&&Z(t.method)}var we=require("node:buffer");function br(t){return Array.isArray(t)?we.Buffer.concat(t).toString("utf8"):we.Buffer.isBuffer(t)?t.toString("utf8"):we.Buffer.from(t).toString("utf8")}var ve=class{constructor(e,r,n){this.authToken=e;this.serverInfo=r;this.getInitialSelection=n}authToken;serverInfo;getInitialSelection;httpServer;wss;sockets=new Set;get port(){let e=this.httpServer?.address();return!e||typeof e=="string"?0:e.port}get clientCount(){return this.sockets.size}async start(){return this.httpServer=(0,Or.createServer)(),this.wss=new Ye.default({server:this.httpServer,verifyClient:({req:e},r)=>{let n=e.headers[st],s=Array.isArray(n)?n[0]:n;r(s===this.authToken,s===this.authToken?void 0:401,"Unauthorized")}}),this.wss.on("connection",e=>{this.sockets.add(e),e.on("close",()=>this.sockets.delete(e)),e.on("error",()=>this.sockets.delete(e)),e.on("message",r=>this.handleMessage(e,br(r)))}),await new Promise((e,r)=>{this.httpServer.once("error",r),this.httpServer.listen(0,"127.0.0.1",()=>{this.httpServer.off("error",r),e()})}),this.port}broadcast(e){let r=JSON.stringify(e);for(let n of this.sockets)n.readyState===yr.OPEN&&n.send(r)}async stop(){for(let e of this.sockets)e.close();this.sockets.clear(),await Promise.all([new Promise(e=>this.wss?.close(()=>e())??e()),new Promise(e=>this.httpServer?.close(()=>e())??e())])}handleMessage(e,r){let n;try{n=JSON.parse(r)}catch{return}if(!vr(n)||n.method!=="initialize")return;let s=this.serverInfo.ide??"vscode",i={protocolVersion:1,server:{name:this.serverInfo.name,version:this.serverInfo.version,ide:s}};e.send(JSON.stringify({jsonrpc:"2.0",id:n.id,result:i}));let o=this.getInitialSelection?.();e.send(JSON.stringify({jsonrpc:"2.0",method:o?"selection_changed":"selection_cleared",params:o?{...o,receivedAt:Date.now()}:{source:s,reason:"no-active-editor",receivedAt:Date.now()}}))}};var Cr=require("node:crypto"),w=require("node:fs/promises"),Tr=require("node:path");function Pr(){return(0,Cr.randomBytes)(32).toString("hex")}function Lr(t,e,r=process.pid){return(0,Tr.join)(Ce(),`${t}-${r}-${e}${it}`)}function Nr(t){let e=(t.now??new Date).toISOString();return{version:1,ide:t.ide,name:t.name,transport:"ws",host:"127.0.0.1",port:t.port,authToken:t.authToken,workspaceFolders:t.workspaceFolders,pid:t.pid??process.pid,createdAt:e,updatedAt:e}}async function Ze(t,e){let r=Ce();await(0,w.mkdir)(r,{recursive:!0,mode:448}),await(0,w.chmod)(r,448).catch(()=>{});let n=`${t}.${process.pid}.${Date.now()}.tmp`;await(0,w.writeFile)(n,`${JSON.stringify(e,null,2)}
|
|
9
|
-
`,{encoding:"utf8",mode:384}),await(0,w.chmod)(n,384).catch(()=>{}),await(0,w.rename)(n,t),await(0,w.chmod)(t,384).catch(()=>{})}async function Ir(t){t&&await(0,w.rm)(t,{force:!0}).catch(()=>{})}function Rr(t,e,r=new Date){return{...t,workspaceFolders:e,updatedAt:r.toISOString()}}function Fr(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Dr(t){return Array.isArray(t)&&t.every(e=>typeof e=="string")}function Xe(t){if(!Fr(t))return;let e=t.workspaceFolders,r=t.name,n=t.lockDir;if(!(e!==void 0&&!Dr(e))&&!(r!==void 0&&typeof r!="string")&&!(n!==void 0&&typeof n!="string"))return{workspaceFolders:e,name:r,lockDir:n}}function Ar(t){if(!(!Fr(t)||typeof t.type!="string"))switch(t.type){case"selection_changed":return Ke(t.snapshot)?{type:"selection_changed",snapshot:t.snapshot}:void 0;case"selection_cleared":{let e={source:"nvim",reason:t.reason??"no-active-editor"};return kr(e)?{type:"selection_cleared",reason:e.reason}:void 0}case"at_mentioned":{let e=t.snapshot;if(!wr(e))return;let r=typeof t.rangeText=="string"?t.rangeText:e.rangeText;return{type:"at_mentioned",snapshot:e,rangeText:r}}case"workspace_changed":return Dr(t.workspaceFolders)?{type:"workspace_changed",workspaceFolders:t.workspaceFolders}:void 0;case"shutdown":return{type:"shutdown"};default:return}}function Qe(t){try{return JSON.parse(t)}catch{return}}async function Ur(t={}){let e=process.env[F];t.lockDir&&(process.env[F]=t.lockDir);let r={workspaceFolders:$r(t.workspaceFolders),stopped:!1},n=Pr(),s=new ve(n,{name:t.name??"Neovim",ide:"nvim"},()=>r.latestSelection),i=await s.start();r.lockFilePath=Lr("nvim",i),r.lockFile=Nr({ide:"nvim",name:t.name??"Neovim",port:i,authToken:n,workspaceFolders:r.workspaceFolders}),await Ze(r.lockFilePath,r.lockFile),(t.stdout??process.stdout).write(JSON.stringify({type:"ready",port:i,lockFilePath:r.lockFilePath})+`
|
|
10
|
-
`);let c=async()=>{r.stopped||(r.stopped=!0,await Ir(r.lockFilePath),await s.stop(),t.lockDir&&(e===void 0?delete process.env[F]:process.env[F]=e))},l=t.stdin??process.stdin,a=t.stderr??process.stderr,f=(0,Mr.createInterface)({input:l});f.on("line",u=>{let _=u.trim();if(!_)return;let p=Qe(_),h=Xe(p);if(h&&!("type"in p)){Wr(r,h,a);return}let g=Ar(p);if(!g){a.write(`pi-x-ide nvim sidecar: ignored malformed message: ${_}
|
|
11
|
-
`);return}Rs(r,s,g,a,c)}),f.on("close",()=>{c()});let d=()=>{c()};return process.once("SIGINT",d),process.once("SIGTERM",d),process.once("beforeExit",d),{server:s,lockFilePath:r.lockFilePath,stop:c}}async function Wr(t,e,r){if(e.workspaceFolders&&(t.workspaceFolders=$r(e.workspaceFolders)),!(!t.lockFilePath||!t.lockFile)){t.lockFile=Rr(t.lockFile,t.workspaceFolders);try{await Ze(t.lockFilePath,t.lockFile)}catch(n){r.write(`pi-x-ide nvim sidecar: failed to refresh lock file: ${Vr(n)}
|
|
12
|
-
`)}}}async function Rs(t,e,r,n,s){switch(r.type){case"selection_changed":{let i=Br(r.snapshot);t.latestSelection=i,e.broadcast({jsonrpc:"2.0",method:"selection_changed",params:{...i,receivedAt:i.receivedAt??Date.now()}});return}case"selection_cleared":t.latestSelection=void 0,e.broadcast({jsonrpc:"2.0",method:"selection_cleared",params:{source:"nvim",reason:r.reason??"no-active-editor",receivedAt:Date.now()}});return;case"at_mentioned":{let i=Br(r.snapshot);t.latestSelection=i;let o=r.rangeText||pt(i);e.broadcast({jsonrpc:"2.0",method:"at_mentioned",params:{...i,rangeText:o,receivedAt:i.receivedAt??Date.now()}});return}case"workspace_changed":await Wr(t,{workspaceFolders:r.workspaceFolders},n);return;case"shutdown":await s();return}}function Br(t){return{...t,source:"nvim"}}function $r(t){let e=t?.filter(r=>r.length>0)??[];return e.length>0?e:[process.cwd()]}function Vr(t){return t instanceof Error?t.message:String(t)}function Fs(t){let e={};for(let r=0;r<t.length;r+=1){let n=t[r];if(n==="--help"||n==="-h")return"help";if(n==="--name")e.name=t[++r];else if(n==="--lock-dir")e.lockDir=t[++r];else if(n==="--workspace-folder")e.workspaceFolders=[...e.workspaceFolders??[],t[++r]].filter(Boolean);else if(n==="--workspace-folders"){let s=t[++r],i=Qe(s??""),o=Xe({workspaceFolders:i});o?.workspaceFolders&&(e.workspaceFolders=o.workspaceFolders)}}return e}function Ds(){process.stdout.write(`Usage: pi-x-ide-nvim-sidecar [options]
|
|
13
|
-
|
|
14
|
-
Options:
|
|
15
|
-
--workspace-folder <path> Add a workspace folder. May be repeated.
|
|
16
|
-
--workspace-folders <json> JSON array of workspace folders.
|
|
17
|
-
--lock-dir <path> Override PI_X_IDE_LOCK_DIR for tests.
|
|
18
|
-
--name <name> Display name reported to Pi.
|
|
19
|
-
--help Show this help.
|
|
20
|
-
`)}if(require.main===module){let t=Fs(process.argv.slice(2));t==="help"?Ds():Ur(t).catch(e=>{process.stderr.write(`pi-x-ide nvim sidecar: ${Vr(e)}
|
|
21
|
-
`),process.exitCode=1})}0&&(module.exports={startNvimSidecar});
|
package/nvim/doc/pi-x-ide.txt
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
*pi-x-ide.txt* Neovim support for Pi x IDE
|
|
2
|
-
|
|
3
|
-
===============================================================================
|
|
4
|
-
CONTENTS *pi-x-ide*
|
|
5
|
-
|
|
6
|
-
1. Setup |pi-x-ide-setup|
|
|
7
|
-
2. Commands |pi-x-ide-commands|
|
|
8
|
-
3. Options |pi-x-ide-options|
|
|
9
|
-
4. Troubleshooting |pi-x-ide-troubleshooting|
|
|
10
|
-
|
|
11
|
-
===============================================================================
|
|
12
|
-
SETUP *pi-x-ide-setup*
|
|
13
|
-
|
|
14
|
-
With lazy.nvim:
|
|
15
|
-
>
|
|
16
|
-
{
|
|
17
|
-
"balaenis/pi-x-ide",
|
|
18
|
-
init = function()
|
|
19
|
-
vim.opt.rtp:prepend(vim.fn.stdpath("data") .. "/lazy/pi-x-ide/nvim")
|
|
20
|
-
end,
|
|
21
|
-
config = function()
|
|
22
|
-
require("pi_x_ide").setup({
|
|
23
|
-
keymap = "<leader>pa",
|
|
24
|
-
})
|
|
25
|
-
end,
|
|
26
|
-
}
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
Note: The `init` block manually adds the `nvim/` subdirectory to the runtime
|
|
30
|
-
path. This avoids a Lua module resolution issue with lazy.nvim's `rtp` option
|
|
31
|
-
on some versions.
|
|
32
|
-
|
|
33
|
-
With native packages, clone the repository into a `pack/*/start` directory and
|
|
34
|
-
add the `nvim` subdirectory to your runtime path before setup:
|
|
35
|
-
>
|
|
36
|
-
set runtimepath+=/path/to/pi-x-ide/nvim
|
|
37
|
-
lua require("pi_x_ide").setup({ keymap = "<leader>pa" })
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
The plugin starts a bundled Node.js sidecar. The sidecar writes a lock file to
|
|
41
|
-
`~/.pi/pi-x-ide/`, and Pi connects through the same `/ide` flow used by VS Code.
|
|
42
|
-
Pi may run in any terminal whose current directory matches the Neovim workspace.
|
|
43
|
-
|
|
44
|
-
===============================================================================
|
|
45
|
-
COMMANDS *pi-x-ide-commands*
|
|
46
|
-
|
|
47
|
-
:PiXIdeStart
|
|
48
|
-
Start the Neovim sidecar.
|
|
49
|
-
|
|
50
|
-
:PiXIdeStop
|
|
51
|
-
Stop the Neovim sidecar and remove its lock file.
|
|
52
|
-
|
|
53
|
-
:PiXIdeStatus
|
|
54
|
-
Show whether the sidecar is running.
|
|
55
|
-
|
|
56
|
-
:PiXIdeAttach
|
|
57
|
-
Attach the current file or selection to connected Pi clients. In Pi this
|
|
58
|
-
inserts an `@relative/path#Lx,y` reference, matching the VS Code attach flow.
|
|
59
|
-
|
|
60
|
-
===============================================================================
|
|
61
|
-
OPTIONS *pi-x-ide-options*
|
|
62
|
-
|
|
63
|
-
Pass options to `require("pi_x_ide").setup({ ... })`.
|
|
64
|
-
|
|
65
|
-
`enabled` (boolean, default true)
|
|
66
|
-
Start the sidecar during setup.
|
|
67
|
-
|
|
68
|
-
`sidecar_cmd` (string[]|nil)
|
|
69
|
-
Command used to start the sidecar. Defaults to:
|
|
70
|
-
`node <plugin-root>/bin/pi-x-ide-nvim-sidecar.cjs`.
|
|
71
|
-
|
|
72
|
-
`debounce_ms` (number, default 150)
|
|
73
|
-
Delay for high-frequency cursor and text-change updates.
|
|
74
|
-
|
|
75
|
-
`range_format` ("comma"|"dash", default "comma")
|
|
76
|
-
Format for manual attach references: `#L10,20` or `#L10-L20`.
|
|
77
|
-
|
|
78
|
-
`keymap` (string|nil)
|
|
79
|
-
Optional normal/visual mode mapping for `:PiXIdeAttach` behavior.
|
|
80
|
-
|
|
81
|
-
`workspace_folders` (string[]|nil)
|
|
82
|
-
Explicit workspace folder list. Defaults to current working directory plus
|
|
83
|
-
active LSP workspace folders when available.
|
|
84
|
-
|
|
85
|
-
===============================================================================
|
|
86
|
-
TROUBLESHOOTING *pi-x-ide-troubleshooting*
|
|
87
|
-
|
|
88
|
-
No `nvim-*.lock` file appears under `~/.pi/pi-x-ide/`:
|
|
89
|
-
Run `:PiXIdeStatus`, confirm Node.js is on PATH, or set `sidecar_cmd` to an
|
|
90
|
-
absolute Node command.
|
|
91
|
-
|
|
92
|
-
Pi shows no IDE connection:
|
|
93
|
-
Start Pi in the same project directory and run `/ide auto`. If the project
|
|
94
|
-
layout is unusual, run `/ide` and choose the Neovim connection manually.
|
|
95
|
-
|
|
96
|
-
The keymap does not work:
|
|
97
|
-
Choose a different `keymap` value in setup. The plugin does not install a
|
|
98
|
-
default keymap to avoid conflicts with existing Neovim configs.
|
|
99
|
-
|
|
100
|
-
Selection is not attached:
|
|
101
|
-
Use visual mode and invoke the configured keymap or `:PiXIdeAttach`. The
|
|
102
|
-
plugin sends file context for normal cursor movement and selection context
|
|
103
|
-
for active or recently completed visual selections.
|
|
104
|
-
|
|
105
|
-
module 'pi_x_ide' not found with lazy.nvim:
|
|
106
|
-
Some lazy.nvim versions fail to update Lua's package.path when `rtp` is
|
|
107
|
-
used. Replace `rtp = "nvim"` with an `init` block that prepends the path:
|
|
108
|
-
>
|
|
109
|
-
init = function()
|
|
110
|
-
vim.opt.rtp:prepend(vim.fn.stdpath("data") .. "/lazy/pi-x-ide/nvim")
|
|
111
|
-
end,
|
|
112
|
-
<
|
|
@@ -1,442 +0,0 @@
|
|
|
1
|
-
local M = {}
|
|
2
|
-
|
|
3
|
-
local state = {
|
|
4
|
-
config = nil,
|
|
5
|
-
job_id = nil,
|
|
6
|
-
timer = nil,
|
|
7
|
-
augroup = nil,
|
|
8
|
-
latest_snapshot = nil,
|
|
9
|
-
visual_mark_valid = false,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
local defaults = {
|
|
13
|
-
enabled = true,
|
|
14
|
-
sidecar_cmd = nil,
|
|
15
|
-
debounce_ms = 150,
|
|
16
|
-
range_format = "comma",
|
|
17
|
-
keymap = nil,
|
|
18
|
-
workspace_folders = nil,
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
local function notify(message, level)
|
|
22
|
-
vim.notify("Pi x IDE: " .. message, level or vim.log.levels.INFO)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
local function plugin_root()
|
|
26
|
-
local source = debug.getinfo(1, "S").source
|
|
27
|
-
if source:sub(1, 1) == "@" then
|
|
28
|
-
source = source:sub(2)
|
|
29
|
-
end
|
|
30
|
-
return vim.fn.fnamemodify(source, ":p:h:h:h")
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
local function default_sidecar_cmd()
|
|
34
|
-
return { "node", plugin_root() .. "/bin/pi-x-ide-nvim-sidecar.cjs" }
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
local function encode(value)
|
|
38
|
-
return vim.json and vim.json.encode(value) or vim.fn.json_encode(value)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
local function send(value)
|
|
42
|
-
if not state.job_id then
|
|
43
|
-
return false
|
|
44
|
-
end
|
|
45
|
-
local ok = vim.fn.chansend(state.job_id, encode(value) .. "\n")
|
|
46
|
-
return ok == 1
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
local function normalize_config(opts)
|
|
50
|
-
local config = vim.tbl_deep_extend("force", defaults, opts or {})
|
|
51
|
-
if config.range_format ~= "dash" then
|
|
52
|
-
config.range_format = "comma"
|
|
53
|
-
end
|
|
54
|
-
return config
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
local function workspace_folders()
|
|
58
|
-
local configured = state.config and state.config.workspace_folders
|
|
59
|
-
if type(configured) == "table" and #configured > 0 then
|
|
60
|
-
return configured
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
local folders = { vim.fn.getcwd() }
|
|
64
|
-
for _, client in pairs(vim.lsp.get_clients and vim.lsp.get_clients() or {}) do
|
|
65
|
-
for _, folder in ipairs(client.workspace_folders or {}) do
|
|
66
|
-
if folder.name and folder.name ~= "" then
|
|
67
|
-
table.insert(folders, folder.name)
|
|
68
|
-
elseif folder.uri then
|
|
69
|
-
local path = vim.uri_to_fname(folder.uri)
|
|
70
|
-
if path and path ~= "" then
|
|
71
|
-
table.insert(folders, path)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
local seen = {}
|
|
78
|
-
local result = {}
|
|
79
|
-
for _, folder in ipairs(folders) do
|
|
80
|
-
local normalized = vim.fn.fnamemodify(folder, ":p"):gsub("/$", "")
|
|
81
|
-
if normalized ~= "" and not seen[normalized] then
|
|
82
|
-
seen[normalized] = true
|
|
83
|
-
table.insert(result, normalized)
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
return result
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
local function is_path_inside(parent, child)
|
|
90
|
-
parent = vim.fn.fnamemodify(parent, ":p"):gsub("/$", "")
|
|
91
|
-
child = vim.fn.fnamemodify(child, ":p")
|
|
92
|
-
if child:gsub("/$", "") == parent then
|
|
93
|
-
return true
|
|
94
|
-
end
|
|
95
|
-
return child:sub(1, #parent + 1) == parent .. "/"
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
local function best_workspace(file_path)
|
|
99
|
-
local best = nil
|
|
100
|
-
for _, folder in ipairs(workspace_folders()) do
|
|
101
|
-
if is_path_inside(folder, file_path) and (not best or #folder > #best) then
|
|
102
|
-
best = folder
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
return best or workspace_folders()[1]
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
local function byte_to_utf16(line, byte_col)
|
|
109
|
-
return vim.str_utfindex(line or "", "utf-16", math.max(0, byte_col), false)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
local function byte_after_char(line, byte_col)
|
|
113
|
-
line = line or ""
|
|
114
|
-
if byte_col >= #line then
|
|
115
|
-
return #line
|
|
116
|
-
end
|
|
117
|
-
local utf16 = byte_to_utf16(line, byte_col)
|
|
118
|
-
return math.min(#line, vim.str_byteindex(line, "utf-16", utf16 + 1, false))
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
local function compare_positions(a, b)
|
|
122
|
-
if a.line ~= b.line then
|
|
123
|
-
return a.line < b.line
|
|
124
|
-
end
|
|
125
|
-
return a.col <= b.col
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
local function sorted_positions(a, b)
|
|
129
|
-
if compare_positions(a, b) then
|
|
130
|
-
return a, b
|
|
131
|
-
end
|
|
132
|
-
return b, a
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
local function get_lines(buf, start_row, end_row)
|
|
136
|
-
return vim.api.nvim_buf_get_lines(buf, start_row, end_row + 1, false)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
local function text_from_range(buf, start_row, start_col, end_row, end_col)
|
|
140
|
-
return table.concat(vim.api.nvim_buf_get_text(buf, start_row, start_col, end_row, end_col, {}), "\n")
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
local function range_from_bytes(buf, start_row, start_col, end_row, end_col)
|
|
144
|
-
local lines = get_lines(buf, start_row, end_row)
|
|
145
|
-
local start_line = lines[1] or ""
|
|
146
|
-
local end_line = lines[#lines] or ""
|
|
147
|
-
return {
|
|
148
|
-
text = text_from_range(buf, start_row, start_col, end_row, end_col),
|
|
149
|
-
selection = {
|
|
150
|
-
start = { line = start_row, character = byte_to_utf16(start_line, start_col) },
|
|
151
|
-
["end"] = { line = end_row, character = byte_to_utf16(end_line, end_col) },
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
local function pos_from_getpos(pos)
|
|
157
|
-
return { line = math.max(0, pos[2] - 1), col = math.max(0, pos[3] - 1), bufnr = pos[1] }
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
local function active_visual_range(buf, mode)
|
|
161
|
-
local start_pos = pos_from_getpos(vim.fn.getpos("v"))
|
|
162
|
-
local end_pos = pos_from_getpos(vim.fn.getpos("."))
|
|
163
|
-
if start_pos.bufnr ~= 0 and start_pos.bufnr ~= buf then
|
|
164
|
-
return {}
|
|
165
|
-
end
|
|
166
|
-
if end_pos.bufnr ~= 0 and end_pos.bufnr ~= buf then
|
|
167
|
-
return {}
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
start_pos, end_pos = sorted_positions(start_pos, end_pos)
|
|
171
|
-
|
|
172
|
-
if mode == "V" then
|
|
173
|
-
local lines = get_lines(buf, start_pos.line, end_pos.line)
|
|
174
|
-
return { range_from_bytes(buf, start_pos.line, 0, end_pos.line, #(lines[#lines] or "")) }
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
if mode == "\022" then
|
|
178
|
-
local start_col = math.min(start_pos.col, end_pos.col)
|
|
179
|
-
local end_col = math.max(start_pos.col, end_pos.col)
|
|
180
|
-
local ranges = {}
|
|
181
|
-
local lines = get_lines(buf, start_pos.line, end_pos.line)
|
|
182
|
-
for offset, line in ipairs(lines) do
|
|
183
|
-
local row = start_pos.line + offset - 1
|
|
184
|
-
local col_start = math.min(start_col, #line)
|
|
185
|
-
local col_end = byte_after_char(line, math.min(end_col, #line))
|
|
186
|
-
if col_start < col_end then
|
|
187
|
-
table.insert(ranges, range_from_bytes(buf, row, col_start, row, col_end))
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
return ranges
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
local end_line = get_lines(buf, end_pos.line, end_pos.line)[1] or ""
|
|
194
|
-
return { range_from_bytes(buf, start_pos.line, start_pos.col, end_pos.line, byte_after_char(end_line, end_pos.col)) }
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
local function marked_visual_range(buf)
|
|
198
|
-
if not state.visual_mark_valid then
|
|
199
|
-
return {}
|
|
200
|
-
end
|
|
201
|
-
local start_mark = vim.api.nvim_buf_get_mark(buf, "<")
|
|
202
|
-
local end_mark = vim.api.nvim_buf_get_mark(buf, ">")
|
|
203
|
-
if start_mark[1] == 0 or end_mark[1] == 0 then
|
|
204
|
-
return {}
|
|
205
|
-
end
|
|
206
|
-
local start_pos = { line = start_mark[1] - 1, col = start_mark[2], bufnr = buf }
|
|
207
|
-
local end_pos = { line = end_mark[1] - 1, col = end_mark[2], bufnr = buf }
|
|
208
|
-
start_pos, end_pos = sorted_positions(start_pos, end_pos)
|
|
209
|
-
local end_line = get_lines(buf, end_pos.line, end_pos.line)[1] or ""
|
|
210
|
-
return { range_from_bytes(buf, start_pos.line, start_pos.col, end_pos.line, byte_after_char(end_line, end_pos.col)) }
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
function M.snapshot(opts)
|
|
214
|
-
opts = opts or {}
|
|
215
|
-
local buf = vim.api.nvim_get_current_buf()
|
|
216
|
-
if vim.bo[buf].buftype ~= "" then
|
|
217
|
-
return state.latest_snapshot
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
local file_path = vim.api.nvim_buf_get_name(buf)
|
|
221
|
-
if file_path == "" then
|
|
222
|
-
return nil
|
|
223
|
-
end
|
|
224
|
-
file_path = vim.fn.fnamemodify(file_path, ":p")
|
|
225
|
-
|
|
226
|
-
local mode = vim.fn.mode()
|
|
227
|
-
local ranges = {}
|
|
228
|
-
if mode == "v" or mode == "V" or mode == "\022" then
|
|
229
|
-
ranges = active_visual_range(buf, mode)
|
|
230
|
-
elseif opts.prefer_marks then
|
|
231
|
-
ranges = marked_visual_range(buf)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
local snapshot = {
|
|
235
|
-
source = "nvim",
|
|
236
|
-
filePath = file_path,
|
|
237
|
-
workspaceFolder = best_workspace(file_path),
|
|
238
|
-
ranges = ranges,
|
|
239
|
-
}
|
|
240
|
-
state.latest_snapshot = snapshot
|
|
241
|
-
return snapshot
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
local function relative_path(snapshot)
|
|
245
|
-
local base = snapshot.workspaceFolder or vim.fn.getcwd()
|
|
246
|
-
local rel = vim.fn.fnamemodify(snapshot.filePath, ":p")
|
|
247
|
-
if vim.fs and vim.fs.relpath then
|
|
248
|
-
local ok, value = pcall(vim.fs.relpath, base, snapshot.filePath)
|
|
249
|
-
if ok and value and value ~= "" then
|
|
250
|
-
return value
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
local prefix = vim.fn.fnamemodify(base, ":p"):gsub("/$", "") .. "/"
|
|
254
|
-
if rel:sub(1, #prefix) == prefix then
|
|
255
|
-
return rel:sub(#prefix + 1)
|
|
256
|
-
end
|
|
257
|
-
return snapshot.filePath
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
local function line_span(range)
|
|
261
|
-
local start_line = range.selection.start.line + 1
|
|
262
|
-
local end_line = range.selection["end"].line + 1
|
|
263
|
-
if start_line == end_line then
|
|
264
|
-
return "#L" .. start_line
|
|
265
|
-
end
|
|
266
|
-
if state.config and state.config.range_format == "dash" then
|
|
267
|
-
return "#L" .. start_line .. "-L" .. end_line
|
|
268
|
-
end
|
|
269
|
-
return "#L" .. start_line .. "," .. end_line
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
function M.format_range_mention(snapshot)
|
|
273
|
-
local rel = relative_path(snapshot)
|
|
274
|
-
if not snapshot.ranges or #snapshot.ranges == 0 then
|
|
275
|
-
return "@" .. rel
|
|
276
|
-
end
|
|
277
|
-
return "@" .. rel .. line_span(snapshot.ranges[1])
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
local function publish_snapshot()
|
|
281
|
-
if not state.job_id then
|
|
282
|
-
return
|
|
283
|
-
end
|
|
284
|
-
local snapshot = M.snapshot()
|
|
285
|
-
if not snapshot then
|
|
286
|
-
send({ type = "selection_cleared", reason = "no-active-editor" })
|
|
287
|
-
return
|
|
288
|
-
end
|
|
289
|
-
send({ type = "selection_changed", snapshot = snapshot })
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
local function schedule_publish(delay)
|
|
293
|
-
delay = delay or (state.config and state.config.debounce_ms or defaults.debounce_ms)
|
|
294
|
-
if state.timer then
|
|
295
|
-
pcall(state.timer.stop, state.timer)
|
|
296
|
-
pcall(state.timer.close, state.timer)
|
|
297
|
-
end
|
|
298
|
-
state.timer = vim.defer_fn(publish_snapshot, delay)
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
function M.start()
|
|
302
|
-
if state.job_id then
|
|
303
|
-
return true
|
|
304
|
-
end
|
|
305
|
-
state.config = state.config or normalize_config()
|
|
306
|
-
local cmd = state.config.sidecar_cmd or default_sidecar_cmd()
|
|
307
|
-
state.job_id = vim.fn.jobstart(cmd, {
|
|
308
|
-
stdin = "pipe",
|
|
309
|
-
detach = false,
|
|
310
|
-
on_exit = function(_, code)
|
|
311
|
-
state.job_id = nil
|
|
312
|
-
if code ~= 0 then
|
|
313
|
-
notify("sidecar exited with code " .. tostring(code), vim.log.levels.WARN)
|
|
314
|
-
end
|
|
315
|
-
end,
|
|
316
|
-
on_stderr = function(_, data)
|
|
317
|
-
for _, line in ipairs(data or {}) do
|
|
318
|
-
if line ~= "" then
|
|
319
|
-
vim.schedule(function()
|
|
320
|
-
notify(line, vim.log.levels.WARN)
|
|
321
|
-
end)
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end,
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
if state.job_id <= 0 then
|
|
328
|
-
state.job_id = nil
|
|
329
|
-
notify("failed to start sidecar", vim.log.levels.ERROR)
|
|
330
|
-
return false
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
send({ workspaceFolders = workspace_folders(), name = "Neovim" })
|
|
334
|
-
schedule_publish(0)
|
|
335
|
-
return true
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
function M.stop()
|
|
339
|
-
if state.timer then
|
|
340
|
-
pcall(state.timer.stop, state.timer)
|
|
341
|
-
pcall(state.timer.close, state.timer)
|
|
342
|
-
state.timer = nil
|
|
343
|
-
end
|
|
344
|
-
if state.job_id then
|
|
345
|
-
send({ type = "shutdown" })
|
|
346
|
-
vim.fn.chanclose(state.job_id, "stdin")
|
|
347
|
-
state.job_id = nil
|
|
348
|
-
end
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
function M.attach()
|
|
352
|
-
if not state.job_id and not M.start() then
|
|
353
|
-
return
|
|
354
|
-
end
|
|
355
|
-
local snapshot = M.snapshot({ prefer_marks = true })
|
|
356
|
-
if not snapshot then
|
|
357
|
-
notify("no active file to attach", vim.log.levels.WARN)
|
|
358
|
-
return
|
|
359
|
-
end
|
|
360
|
-
local range_text = M.format_range_mention(snapshot)
|
|
361
|
-
send({ type = "at_mentioned", snapshot = vim.tbl_extend("force", snapshot, { rangeText = range_text }), rangeText = range_text })
|
|
362
|
-
notify("attached " .. range_text)
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
function M.status()
|
|
366
|
-
notify(state.job_id and "sidecar running" or "sidecar stopped")
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
local function setup_autocmds()
|
|
370
|
-
if state.augroup then
|
|
371
|
-
pcall(vim.api.nvim_del_augroup_by_id, state.augroup)
|
|
372
|
-
end
|
|
373
|
-
state.augroup = vim.api.nvim_create_augroup("PiXIde", { clear = true })
|
|
374
|
-
vim.api.nvim_create_autocmd({ "BufEnter", "WinEnter", "CursorMoved", "CursorMovedI", "TextChanged", "TextChangedI", "DirChanged" }, {
|
|
375
|
-
group = state.augroup,
|
|
376
|
-
callback = function(event)
|
|
377
|
-
if event.event == "DirChanged" then
|
|
378
|
-
send({ type = "workspace_changed", workspaceFolders = workspace_folders() })
|
|
379
|
-
end
|
|
380
|
-
schedule_publish()
|
|
381
|
-
end,
|
|
382
|
-
})
|
|
383
|
-
vim.api.nvim_create_autocmd("ModeChanged", {
|
|
384
|
-
group = state.augroup,
|
|
385
|
-
callback = function(event)
|
|
386
|
-
if event.match and event.match:match("^[vV\022].*:n$") then
|
|
387
|
-
state.visual_mark_valid = true
|
|
388
|
-
end
|
|
389
|
-
schedule_publish(0)
|
|
390
|
-
end,
|
|
391
|
-
})
|
|
392
|
-
vim.api.nvim_create_autocmd("VimLeavePre", {
|
|
393
|
-
group = state.augroup,
|
|
394
|
-
callback = function()
|
|
395
|
-
M.stop()
|
|
396
|
-
end,
|
|
397
|
-
})
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
local function setup_commands()
|
|
401
|
-
local commands = {
|
|
402
|
-
PiXIdeStart = M.start,
|
|
403
|
-
PiXIdeStop = M.stop,
|
|
404
|
-
PiXIdeStatus = M.status,
|
|
405
|
-
PiXIdeAttach = M.attach,
|
|
406
|
-
}
|
|
407
|
-
for name, fn in pairs(commands) do
|
|
408
|
-
pcall(vim.api.nvim_create_user_command, name, fn, {})
|
|
409
|
-
end
|
|
410
|
-
end
|
|
411
|
-
|
|
412
|
-
local function setup_keymap()
|
|
413
|
-
if not state.config.keymap then
|
|
414
|
-
return
|
|
415
|
-
end
|
|
416
|
-
vim.keymap.set({ "n", "v" }, state.config.keymap, M.attach, { desc = "Pi x IDE: attach selection" })
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
function M.setup(opts)
|
|
420
|
-
state.config = normalize_config(opts)
|
|
421
|
-
setup_commands()
|
|
422
|
-
setup_autocmds()
|
|
423
|
-
setup_keymap()
|
|
424
|
-
if state.config.enabled then
|
|
425
|
-
M.start()
|
|
426
|
-
end
|
|
427
|
-
end
|
|
428
|
-
|
|
429
|
-
function M._test_set_visual_mark_valid(value)
|
|
430
|
-
state.visual_mark_valid = value
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
function M._test_reset()
|
|
434
|
-
M.stop()
|
|
435
|
-
state.config = normalize_config({ enabled = false })
|
|
436
|
-
state.latest_snapshot = nil
|
|
437
|
-
state.visual_mark_valid = false
|
|
438
|
-
end
|
|
439
|
-
|
|
440
|
-
setup_commands()
|
|
441
|
-
|
|
442
|
-
return M
|
package/nvim/plugin/pi-x-ide.lua
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
if vim.g.loaded_pi_x_ide == 1 then
|
|
2
|
-
return
|
|
3
|
-
end
|
|
4
|
-
vim.g.loaded_pi_x_ide = 1
|
|
5
|
-
|
|
6
|
-
local function command(name, fn)
|
|
7
|
-
pcall(vim.api.nvim_create_user_command, name, function()
|
|
8
|
-
require("pi_x_ide")[fn]()
|
|
9
|
-
end, {})
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
command("PiXIdeStart", "start")
|
|
13
|
-
command("PiXIdeStop", "stop")
|
|
14
|
-
command("PiXIdeStatus", "status")
|
|
15
|
-
command("PiXIdeAttach", "attach")
|