@babtab/relay 0.1.1 → 0.2.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/CHANGELOG.md CHANGED
@@ -6,6 +6,20 @@ and [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### 0.2.0 — automatic local onboarding (release candidate)
10
+
11
+ - MCP-owned `stdio` bridge starts / reuses a local relay, reconnects after owner
12
+ exit, and stores credentials under `~/.babtab/` instead of the working directory.
13
+ - Local `setup` now writes stdio config before any relay or browser connection
14
+ exists. Remote `--relay-url` setup keeps the HTTP pairing flow.
15
+ - Tool discovery is immediate; browser calls remain gated by explicit pairing,
16
+ token scopes, and expiry. Interrupted actions are never replayed automatically.
17
+ - Extension adds an Add to Cursor link, agent-first onboarding, and an alarm to
18
+ restore opted-in connections after service-worker suspension.
19
+ - Publish `@babtab/relay@0.2.0` before releasing extension 0.2.0; its install
20
+ links and setup commands deliberately pin that version.
21
+
22
+
9
23
  ## [0.1.1] — 2026-09-29
10
24
 
11
25
  ### Security and compatibility
package/README.es.md CHANGED
@@ -9,6 +9,12 @@ El **servidor relay local** para la extensión Babtab de Chrome: conecta tu agen
9
9
 
10
10
  Las extensiones MV3 no pueden escuchar en un puerto, así que este pequeño programa actúa como puente. Se ejecuta en `localhost`, por lo que el tráfico nunca sale de tu máquina. El relay reenvía solicitudes y resultados solo en memoria (incluidas observaciones de página y capturas); no almacena el contenido de las páginas.
11
11
 
12
+ ## Instalación recomendada (0.2.0)
13
+
14
+ Requiere Node.js 20+. Instala la extensión desde Chrome Web Store y pulsa **Add to Cursor** en Babtab. Confirma y activa Babtab en Cursor, vuelve a Chrome y pulsa **Approve**. Tu herramienta de IA inicia el relay automáticamente; no necesitas mantener una terminal abierta. Para otras herramientas, usa **Other AI tools / install with a command**.
15
+
16
+ Detén el relay manual anterior antes de cambiar. Consulta la [guía actualizada](README.md). Las instrucciones siguientes corresponden a la conexión HTTP manual.
17
+
12
18
  ## Actualización a conexiones de dispositivo autenticadas
13
19
 
14
20
  Actualiza el relay y la extensión juntos, recarga la extensión, reconecta en el Side Panel y repite el paso 2 para cada agente. La extensión genera un nuevo ID de dispositivo `dev_v2_`; los tokens vinculados a IDs anteriores ya no controlan la nueva conexión. El relay ahora se vincula explícitamente a `127.0.0.1`. En despliegues remotos debes configurar `HOST` y usar TLS (`wss://` / `https://`) para proteger las credenciales en tránsito.
@@ -67,7 +73,7 @@ Esto registra tu Chrome como un dispositivo en el relay.
67
73
  1. En la misma página del Side Panel, paso 2 → haz clic en **Cursor** → copia el comando de una línea:
68
74
 
69
75
  ```bash
70
- npx -y @babtab/relay setup --target cursor --port 3000 --device <tu-device-id>
76
+ npx -y @babtab/relay setup --target cursor --relay-url http://127.0.0.1:3000 --device <tu-device-id>
71
77
  ```
72
78
 
73
79
  2. Pégalo en cualquier terminal y ejecútalo. Mostrará un código de emparejamiento
package/README.hi.md CHANGED
@@ -9,6 +9,12 @@ Babtab Chrome एक्सटेंशन के लिए **लोकल relay
9
9
 
10
10
  MV3 एक्सटेंशन स्वयं किसी पोर्ट पर listen नहीं कर सकते, इसलिए यह छोटा प्रोग्राम bridge का काम करता है। यह `localhost` पर चलता है, इसलिए ट्रैफ़िक आपकी मशीन से बाहर कभी नहीं जाता। Relay अनुरोध और परिणाम सिर्फ़ मेमोरी में आगे बढ़ाता है (पेज अवलोकन और स्क्रीनशॉट सहित); यह पेज सामग्री को store नहीं करता।
11
11
 
12
+ ## अनुशंसित सेटअप (0.2.0)
13
+
14
+ Node.js 20+ आवश्यक है। Chrome Web Store से एक्सटेंशन इंस्टॉल करें और Babtab में **Add to Cursor** दबाएँ। Cursor में जोड़ने और सक्षम करने की पुष्टि करें, फिर Chrome में लौटकर **Approve** दबाएँ। AI टूल Relay को अपने आप शुरू करता है; टर्मिनल खुला रखने की जरूरत नहीं है। अन्य टूल के लिए **Other AI tools / install with a command** चुनें।
15
+
16
+ बदलने से पहले पुराना मैन्युअल Relay बंद करें। [नवीनतम गाइड](README.md) देखें। नीचे दिए गए निर्देश मैन्युअल HTTP कनेक्शन के लिए हैं।
17
+
12
18
  ## प्रमाणित डिवाइस कनेक्शन पर अपग्रेड
13
19
 
14
20
  Relay और एक्सटेंशन दोनों को एक साथ अपडेट करें, एक्सटेंशन reload करें, Side Panel में फिर से connect करें, और हर एजेंट के लिए चरण 2 दोहराएँ। एक्सटेंशन नई `dev_v2_` डिवाइस ID बनाता है; पुरानी ID से जुड़े टोकन नया कनेक्शन नियंत्रित नहीं कर सकते। Relay अब स्पष्ट रूप से सिर्फ़ `127.0.0.1` पर bind होता है। रिमोट डिप्लॉयमेंट में `HOST` सेट करें और ट्रांज़िट में क्रेडेंशियल की सुरक्षा के लिए TLS (`wss://` / `https://`) इस्तेमाल करें।
@@ -67,7 +73,7 @@ BABTAB_TOKEN_FILE=~/.babtab/relay-tokens.json npx @babtab/relay
67
73
  1. Side Panel के उसी पेज पर चरण 2 → **Cursor** पर क्लिक करें → एक-पंक्ति कमांड copy करें:
68
74
 
69
75
  ```bash
70
- npx -y @babtab/relay setup --target cursor --port 3000 --device <आपकी-device-id>
76
+ npx -y @babtab/relay setup --target cursor --relay-url http://127.0.0.1:3000 --device <आपकी-device-id>
71
77
  ```
72
78
 
73
79
  2. किसी भी टर्मिनल में paste करके चलाएँ। 6-अंकीय पेयरिंग कोड दिखेगा —
package/README.ja.md CHANGED
@@ -9,6 +9,12 @@ Babtab Chrome 拡張機能のための**ローカル中継サーバー**です
9
9
 
10
10
  MV3 の拡張機能は自分でポートを listen できないため、この小さなプログラムが橋渡しをします。`localhost` 上で動作するので、通信が PC の外に出ることはありません。Relay はリクエストと結果をメモリ上でのみ転送します(ページ観測やスクリーンショットを含みます)。ページ内容を保存することはありません。
11
11
 
12
+ ## 推奨セットアップ(0.2.0)
13
+
14
+ Node.js 20+ が必要です。Chrome ウェブストアから拡張機能をインストールし、Babtab の **Add to Cursor** を押します。Cursor で追加・有効化し、Chrome に戻って **Approve** を押してください。Relay は AI ツールが自動起動するため、ターミナルを開いたままにする必要はありません。ほかの AI ツールは **Other AI tools / install with a command** から設定できます。
15
+
16
+ 旧版の手動 Relay を終了してから切り替えてください。詳細は [最新ガイド](README.md) を参照してください。以下は手動 HTTP 接続用の手順です。
17
+
12
18
  ## デバイス認証へのアップグレード
13
19
 
14
20
  Relay と拡張機能を一緒に更新し、拡張機能を再読み込みして Side Panel で再接続したうえで、各エージェントについてステップ 2 を再実行してください。拡張機能は新しい `dev_v2_` デバイス ID を生成します。古い ID に紐づくトークンでは新しい接続を操作できません。Relay は明示的に `127.0.0.1` にバインドするようになりました。リモート配置では `HOST` を指定し、TLS(`wss://`/`https://`)で転送中の認証情報を保護してください。
@@ -67,7 +73,7 @@ BABTAB_TOKEN_FILE=~/.babtab/relay-tokens.json npx @babtab/relay
67
73
  1. Side Panel の同じページでステップ 2 → **Cursor** をクリック → ワンライナーのコマンドをコピーします:
68
74
 
69
75
  ```bash
70
- npx -y @babtab/relay setup --target cursor --port 3000 --device <あなたのデバイスID>
76
+ npx -y @babtab/relay setup --target cursor --relay-url http://127.0.0.1:3000 --device <あなたのデバイスID>
71
77
  ```
72
78
 
73
79
  2. 任意のターミナルに貼り付けて実行します。6 桁のペアリングコードが表示されるので、Side Panel 上部のバナーで **Approve(承認)**します。
package/README.ko.md CHANGED
@@ -9,6 +9,12 @@ Babtab Chrome 확장 프로그램을 위한 **로컬 중계 서버**입니다. A
9
9
 
10
10
  MV3 확장 프로그램은 스스로 포트를 listen 할 수 없기 때문에, 이 작은 프로그램이 다리 역할을 합니다. `localhost`에서 동작하므로 트래픽이 컴퓨터 밖으로 나가지 않습니다. Relay는 요청과 결과를 메모리에서만 전달합니다(페이지 관찰 및 스크린샷 포함). 페이지 내용을 저장하지 않습니다.
11
11
 
12
+ ## 권장 설치 방법 (0.2.0)
13
+
14
+ Node.js 20+가 필요합니다. Chrome 웹 스토어에서 확장 프로그램을 설치하고 Babtab의 **Add to Cursor**를 누르세요. Cursor에서 추가 / 활성화한 뒤 Chrome으로 돌아와 **Approve**를 누르세요. AI 도구가 Relay를 자동으로 실행하므로 터미널을 계속 열어 둘 필요가 없습니다. 다른 도구는 **Other AI tools / install with a command**에서 설정할 수 있습니다.
15
+
16
+ 전환 전에 기존 수동 Relay를 종료하세요. 자세한 내용은 [최신 가이드](README.md)를 참조하세요. 아래는 수동 HTTP 연결용 절차입니다.
17
+
12
18
  ## 인증된 디바이스 연결로 업그레이드
13
19
 
14
20
  Relay와 확장 프로그램을 함께 업데이트하고, 확장 프로그램을 새로고침한 뒤 Side Panel에서 다시 연결한 다음, 각 에이전트마다 2단계를 다시 실행하세요. 확장 프로그램이 새 `dev_v2_` 디바이스 ID를 생성합니다. 이전 ID에 연결된 토큰으로는 새 연결을 제어할 수 없습니다. Relay는 이제 명시적으로 `127.0.0.1`에만 바인딩됩니다. 원격 배포에서는 `HOST`를 직접 설정하고 TLS(`wss://` / `https://`)로 전송 중 인증 정보를 보호하세요.
@@ -67,7 +73,7 @@ BABTAB_TOKEN_FILE=~/.babtab/relay-tokens.json npx @babtab/relay
67
73
  1. Side Panel 같은 페이지에서 2단계 → **Cursor** 클릭 → 한 줄 명령어를 복사:
68
74
 
69
75
  ```bash
70
- npx -y @babtab/relay setup --target cursor --port 3000 --device <내-디바이스-ID>
76
+ npx -y @babtab/relay setup --target cursor --relay-url http://127.0.0.1:3000 --device <내-디바이스-ID>
71
77
  ```
72
78
 
73
79
  2. 아무 터미널에 붙여넣어 실행. 6자리 페어링 코드가 표시되면 Side Panel 상단 배너에서 **Approve(승인)** 클릭.
package/README.md CHANGED
@@ -9,93 +9,51 @@ The **local relay server** for the Babtab Chrome extension: it connects your AI
9
9
 
10
10
  MV3 extensions cannot listen on a port, so this tiny program acts as the bridge. It runs on `localhost`, so traffic never leaves your machine. The relay forwards requests and results in memory, including page observations and screenshots; it does not persist page content.
11
11
 
12
- ## Upgrading to authenticated device connections
12
+ ## Quick start (0.2.0)
13
13
 
14
- Update the relay and extension together, reload the extension, reconnect in the
15
- Side Panel, and run Step 2 again for each agent. The extension creates a new
16
- `dev_v2_` device ID; tokens paired to older IDs do not control the new connection.
17
- The relay now binds `127.0.0.1` explicitly. A remote deployment must opt in with
18
- `HOST` and use TLS (`wss://` / `https://`) to protect credentials in transit.
14
+ Requires Node.js 20+ and the matching Babtab extension. Install the extension from the **Chrome Web Store**; Developer mode is for local development only.
19
15
 
20
- ## How it connects (3 roles)
16
+ 1. Open Babtab in Chrome and click **Add to Cursor**.
17
+ 2. Confirm Add / Enable in Cursor. Cursor starts the local bridge automatically.
18
+ 3. Return to Babtab and **Approve** the first connection.
19
+ 4. On a regular website, ask your agent: **Use babtab to observe the current tab**. Approve site access in Babtab if asked.
21
20
 
22
- ```text
23
- AI agent (Cursor / Pi …) ←→ Relay (local :3000) ←→ Chrome extension (with Side Panel)
24
- connects via MCP config forwarding + pairing only does the real work in your tabs
25
- ```
26
-
27
- ## Quick start (no clone, no install)
28
-
29
- ### Step 1: Install the Chrome extension
30
-
31
- `chrome://extensions` → enable **Developer mode** → **Load unpacked** → select the `dist` folder.
32
-
33
- > Once published on the Chrome Web Store, this step becomes "install from the store".
34
-
35
- ### Step 2: Start the relay (pick one, same result)
36
-
37
- ```bash
38
- # A. Have Node 20+? No install needed, just run:
39
- npx @babtab/relay
21
+ No separate relay command or terminal window is needed. Keep Chrome open.
22
+ The first npm download requires internet access. Pairing credentials are stored in `~/.babtab/`, independent of your working directory.
40
23
 
41
- # B. No Node? Download the binary for your OS from GitHub Releases:
42
- ./babtab-relay-darwin-arm64 # e.g. macOS Apple Silicon
43
- ```
44
-
45
- You're up when you see (default port `3000`):
46
-
47
- ```text
48
- [babtab-relay] listening on http://127.0.0.1:3000
49
- ```
24
+ ### Other AI tools
50
25
 
51
- Advanced (custom port / token file location):
26
+ Open **Other AI tools / install with a command**, choose your tool and copy its personalized command:
52
27
 
53
28
  ```bash
54
- PORT=3001 npx @babtab/relay
55
- BABTAB_TOKEN_FILE=~/.babtab/relay-tokens.json npx @babtab/relay
29
+ npx -y @babtab/relay@0.2.0 setup --target windsurf --port 3000 --device <device-id-from-extension>
56
30
  ```
57
31
 
58
- > `npx` doesn't install anything — it downloads and runs once. Closing the terminal stops the relay.
32
+ Run once, enable / reload MCP in your AI tool, then approve in Chrome. Setup preserves other servers and backs up existing config files. Supported automatic targets: Cursor, Claude Code, Windsurf, Copilot, Codex, Claude Desktop, Antigravity, Devin, Kimi and Hermes. Pi / Manual use the advanced HTTP flow.
59
33
 
60
- ### Step 3: Connect the extension to the relay
34
+ ### How automatic startup works
61
35
 
62
- 1. Open any website in Chrome, click the Babtab toolbar icon to open the **Side Panel**
63
- 2. Step 1: confirm the port (default `3000`, must match the relay) — no URL typing needed
64
- 3. Click **"Save & Connect"**
36
+ Your MCP client launches `babtab-relay stdio --device … --client … --port 3000`. The bridge starts or reuses the loopback relay. Tool discovery works before approval; browser operations require an explicitly approved token. Multiple clients share the relay; a remaining client takes over if its owner exits. In-flight actions interrupted by shutdown return an error and are never replayed automatically.
65
37
 
66
- This registers your Chrome as a device on the relay.
67
- (Remote relay on a VPS? Use *Advanced: custom Relay URL* in the same step.)
38
+ Credentials live in `~/.babtab/` (override with `BABTAB_DATA_DIR`). The extension reconnects after browser / MCP restarts. Explicit **Disconnect** stops automatic reconnection until you reconnect.
68
39
 
69
- ### Step 4: Connect your AI agent to the relay (Cursor as example)
70
-
71
- 1. On the same Side Panel page, Step 2 → click **Cursor** → copy the one-line command:
72
-
73
- ```bash
74
- npx -y @babtab/relay setup --target cursor --port 3000 --device <your-device-id>
75
- ```
40
+ ### Upgrading from 0.1.x
76
41
 
77
- 2. Paste it into any terminal and run it. It shows a 6-digit pairing code —
78
- approve it on the banner at the top of the Side Panel.
79
- 3. Done: the command writes `babtab` into `~/.cursor/mcp.json` for you
80
- (existing entries preserved, previous file kept as `.bak`). Reload MCP in
81
- Cursor (Settings → MCP) and the panel shows `Controlled by: cursor`.
42
+ Stop the manually started relay, update the extension and add your AI tool again. Approve once to pair with the new managed credentials. Port conflicts or an older relay are reported without sending credentials to the conflicting service. Choose a different port under **Advanced connection settings** and reinstall the MCP entry if needed.
82
43
 
83
- One sentence to verify (ask your agent):
44
+ ### Advanced: manual or remote relay
84
45
 
85
- > Use browser_observe to look at the tabs open in my Chrome, then tell me their titles and URLs.
46
+ `npx @babtab/relay` still starts a standalone HTTP relay. In the extension, open **Advanced connection settings**, set the port / URL and use **Save & Connect**. Manual HTTP config generation remains available.
86
47
 
87
- Supported `--target` values: `cursor`, `claude-code`, `windsurf`, `copilot`,
88
- `copilot-insiders`, `codex`, `pi`, `claude-desktop`, `antigravity`, `devin`,
89
- `kimi`, `hermes`, `manual`. Run `npx -y @babtab/relay setup --help` for all
90
- commands (`--list-targets` prints one ready line per harness). No terminal at
91
- hand? Step 2 also offers *Pair & copy JSON manually* as a fallback.
48
+ Standalone token storage uses `BABTAB_TOKEN_FILE` or `./data/relay-tokens.json` relative to the launch directory. Remote relays need an explicit `HOST` and TLS (`wss://` / `https://`). Use `setup --target <tool> --relay-url https://… --device <id>` after the relay and extension are connected.
92
49
 
93
- ## FAQ
50
+ ### Troubleshooting
94
51
 
95
- - **"Save & Connect" does nothing?** Check the relay terminal for `listening` first, then confirm the Step 1 port matches the relay's port.
96
- - **Pairing code expired?** Codes are short-lived — just re-run the setup command.
97
- - **Want a new token?** Re-running the setup command issues a new token and rewrites the config (old `.bak` kept).
98
- - **Agent and Chrome on different machines?** (Advanced) Put the relay on a VPS, use *Advanced: custom Relay URL* in Side Panel Step 1 with your `wss://…`, and pass `--relay-url https://…` to the setup command. The flow stays the same.
52
+ - **Cursor did not open?** Use the setup command under the button, then reload / enable MCP.
53
+ - **No pairing request?** Check that Node 20+ / `npx` is on your AI tool's PATH and Babtab is enabled. Keep the Chrome panel open. The MCP server's stderr logs explain startup problems.
54
+ - **Pairing expired?** Keep the AI tool running; it requests a new code automatically.
55
+ - **Connection stopped?** Reopen your AI tool and Chrome. If you explicitly disconnected, press Reconnect in Babtab.
56
+ - **Lost / revoked credentials?** Approve the new pairing request; the bridge never bypasses browser approval.
99
57
 
100
58
  ## Privacy
101
59
 
package/README.pt-BR.md CHANGED
@@ -9,6 +9,12 @@ O **servidor relay local** para a extensão Babtab do Chrome: conecta seu agente
9
9
 
10
10
  Extensões MV3 não conseguem escutar em uma porta, então este programinha age como ponte. Roda em `localhost`, por isso o tráfego nunca sai da sua máquina. O relay encaminha solicitações e resultados apenas em memória (incluindo observações de página e capturas); não armazena o conteúdo das páginas.
11
11
 
12
+ ## Instalação recomendada (0.2.0)
13
+
14
+ Requer Node.js 20+. Instale a extensão pela Chrome Web Store e clique em **Add to Cursor** no Babtab. Confirme e ative no Cursor, volte ao Chrome e clique em **Approve**. A ferramenta de IA inicia o relay automaticamente; não é preciso manter um terminal aberto. Para outras ferramentas, use **Other AI tools / install with a command**.
15
+
16
+ Encerre o relay manual anterior antes de mudar. Consulte o [guia atualizado](README.md). As instruções abaixo são para conexão HTTP manual.
17
+
12
18
  ## Atualização para conexões de dispositivo autenticadas
13
19
 
14
20
  Atualize o relay e a extensão juntos, recarregue a extensão, reconecte no Side Panel e repita o passo 2 para cada agente. A extensão gera um novo ID de dispositivo `dev_v2_`; tokens vinculados a IDs anteriores não controlam mais a nova conexão. O relay agora se vincula explicitamente a `127.0.0.1`. Em implantações remotas, configure `HOST` e use TLS (`wss://` / `https://`) para proteger as credenciais em trânsito.
@@ -67,7 +73,7 @@ Isso registra seu Chrome como um dispositivo no relay.
67
73
  1. Na mesma página do Side Panel, passo 2 → clique em **Cursor** → copie o comando de uma linha:
68
74
 
69
75
  ```bash
70
- npx -y @babtab/relay setup --target cursor --port 3000 --device <seu-device-id>
76
+ npx -y @babtab/relay setup --target cursor --relay-url http://127.0.0.1:3000 --device <seu-device-id>
71
77
  ```
72
78
 
73
79
  2. Cole em qualquer terminal e execute. Ele mostra um código de pareamento de
package/README.zh-TW.md CHANGED
@@ -9,91 +9,61 @@ Babtab Chrome 擴充功能的**本機中轉伺服器**:把你的 AI Agent(Cu
9
9
 
10
10
  MV3 擴充功能自己不能 listen port,所以需要這支小程式當橋樑。跑在 `localhost`,流量不出你的電腦;Relay 會在記憶體中轉發請求與結果(包含頁面觀察及截圖),不會儲存頁面內容。
11
11
 
12
- ## 升級裝置驗證
12
+ ## 使用者快速開始(0.2.0)
13
13
 
14
- 請一起更新 Relay 與擴充功能,重新載入擴充功能、在 Side Panel 重新連線,
15
- 再為每個 Agent 執行一次步驟 2 配對。擴充功能會產生新的 `dev_v2_` 裝置 ID;
16
- 舊 ID 的 token 無法控制新連線。Relay 現在明確只監聽 `127.0.0.1`;
17
- 遠端部署需自行設定 `HOST`,並使用 TLS(`wss://`/`https://`)保護傳輸憑證。
14
+ 需要 Node.js 20+ 與對應新版外掛。一般使用者從 **Chrome Web Store 安裝 Babtab**;開發者模式只供本機測試。
18
15
 
19
- ## 連線方式(3 個角色)
16
+ 1. 開啟 Babtab Side Panel,按 **Add to Cursor**。
17
+ 2. 在 Cursor 確認加入/啟用 Babtab;Cursor 自動啟動本機橋接程式。
18
+ 3. 回到外掛,確認工具名稱後按 **Approve**。
19
+ 4. 在一般網站分頁,對 AI 說 **Use babtab to observe the current tab**;需要網站授權時在外掛批准。
20
20
 
21
- ```text
22
- AI Agent(Cursor / Pi …) ←→ Relay(本機 :3000) ←→ Chrome 擴充功能(含 Side Panel)
23
- 用 MCP 設定連過來 只做轉發與配對 真正在分頁上動手的人
24
- ```
25
-
26
- ## 使用者快速開始(不用 clone、不用 install)
27
-
28
- ### 步驟 1:安裝 Chrome 擴充功能
29
-
30
- `chrome://extensions` → 開啟**開發者模式** → **載入未封裝項目** → 選 `dist` 資料夾。
31
-
32
- > 上架 Chrome 商店後,這步會變成「去商店按安裝」。
33
-
34
- ### 步驟 2:啟動 Relay(二選一,效果一樣)
35
-
36
- ```bash
37
- # A. 有 Node 20+ 的人:免安裝,直接跑
38
- npx @babtab/relay
21
+ 不用先啟動 Relay、不用設定 port、不用保持終端機開啟。使用時保留 Chrome。
22
+ 首次 npm 下載需要網路;憑證固定保存在 `~/.babtab/`,更換工作目錄不影響連線。
39
23
 
40
- # B. 不想裝 Node 的人:去 GitHub Release 下載對應系統的執行檔
41
- ./babtab-relay-darwin-arm64 # macOS Apple Silicon 為例
42
- ```
43
-
44
- 看到以下訊息就是起來了(預設 port `3000`):
45
-
46
- ```text
47
- [babtab-relay] listening on http://127.0.0.1:3000
48
- ```
24
+ ### 其他 AI 工具
49
25
 
50
- 進階用法(換 port、指定 token 存檔位置):
26
+ 開啟 **Other AI tools / install with a command**,選工具並複製專屬指令:
51
27
 
52
28
  ```bash
53
- PORT=3001 npx @babtab/relay
54
- BABTAB_TOKEN_FILE=~/.babtab/relay-tokens.json npx @babtab/relay
29
+ npx -y @babtab/relay@0.2.0 setup --target windsurf --port 3000 --device <外掛提供的deviceId>
55
30
  ```
56
31
 
57
- > `npx` 不是安裝,是「下載來跑一次」,關掉終端機就停了。
32
+ 只需執行一次。指令保留其他 server、備份舊設定,寫入由 AI 工具自動啟動的 MCP 設定。
33
+ 接著重載/啟用 MCP,再回 Chrome 批准配對。
34
+ 自動啟動支援 Cursor、Claude Code、Windsurf、Copilot、Codex、Claude Desktop、Antigravity、Devin、Kimi、Hermes;Pi/Manual 沿用進階 HTTP 流程。
58
35
 
59
- ### 步驟 3:擴充功能連上 Relay
36
+ ### 自動啟動與重連
60
37
 
61
- 1. 在 Chrome 開任意網站,點工具列的 Babtab 圖示開啟 **Side Panel**
62
- 2. 步驟 1:確認 port(預設 `3000`,要跟 Relay 一致)即可,不用手打 URL
63
- 3. 按 **"Save & Connect"**
38
+ AI 工具啟動 `babtab-relay stdio --device … --client … --port 3000`,橋接程式啟動或重用本機 Relay。
39
+ 未配對時可列出工具,實際操作仍須人工批准。多個 AI 工具共用 Relay;持有 Relay 的工具結束後,剩餘工具會接手。
40
+ 中斷中的動作會回報錯誤,不會自動重送。
64
41
 
65
- 這一步是把你的 Chrome 註冊成 Relay 上的一台 device。
66
- (Relay 在遠端 VPS?同一步有 *Advanced: custom Relay URL* 可填。)
42
+ 自動模式的憑證保存在 `~/.babtab/`(可透過 `BABTAB_DATA_DIR` 覆寫)。
43
+ 重新開啟 Chrome/AI 工具後會自動重連。明確按 **Disconnect** 後,自動重連會停止,需再按 Reconnect。
67
44
 
68
- ### 步驟 4:AI Agent 連上 Relay(以 Cursor 為例)
69
-
70
- 1. 在 Side Panel 同一頁,步驟 2 → 按 **Cursor** → 複製那行指令:
71
-
72
- ```bash
73
- npx -y @babtab/relay setup --target cursor --port 3000 --device <你的deviceId>
74
- ```
45
+ ### 從 0.1.x 升級
75
46
 
76
- 2. 貼到任意終端機執行,會顯示 6 位配對碼 → 回到 Side Panel 在頂部橫條按 **Approve**。
77
- 3. 完成:指令會自動把 `babtab` 寫進 `~/.cursor/mcp.json`
78
- (原有內容保留,舊檔留一份 `.bak`)。去 Cursor 重載 MCP(Settings → MCP),
79
- Panel 出現 `Controlled by: cursor` 就通了。
47
+ 先關掉舊的手動 Relay,更新外掛,再重新加入 AI 工具並批准一次。
48
+ 自動模式使用新的固定憑證目錄。若 port 被其他服務或舊版 Relay 佔用,會顯示錯誤;
49
+ 可在 **Advanced connection settings** 換 port,再重新加入 AI 工具。
80
50
 
81
- 驗證一句話(在 Agent 裡下):
51
+ ### 進階:手動或遠端 Relay
82
52
 
83
- > 用 browser_observe 看我現在 Chrome 開的分頁,然後告訴我標題和網址
53
+ 仍可執行 `npx @babtab/relay` 啟動獨立 HTTP Relay。
54
+ 外掛 **Advanced connection settings** 可設定 port/URL 並按 **Save & Connect**;也保留手動產生 HTTP 設定。
84
55
 
85
- 支援的 `--target`:`cursor`、`claude-code`、`windsurf`、`copilot`、
86
- `copilot-insiders`、`codex`、`pi`、`claude-desktop`、`antigravity`、`devin`、
87
- `kimi`、`hermes`、`manual`。`npx -y @babtab/relay setup --help` 看完整說明
88
- (`--list-targets` 一次印出每個 harness 的現成指令)。沒終端機的環境,
89
- 步驟 2 也有 *Pair & copy JSON manually* 可退回手動貼上。
56
+ 手動模式沿用 `BABTAB_TOKEN_FILE` 或啟動目錄的 `./data/relay-tokens.json`。
57
+ 遠端部署須明確設定 `HOST` 並使用 TLS(`wss://`/`https://`);先讓外掛連上 Relay,
58
+ 再跑 `setup --target <tool> --relay-url https://… --device <id>`。
90
59
 
91
- ## 常見問題
60
+ ### 常見問題
92
61
 
93
- - **按 "Save & Connect"沒反應?** 先看 Relay 終端機有沒有 `listening`,再確認步驟 1 的 port 跟 Relay 一致。
94
- - **配對碼過期?** 配對碼只有短暫有效,超時就重跑一次 setup 指令。
95
- - **想換 token?** 重跑一次 setup 指令會產生新 token 並重寫設定(舊檔留 `.bak`)。
96
- - **Agent 跟 Chrome 不在同一台電腦?**(進階)把 Relay 放到 VPS 上,Side Panel 步驟 1 用 *Advanced: custom Relay URL* 填 `wss://…`,setup 指令加 `--relay-url https://…` 即可,流程不變。
62
+ - **Cursor 沒開啟?** 展開按鈕下方的 setup 指令,執行一次,再重載/啟用 MCP。
63
+ - **沒出現配對要求?** 確认 AI 工具的 PATH 找得到 Node 20+/`npx`,且 Babtab 已啟用;保持外掛面板開啟。MCP 日誌會顯示啟動錯誤。
64
+ - **配對碼過期?** 保持 AI 工具執行,橋接程式會自動取得新碼。
65
+ - **斷線?** 開啟 AI 工具和 Chrome;若先前主動 Disconnect,請在外掛按 Reconnect。
66
+ - **憑證遺失或撤銷?** 重新批准配對;橋接程式不會跳過人工批准。
97
67
 
98
68
  ## 隱私說明
99
69
 
package/dist/relay.cjs CHANGED
@@ -1,83 +1,93 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Jn=Object.create;var at=Object.defineProperty;var Kn=Object.getOwnPropertyDescriptor;var Yn=Object.getOwnPropertyNames;var Zn=Object.getPrototypeOf,Xn=Object.prototype.hasOwnProperty;var x=(e,t)=>()=>(e&&(t=e(e=0)),t);var w=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Zt=(e,t)=>{for(var r in t)at(e,r,{get:t[r],enumerable:!0})},Qn=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Yn(t))!Xn.call(e,i)&&i!==r&&at(e,i,{get:()=>t[i],enumerable:!(n=Kn(t,i))||n.enumerable});return e};var U=(e,t,r)=>(r=e!=null?Jn(Zn(e)):{},Qn(t||!e||!e.__esModule?at(r,"default",{value:e,enumerable:!0}):r,e));var Qt={};Zt(Qt,{extractBearer:()=>Ie,hasScope:()=>Xt,tokenAllows:()=>ce});function Ie(e){let t=Array.isArray(e)?e[0]:e;if(!t)return null;let r=/^Bearer\s+(.+)$/i.exec(t.trim());return r?r[1].trim():null}function Xt(e,t){return e.includes("*")||e.includes(t)}function ce(e,t){return e?Xt(e.scopes,t):!1}var fe=x(()=>{"use strict"});var R=w((fo,rr)=>{"use strict";var er=["nodebuffer","arraybuffer","fragments"],tr=typeof Blob<"u";tr&&er.push("blob");rr.exports={BINARY_TYPES:er,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:tr,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var ue=w((uo,Le)=>{"use strict";var{EMPTY_BUFFER:ri}=R(),ft=Buffer[Symbol.species];function ni(e,t){if(e.length===0)return ri;if(e.length===1)return e[0];let r=Buffer.allocUnsafe(t),n=0;for(let i=0;i<e.length;i++){let s=e[i];r.set(s,n),n+=s.length}return n<t?new ft(r.buffer,r.byteOffset,n):r}function nr(e,t,r,n,i){for(let s=0;s<i;s++)r[n+s]=e[s]^t[s&3]}function ir(e,t){for(let r=0;r<e.length;r++)e[r]^=t[r&3]}function ii(e){return e.length===e.buffer.byteLength?e.buffer:e.buffer.slice(e.byteOffset,e.byteOffset+e.length)}function ut(e){if(ut.readOnly=!0,Buffer.isBuffer(e))return e;let t;return e instanceof ArrayBuffer?t=new ft(e):ArrayBuffer.isView(e)?t=new ft(e.buffer,e.byteOffset,e.byteLength):(t=Buffer.from(e),ut.readOnly=!1),t}Le.exports={concat:ni,mask:nr,toArrayBuffer:ii,toBuffer:ut,unmask:ir};if(!process.env.WS_NO_BUFFER_UTIL)try{let e=require("bufferutil");Le.exports.mask=function(t,r,n,i,s){s<48?nr(t,r,n,i,s):e.mask(t,r,n,i,s)},Le.exports.unmask=function(t,r){t.length<32?ir(t,r):e.unmask(t,r)}}catch{}});var ar=w((ho,or)=>{"use strict";var sr=Symbol("kDone"),dt=Symbol("kRun"),ht=class{constructor(t){this[sr]=()=>{this.pending--,this[dt]()},this.concurrency=t||1/0,this.jobs=[],this.pending=0}add(t){this.jobs.push(t),this[dt]()}[dt](){if(this.pending!==this.concurrency&&this.jobs.length){let t=this.jobs.shift();this.pending++,t(this[sr])}}};or.exports=ht});var te=w((po,ur)=>{"use strict";var de=require("zlib"),lr=ue(),si=ar(),{kStatusCode:cr}=R(),oi=Buffer[Symbol.species],ai=Buffer.from([0,0,255,255]),Re=Symbol("permessage-deflate"),M=Symbol("total-length"),Q=Symbol("callback"),j=Symbol("buffers"),ee=Symbol("error"),De,pt=class{constructor(t){if(this._options=t||{},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,!De){let r=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;De=new si(r)}}static get extensionName(){return"permessage-deflate"}offer(){let t={};return this._options.serverNoContextTakeover&&(t.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(t.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(t.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?t.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(t.client_max_window_bits=!0),t}accept(t){return t=this.normalizeParams(t),this.params=this._isServer?this.acceptAsServer(t):this.acceptAsClient(t),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let t=this._deflate[Q];this._deflate.close(),this._deflate=null,t&&t(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(t){let r=this._options,n=t.find(i=>!(r.serverNoContextTakeover===!1&&i.server_no_context_takeover||i.server_max_window_bits&&(r.serverMaxWindowBits===!1||typeof r.serverMaxWindowBits=="number"&&r.serverMaxWindowBits>i.server_max_window_bits)||typeof r.clientMaxWindowBits=="number"&&(typeof i.client_max_window_bits=="number"?r.clientMaxWindowBits>i.client_max_window_bits:!i.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(t){let r=t[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(t){return t.forEach(r=>{Object.keys(r).forEach(n=>{let i=r[n];if(i.length>1)throw new Error(`Parameter "${n}" must have only a single value`);if(i=i[0],n==="client_max_window_bits"){if(i!==!0){let s=+i;if(!Number.isInteger(s)||s<8||s>15)throw new TypeError(`Invalid value for parameter "${n}": ${i}`);i=s}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${n}": ${i}`)}else if(n==="server_max_window_bits"){let s=+i;if(!Number.isInteger(s)||s<8||s>15)throw new TypeError(`Invalid value for parameter "${n}": ${i}`);i=s}else if(n==="client_no_context_takeover"||n==="server_no_context_takeover"){if(i!==!0)throw new TypeError(`Invalid value for parameter "${n}": ${i}`)}else throw new Error(`Unknown parameter "${n}"`);r[n]=i})}),t}decompress(t,r,n){De.add(i=>{this._decompress(t,r,(s,o)=>{i(),n(s,o)})})}compress(t,r,n){De.add(i=>{this._compress(t,r,(s,o)=>{i(),n(s,o)})})}_decompress(t,r,n){let i=this._isServer?"client":"server";if(!this._inflate){let s=`${i}_max_window_bits`,o=typeof this.params[s]!="number"?de.Z_DEFAULT_WINDOWBITS:this.params[s];this._inflate=de.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[Re]=this,this._inflate[M]=0,this._inflate[j]=[],this._inflate.on("error",ci),this._inflate.on("data",fr)}this._inflate[Q]=n,this._inflate.write(t),r&&this._inflate.write(ai),this._inflate.flush(()=>{let s=this._inflate[ee];if(s){this._inflate.close(),this._inflate=null,n(s);return}let o=lr.concat(this._inflate[j],this._inflate[M]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[M]=0,this._inflate[j]=[],r&&this.params[`${i}_no_context_takeover`]&&this._inflate.reset()),n(null,o)})}_compress(t,r,n){let i=this._isServer?"server":"client";if(!this._deflate){let s=`${i}_max_window_bits`,o=typeof this.params[s]!="number"?de.Z_DEFAULT_WINDOWBITS:this.params[s];this._deflate=de.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[M]=0,this._deflate[j]=[],this._deflate.on("data",li)}this._deflate[Q]=n,this._deflate.write(t),this._deflate.flush(de.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let s=lr.concat(this._deflate[j],this._deflate[M]);r&&(s=new oi(s.buffer,s.byteOffset,s.length-4)),this._deflate[Q]=null,this._deflate[M]=0,this._deflate[j]=[],r&&this.params[`${i}_no_context_takeover`]&&this._deflate.reset(),n(null,s)})}};ur.exports=pt;function li(e){this[j].push(e),this[M]+=e.length}function fr(e){if(this[M]+=e.length,this[Re]._maxPayload<1||this[M]<=this[Re]._maxPayload){this[j].push(e);return}this[ee]=new RangeError("Max payload size exceeded"),this[ee].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[ee][cr]=1009,this.removeListener("data",fr),this.reset()}function ci(e){if(this[Re]._inflate=null,this[ee]){this[Q](this[ee]);return}e[cr]=1007,this[Q](e)}});var re=w((mo,Me)=>{"use strict";var{isUtf8:dr}=require("buffer"),{hasBlob:fi}=R(),ui=[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 di(e){return e>=1e3&&e<=1014&&e!==1004&&e!==1005&&e!==1006||e>=3e3&&e<=4999}function mt(e){let t=e.length,r=0;for(;r<t;)if(!(e[r]&128))r++;else if((e[r]&224)===192){if(r+1===t||(e[r+1]&192)!==128||(e[r]&254)===192)return!1;r+=2}else if((e[r]&240)===224){if(r+2>=t||(e[r+1]&192)!==128||(e[r+2]&192)!==128||e[r]===224&&(e[r+1]&224)===128||e[r]===237&&(e[r+1]&224)===160)return!1;r+=3}else if((e[r]&248)===240){if(r+3>=t||(e[r+1]&192)!==128||(e[r+2]&192)!==128||(e[r+3]&192)!==128||e[r]===240&&(e[r+1]&240)===128||e[r]===244&&e[r+1]>143||e[r]>244)return!1;r+=4}else return!1;return!0}function hi(e){return fi&&typeof e=="object"&&typeof e.arrayBuffer=="function"&&typeof e.type=="string"&&typeof e.stream=="function"&&(e[Symbol.toStringTag]==="Blob"||e[Symbol.toStringTag]==="File")}Me.exports={isBlob:hi,isValidStatusCode:di,isValidUTF8:mt,tokenChars:ui};if(dr)Me.exports.isValidUTF8=function(e){return e.length<24?mt(e):dr(e)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let e=require("utf-8-validate");Me.exports.isValidUTF8=function(t){return t.length<32?mt(t):e(t)}}catch{}});var bt=w((go,Sr)=>{"use strict";var{Writable:pi}=require("stream"),hr=te(),{BINARY_TYPES:mi,EMPTY_BUFFER:pr,kStatusCode:gi,kWebSocket:_i}=R(),{concat:gt,toArrayBuffer:yi,unmask:Si}=ue(),{isValidStatusCode:bi,isValidUTF8:mr}=re(),$e=Buffer[Symbol.species],O=0,gr=1,_r=2,yr=3,_t=4,yt=5,Be=6,St=class extends pi{constructor(t={}){super(),this._allowSynchronousEvents=t.allowSynchronousEvents!==void 0?t.allowSynchronousEvents:!0,this._binaryType=t.binaryType||mi[0],this._extensions=t.extensions||{},this._isServer=!!t.isServer,this._maxBufferedChunks=t.maxBufferedChunks|0,this._maxFragments=t.maxFragments|0,this._maxPayload=t.maxPayload|0,this._skipUTF8Validation=!!t.skipUTF8Validation,this[_i]=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._numFragments=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=O}_write(t,r,n){if(this._opcode===8&&this._state==O)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+=t.length,this._buffers.push(t),this.startLoop(n)}consume(t){if(this._bufferedBytes-=t,t===this._buffers[0].length)return this._buffers.shift();if(t<this._buffers[0].length){let n=this._buffers[0];return this._buffers[0]=new $e(n.buffer,n.byteOffset+t,n.length-t),new $e(n.buffer,n.byteOffset,t)}let r=Buffer.allocUnsafe(t);do{let n=this._buffers[0],i=r.length-t;t>=n.length?r.set(this._buffers.shift(),i):(r.set(new Uint8Array(n.buffer,n.byteOffset,t),i),this._buffers[0]=new $e(n.buffer,n.byteOffset+t,n.length-t)),t-=n.length}while(t>0);return r}startLoop(t){this._loop=!0;do switch(this._state){case O:this.getInfo(t);break;case gr:this.getPayloadLength16(t);break;case _r:this.getPayloadLength64(t);break;case yr:this.getMask();break;case _t:this.getData(t);break;case yt:case Be:this._loop=!1;return}while(this._loop);this._errored||t()}getInfo(t){if(this._bufferedBytes<2){this._loop=!1;return}let r=this.consume(2);if(r[0]&48){let i=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");t(i);return}let n=(r[0]&64)===64;if(n&&!this._extensions[hr.extensionName]){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(i);return}if(this._fin=(r[0]&128)===128,this._opcode=r[0]&15,this._payloadLength=r[1]&127,this._opcode===0){if(n){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(i);return}if(!this._fragmented){let i=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");t(i);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let i=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(i);return}this._compressed=n}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let i=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");t(i);return}if(n){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(i);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let i=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");t(i);return}}else{let i=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(i);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(r[1]&128)===128,this._isServer){if(!this._masked){let i=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");t(i);return}}else if(this._masked){let i=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");t(i);return}this._payloadLength===126?this._state=gr:this._payloadLength===127?this._state=_r:this.haveLength(t)}getPayloadLength16(t){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(t)}getPayloadLength64(t){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 i=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");t(i);return}this._payloadLength=n*Math.pow(2,32)+r.readUInt32BE(4),this.haveLength(t)}haveLength(t){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");t(r);return}this._masked?this._state=yr:this._state=_t}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=_t}getData(t){let r=pr;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]&&Si(r,this._mask)}if(this._opcode>7){this.controlMessage(r,t);return}if(this._maxFragments>0&&++this._numFragments>this._maxFragments){let n=this.createError(RangeError,"Too many message fragments",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS");t(n);return}if(this._compressed){this._state=yt,this.decompress(r,t);return}r.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(r)),this.dataMessage(t)}decompress(t,r){this._extensions[hr.extensionName].decompress(t,this._fin,(i,s)=>{if(i)return r(i);if(s.length){if(this._messageLength+=s.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}this._fragments.push(s)}this.dataMessage(r),this._state===O&&this.startLoop(r)})}dataMessage(t){if(!this._fin){this._state=O;return}let r=this._messageLength,n=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._numFragments=0,this._fragments=[],this._opcode===2){let i;this._binaryType==="nodebuffer"?i=gt(n,r):this._binaryType==="arraybuffer"?i=yi(gt(n,r)):this._binaryType==="blob"?i=new Blob(n):i=n,this._allowSynchronousEvents?(this.emit("message",i,!0),this._state=O):(this._state=Be,setImmediate(()=>{this.emit("message",i,!0),this._state=O,this.startLoop(t)}))}else{let i=gt(n,r);if(!this._skipUTF8Validation&&!mr(i)){let s=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");t(s);return}this._state===yt||this._allowSynchronousEvents?(this.emit("message",i,!1),this._state=O):(this._state=Be,setImmediate(()=>{this.emit("message",i,!1),this._state=O,this.startLoop(t)}))}}controlMessage(t,r){if(this._opcode===8){if(t.length===0)this._loop=!1,this.emit("conclude",1005,pr),this.end();else{let n=t.readUInt16BE(0);if(!bi(n)){let s=this.createError(RangeError,`invalid status code ${n}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");r(s);return}let i=new $e(t.buffer,t.byteOffset+2,t.length-2);if(!this._skipUTF8Validation&&!mr(i)){let s=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");r(s);return}this._loop=!1,this.emit("conclude",n,i),this.end()}this._state=O;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",t),this._state=O):(this._state=Be,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",t),this._state=O,this.startLoop(r)}))}createError(t,r,n,i,s){this._loop=!1,this._errored=!0;let o=new t(n?`Invalid WebSocket frame: ${r}`:r);return Error.captureStackTrace(o,this.createError),o.code=s,o[gi]=i,o}};Sr.exports=St});var xt=w((yo,vr)=>{"use strict";var{Duplex:_o}=require("stream"),{randomFillSync:Ei}=require("crypto"),{types:{isUint8Array:vi}}=require("util"),br=te(),{EMPTY_BUFFER:xi,kWebSocket:wi,NOOP:Ti}=R(),{isBlob:ne,isValidStatusCode:ki}=re(),{mask:Er,toBuffer:G}=ue(),A=Symbol("kByteLength"),Ci=Buffer.alloc(4),Ue=8*1024,H,ie=Ue,N=0,Oi=1,Ai=2,Et=class e{constructor(t,r,n){this._extensions=r||{},n&&(this._generateMask=n,this._maskBuffer=Buffer.alloc(4)),this._socket=t,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=N,this.onerror=Ti,this[wi]=void 0}static frame(t,r){let n,i=!1,s=2,o=!1;r.mask&&(n=r.maskBuffer||Ci,r.generateMask?r.generateMask(n):(ie===Ue&&(H===void 0&&(H=Buffer.alloc(Ue)),Ei(H,0,Ue),ie=0),n[0]=H[ie++],n[1]=H[ie++],n[2]=H[ie++],n[3]=H[ie++]),o=(n[0]|n[1]|n[2]|n[3])===0,s=6);let a;typeof t=="string"?(!r.mask||o)&&r[A]!==void 0?a=r[A]:(t=Buffer.from(t),a=t.length):(a=t.length,i=r.mask&&r.readOnly&&!o);let l=a;a>=65536?(s+=8,l=127):a>125&&(s+=2,l=126);let c=Buffer.allocUnsafe(i?a+s:s);return c[0]=r.fin?r.opcode|128:r.opcode,r.rsv1&&(c[0]|=64),c[1]=l,l===126?c.writeUInt16BE(a,2):l===127&&(c[2]=c[3]=0,c.writeUIntBE(a,4,6)),r.mask?(c[1]|=128,c[s-4]=n[0],c[s-3]=n[1],c[s-2]=n[2],c[s-1]=n[3],o?[c,t]:i?(Er(t,n,c,s,a),[c]):(Er(t,n,t,0,a),[c,t])):[c,t]}close(t,r,n,i){let s;if(t===void 0)s=xi;else{if(typeof t!="number"||!ki(t))throw new TypeError("First argument must be a valid error code number");if(r===void 0||!r.length)s=Buffer.allocUnsafe(2),s.writeUInt16BE(t,0);else{let a=Buffer.byteLength(r);if(a>123)throw new RangeError("The message must not be greater than 123 bytes");if(s=Buffer.allocUnsafe(2+a),s.writeUInt16BE(t,0),typeof r=="string")s.write(r,2);else if(vi(r))s.set(r,2);else throw new TypeError("Second argument must be a string or a Uint8Array")}}let o={[A]:s.length,fin:!0,generateMask:this._generateMask,mask:n,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==N?this.enqueue([this.dispatch,s,!1,o,i]):this.sendFrame(e.frame(s,o),i)}ping(t,r,n){let i,s;if(typeof t=="string"?(i=Buffer.byteLength(t),s=!1):ne(t)?(i=t.size,s=!1):(t=G(t),i=t.length,s=G.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[A]:i,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:9,readOnly:s,rsv1:!1};ne(t)?this._state!==N?this.enqueue([this.getBlobData,t,!1,o,n]):this.getBlobData(t,!1,o,n):this._state!==N?this.enqueue([this.dispatch,t,!1,o,n]):this.sendFrame(e.frame(t,o),n)}pong(t,r,n){let i,s;if(typeof t=="string"?(i=Buffer.byteLength(t),s=!1):ne(t)?(i=t.size,s=!1):(t=G(t),i=t.length,s=G.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[A]:i,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:10,readOnly:s,rsv1:!1};ne(t)?this._state!==N?this.enqueue([this.getBlobData,t,!1,o,n]):this.getBlobData(t,!1,o,n):this._state!==N?this.enqueue([this.dispatch,t,!1,o,n]):this.sendFrame(e.frame(t,o),n)}send(t,r,n){let i=this._extensions[br.extensionName],s=r.binary?2:1,o=r.compress,a,l;typeof t=="string"?(a=Buffer.byteLength(t),l=!1):ne(t)?(a=t.size,l=!1):(t=G(t),a=t.length,l=G.readOnly),this._firstFragment?(this._firstFragment=!1,o&&i&&i.params[i._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(o=a>=i._threshold),this._compress=o):(o=!1,s=0),r.fin&&(this._firstFragment=!0);let c={[A]:a,fin:r.fin,generateMask:this._generateMask,mask:r.mask,maskBuffer:this._maskBuffer,opcode:s,readOnly:l,rsv1:o};ne(t)?this._state!==N?this.enqueue([this.getBlobData,t,this._compress,c,n]):this.getBlobData(t,this._compress,c,n):this._state!==N?this.enqueue([this.dispatch,t,this._compress,c,n]):this.dispatch(t,this._compress,c,n)}getBlobData(t,r,n,i){this._bufferedBytes+=n[A],this._state=Ai,t.arrayBuffer().then(s=>{if(this._socket.destroyed){let a=new Error("The socket was closed while the blob was being read");process.nextTick(vt,this,a,i);return}this._bufferedBytes-=n[A];let o=G(s);r?this.dispatch(o,r,n,i):(this._state=N,this.sendFrame(e.frame(o,n),i),this.dequeue())}).catch(s=>{process.nextTick(Ni,this,s,i)})}dispatch(t,r,n,i){if(!r){this.sendFrame(e.frame(t,n),i);return}let s=this._extensions[br.extensionName];this._bufferedBytes+=n[A],this._state=Oi,s.compress(t,n.fin,(o,a)=>{if(this._socket.destroyed){let l=new Error("The socket was closed while data was being compressed");vt(this,l,i);return}this._bufferedBytes-=n[A],this._state=N,n.readOnly=!1,this.sendFrame(e.frame(a,n),i),this.dequeue()})}dequeue(){for(;this._state===N&&this._queue.length;){let t=this._queue.shift();this._bufferedBytes-=t[3][A],Reflect.apply(t[0],this,t.slice(1))}}enqueue(t){this._bufferedBytes+=t[3][A],this._queue.push(t)}sendFrame(t,r){t.length===2?(this._socket.cork(),this._socket.write(t[0]),this._socket.write(t[1],r),this._socket.uncork()):this._socket.write(t[0],r)}};vr.exports=Et;function vt(e,t,r){typeof r=="function"&&r(t);for(let n=0;n<e._queue.length;n++){let i=e._queue[n],s=i[i.length-1];typeof s=="function"&&s(t)}}function Ni(e,t,r){vt(e,t,r),e.onerror(t)}});var Pr=w((So,Nr)=>{"use strict";var{kForOnEventAttribute:he,kListener:wt}=R(),xr=Symbol("kCode"),wr=Symbol("kData"),Tr=Symbol("kError"),kr=Symbol("kMessage"),Cr=Symbol("kReason"),se=Symbol("kTarget"),Or=Symbol("kType"),Ar=Symbol("kWasClean"),$=class{constructor(t){this[se]=null,this[Or]=t}get target(){return this[se]}get type(){return this[Or]}};Object.defineProperty($.prototype,"target",{enumerable:!0});Object.defineProperty($.prototype,"type",{enumerable:!0});var z=class extends ${constructor(t,r={}){super(t),this[xr]=r.code===void 0?0:r.code,this[Cr]=r.reason===void 0?"":r.reason,this[Ar]=r.wasClean===void 0?!1:r.wasClean}get code(){return this[xr]}get reason(){return this[Cr]}get wasClean(){return this[Ar]}};Object.defineProperty(z.prototype,"code",{enumerable:!0});Object.defineProperty(z.prototype,"reason",{enumerable:!0});Object.defineProperty(z.prototype,"wasClean",{enumerable:!0});var oe=class extends ${constructor(t,r={}){super(t),this[Tr]=r.error===void 0?null:r.error,this[kr]=r.message===void 0?"":r.message}get error(){return this[Tr]}get message(){return this[kr]}};Object.defineProperty(oe.prototype,"error",{enumerable:!0});Object.defineProperty(oe.prototype,"message",{enumerable:!0});var pe=class extends ${constructor(t,r={}){super(t),this[wr]=r.data===void 0?null:r.data}get data(){return this[wr]}};Object.defineProperty(pe.prototype,"data",{enumerable:!0});var Pi={addEventListener(e,t,r={}){for(let i of this.listeners(e))if(!r[he]&&i[wt]===t&&!i[he])return;let n;if(e==="message")n=function(s,o){let a=new pe("message",{data:o?s:s.toString()});a[se]=this,je(t,this,a)};else if(e==="close")n=function(s,o){let a=new z("close",{code:s,reason:o.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});a[se]=this,je(t,this,a)};else if(e==="error")n=function(s){let o=new oe("error",{error:s,message:s.message});o[se]=this,je(t,this,o)};else if(e==="open")n=function(){let s=new $("open");s[se]=this,je(t,this,s)};else return;n[he]=!!r[he],n[wt]=t,r.once?this.once(e,n):this.on(e,n)},removeEventListener(e,t){for(let r of this.listeners(e))if(r[wt]===t&&!r[he]){this.removeListener(e,r);break}}};Nr.exports={CloseEvent:z,ErrorEvent:oe,Event:$,EventTarget:Pi,MessageEvent:pe};function je(e,t,r){typeof e=="object"&&e.handleEvent?e.handleEvent.call(e,r):e.call(t,r)}});var Fe=w((bo,Ir)=>{"use strict";var{tokenChars:me}=re();function D(e,t,r){e[t]===void 0?e[t]=[r]:e[t].push(r)}function Ii(e){let t=Object.create(null),r=Object.create(null),n=!1,i=!1,s=!1,o,a,l=-1,c=-1,f=-1,d=0;for(;d<e.length;d++)if(c=e.charCodeAt(d),o===void 0)if(f===-1&&me[c]===1)l===-1&&(l=d);else if(d!==0&&(c===32||c===9))f===-1&&l!==-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let h=e.slice(l,f);c===44?(D(t,h,r),r=Object.create(null)):o=h,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);else if(a===void 0)if(f===-1&&me[c]===1)l===-1&&(l=d);else if(c===32||c===9)f===-1&&l!==-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d),D(r,e.slice(l,f),!0),c===44&&(D(t,o,r),r=Object.create(null),o=void 0),l=f=-1}else if(c===61&&l!==-1&&f===-1)a=e.slice(l,d),l=f=-1;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(i){if(me[c]!==1)throw new SyntaxError(`Unexpected character at index ${d}`);l===-1?l=d:n||(n=!0),i=!1}else if(s)if(me[c]===1)l===-1&&(l=d);else if(c===34&&l!==-1)s=!1,f=d;else if(c===92)i=!0;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(c===34&&e.charCodeAt(d-1)===61)s=!0;else if(f===-1&&me[c]===1)l===-1&&(l=d);else if(l!==-1&&(c===32||c===9))f===-1&&(f=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);f===-1&&(f=d);let h=e.slice(l,f);n&&(h=h.replace(/\\/g,""),n=!1),D(r,a,h),c===44&&(D(t,o,r),r=Object.create(null),o=void 0),a=void 0,l=f=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);if(l===-1||s||c===32||c===9)throw new SyntaxError("Unexpected end of input");f===-1&&(f=d);let u=e.slice(l,f);return o===void 0?D(t,u,r):(a===void 0?D(r,u,!0):n?D(r,a,u.replace(/\\/g,"")):D(r,a,u),D(t,o,r)),t}function Li(e){return Object.keys(e).map(t=>{let r=e[t];return Array.isArray(r)||(r=[r]),r.map(n=>[t].concat(Object.keys(n).map(i=>{let s=n[i];return Array.isArray(s)||(s=[s]),s.map(o=>o===!0?i:`${i}=${o}`).join("; ")})).join("; ")).join(", ")}).join(", ")}Ir.exports={format:Li,parse:Ii}});var Ge=w((xo,Vr)=>{"use strict";var Di=require("events"),Ri=require("https"),Mi=require("http"),Rr=require("net"),$i=require("tls"),{randomBytes:Bi,createHash:Ui}=require("crypto"),{Duplex:Eo,Readable:vo}=require("stream"),{URL:Tt}=require("url"),F=te(),ji=bt(),Fi=xt(),{isBlob:Wi}=re(),{BINARY_TYPES:Lr,CLOSE_TIMEOUT:qi,EMPTY_BUFFER:We,GUID:Vi,kForOnEventAttribute:kt,kListener:Gi,kStatusCode:Hi,kWebSocket:v,NOOP:Mr}=R(),{EventTarget:{addEventListener:zi,removeEventListener:Ji}}=Pr(),{format:Ki,parse:Yi}=Fe(),{toBuffer:Zi}=ue(),$r=Symbol("kAborted"),Ct=[8,13],B=["CONNECTING","OPEN","CLOSING","CLOSED"],Xi=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,y=class e extends Di{constructor(t,r,n){super(),this._binaryType=Lr[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=We,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=e.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,t!==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]),Br(this,t,r,n)):(this._autoPong=n.autoPong,this._closeTimeout=n.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(t){Lr.includes(t)&&(this._binaryType=t,this._receiver&&(this._receiver._binaryType=t))}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(t,r,n){let i=new ji({allowSynchronousEvents:n.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxBufferedChunks:n.maxBufferedChunks,maxFragments:n.maxFragments,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation}),s=new Fi(t,this._extensions,n.generateMask);this._receiver=i,this._sender=s,this._socket=t,i[v]=this,s[v]=this,t[v]=this,i.on("conclude",ts),i.on("drain",rs),i.on("error",ns),i.on("message",is),i.on("ping",ss),i.on("pong",os),s.onerror=as,t.setTimeout&&t.setTimeout(0),t.setNoDelay&&t.setNoDelay(),r.length>0&&t.unshift(r),t.on("close",Fr),t.on("data",Ve),t.on("end",Wr),t.on("error",qr),this._readyState=e.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=e.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[F.extensionName]&&this._extensions[F.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=e.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(t,r){if(this.readyState!==e.CLOSED){if(this.readyState===e.CONNECTING){T(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===e.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=e.CLOSING,this._sender.close(t,r,!this._isServer,n=>{n||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),jr(this)}}pause(){this.readyState===e.CONNECTING||this.readyState===e.CLOSED||(this._paused=!0,this._socket.pause())}ping(t,r,n){if(this.readyState===e.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(n=t,t=r=void 0):typeof r=="function"&&(n=r,r=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==e.OPEN){Ot(this,t,n);return}r===void 0&&(r=!this._isServer),this._sender.ping(t||We,r,n)}pong(t,r,n){if(this.readyState===e.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(n=t,t=r=void 0):typeof r=="function"&&(n=r,r=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==e.OPEN){Ot(this,t,n);return}r===void 0&&(r=!this._isServer),this._sender.pong(t||We,r,n)}resume(){this.readyState===e.CONNECTING||this.readyState===e.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(t,r,n){if(this.readyState===e.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof r=="function"&&(n=r,r={}),typeof t=="number"&&(t=t.toString()),this.readyState!==e.OPEN){Ot(this,t,n);return}let i={binary:typeof t!="string",mask:!this._isServer,compress:!0,fin:!0,...r};this._extensions[F.extensionName]||(i.compress=!1),this._sender.send(t||We,i,n)}terminate(){if(this.readyState!==e.CLOSED){if(this.readyState===e.CONNECTING){T(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=e.CLOSING,this._socket.destroy())}}};Object.defineProperty(y,"CONNECTING",{enumerable:!0,value:B.indexOf("CONNECTING")});Object.defineProperty(y.prototype,"CONNECTING",{enumerable:!0,value:B.indexOf("CONNECTING")});Object.defineProperty(y,"OPEN",{enumerable:!0,value:B.indexOf("OPEN")});Object.defineProperty(y.prototype,"OPEN",{enumerable:!0,value:B.indexOf("OPEN")});Object.defineProperty(y,"CLOSING",{enumerable:!0,value:B.indexOf("CLOSING")});Object.defineProperty(y.prototype,"CLOSING",{enumerable:!0,value:B.indexOf("CLOSING")});Object.defineProperty(y,"CLOSED",{enumerable:!0,value:B.indexOf("CLOSED")});Object.defineProperty(y.prototype,"CLOSED",{enumerable:!0,value:B.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(e=>{Object.defineProperty(y.prototype,e,{enumerable:!0})});["open","error","close","message"].forEach(e=>{Object.defineProperty(y.prototype,`on${e}`,{enumerable:!0,get(){for(let t of this.listeners(e))if(t[kt])return t[Gi];return null},set(t){for(let r of this.listeners(e))if(r[kt]){this.removeListener(e,r);break}typeof t=="function"&&this.addEventListener(e,t,{[kt]:!0})}})});y.prototype.addEventListener=zi;y.prototype.removeEventListener=Ji;Vr.exports=y;function Br(e,t,r,n){let i={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:qi,protocolVersion:Ct[1],maxBufferedChunks:262144,maxFragments:16384,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(e._autoPong=i.autoPong,e._closeTimeout=i.closeTimeout,!Ct.includes(i.protocolVersion))throw new RangeError(`Unsupported protocol version: ${i.protocolVersion} (supported versions: ${Ct.join(", ")})`);let s;if(t instanceof Tt)s=t;else try{s=new Tt(t)}catch{throw new SyntaxError(`Invalid URL: ${t}`)}s.protocol==="http:"?s.protocol="ws:":s.protocol==="https:"&&(s.protocol="wss:"),e._url=s.href;let o=s.protocol==="wss:",a=s.protocol==="ws+unix:",l;if(s.protocol!=="ws:"&&!o&&!a?l=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:a&&!s.pathname?l="The URL's pathname is empty":s.hash&&(l="The URL contains a fragment identifier"),l){let m=new SyntaxError(l);if(e._redirects===0)throw m;qe(e,m);return}let c=o?443:80,f=Bi(16).toString("base64"),d=o?Ri.request:Mi.request,u=new Set,h;if(i.createConnection=i.createConnection||(o?es:Qi),i.defaultPort=i.defaultPort||c,i.port=s.port||c,i.host=s.hostname.startsWith("[")?s.hostname.slice(1,-1):s.hostname,i.headers={...i.headers,"Sec-WebSocket-Version":i.protocolVersion,"Sec-WebSocket-Key":f,Connection:"Upgrade",Upgrade:"websocket"},i.path=s.pathname+s.search,i.timeout=i.handshakeTimeout,i.perMessageDeflate&&(h=new F({...i.perMessageDeflate,isServer:!1,maxPayload:i.maxPayload}),i.headers["Sec-WebSocket-Extensions"]=Ki({[F.extensionName]:h.offer()})),r.length){for(let m of r){if(typeof m!="string"||!Xi.test(m)||u.has(m))throw new SyntaxError("An invalid or duplicated subprotocol was specified");u.add(m)}i.headers["Sec-WebSocket-Protocol"]=r.join(",")}if(i.origin&&(i.protocolVersion<13?i.headers["Sec-WebSocket-Origin"]=i.origin:i.headers.Origin=i.origin),(s.username||s.password)&&(i.auth=`${s.username}:${s.password}`),a){let m=i.path.split(":");i.socketPath=m[0],i.path=m[1]}let g;if(i.followRedirects){if(e._redirects===0){e._originalIpc=a,e._originalSecure=o,e._originalHostOrSocketPath=a?i.socketPath:s.host;let m=n&&n.headers;if(n={...n,headers:{}},m)for(let[S,E]of Object.entries(m))n.headers[S.toLowerCase()]=E}else if(e.listenerCount("redirect")===0){let m=a?e._originalIpc?i.socketPath===e._originalHostOrSocketPath:!1:e._originalIpc?!1:s.host===e._originalHostOrSocketPath;(!m||e._originalSecure&&!o)&&(delete i.headers.authorization,delete i.headers.cookie,m||delete i.headers.host,i.auth=void 0)}i.auth&&!n.headers.authorization&&(n.headers.authorization="Basic "+Buffer.from(i.auth).toString("base64")),g=e._req=d(i),e._redirects&&e.emit("redirect",e.url,g)}else g=e._req=d(i);i.timeout&&g.on("timeout",()=>{T(e,g,"Opening handshake has timed out")}),g.on("error",m=>{g===null||g[$r]||(g=e._req=null,qe(e,m))}),g.on("response",m=>{let S=m.headers.location,E=m.statusCode;if(S&&i.followRedirects&&E>=300&&E<400){if(++e._redirects>i.maxRedirects){T(e,g,"Maximum redirects exceeded");return}g.abort();let C;try{C=new Tt(S,t)}catch{let X=new SyntaxError(`Invalid URL: ${S}`);qe(e,X);return}Br(e,C,r,n)}else e.emit("unexpected-response",g,m)||T(e,g,`Unexpected server response: ${m.statusCode}`)}),g.on("upgrade",(m,S,E)=>{if(e.emit("upgrade",m),e.readyState!==y.CONNECTING)return;g=e._req=null;let C=m.headers.upgrade;if(C===void 0||C.toLowerCase()!=="websocket"){T(e,S,"Invalid Upgrade header");return}let q=Ui("sha1").update(f+Vi).digest("base64");if(m.headers["sec-websocket-accept"]!==q){T(e,S,"Invalid Sec-WebSocket-Accept header");return}let X=m.headers["sec-websocket-protocol"],ae;if(X!==void 0?u.size?u.has(X)||(ae="Server sent an invalid subprotocol"):ae="Server sent a subprotocol but none was requested":u.size&&(ae="Server sent no subprotocol"),ae){T(e,S,ae);return}X&&(e._protocol=X);let Kt=m.headers["sec-websocket-extensions"];if(Kt!==void 0){if(!h){T(e,S,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let st;try{st=Yi(Kt)}catch{T(e,S,"Invalid Sec-WebSocket-Extensions header");return}let Yt=Object.keys(st);if(Yt.length!==1||Yt[0]!==F.extensionName){T(e,S,"Server indicated an extension that was not requested");return}try{h.accept(st[F.extensionName])}catch{T(e,S,"Invalid Sec-WebSocket-Extensions header");return}e._extensions[F.extensionName]=h}e.setSocket(S,E,{allowSynchronousEvents:i.allowSynchronousEvents,generateMask:i.generateMask,maxBufferedChunks:i.maxBufferedChunks,maxFragments:i.maxFragments,maxPayload:i.maxPayload,skipUTF8Validation:i.skipUTF8Validation})}),i.finishRequest?i.finishRequest(g,e):g.end()}function qe(e,t){e._readyState=y.CLOSING,e._errorEmitted=!0,e.emit("error",t),e.emitClose()}function Qi(e){return e.path=e.socketPath,Rr.connect(e)}function es(e){return e.path=void 0,!e.servername&&e.servername!==""&&(e.servername=Rr.isIP(e.host)?"":e.host),$i.connect(e)}function T(e,t,r){e._readyState=y.CLOSING;let n=new Error(r);Error.captureStackTrace(n,T),t.setHeader?(t[$r]=!0,t.abort(),t.socket&&!t.socket.destroyed&&t.socket.destroy(),process.nextTick(qe,e,n)):(t.destroy(n),t.once("error",e.emit.bind(e,"error")),t.once("close",e.emitClose.bind(e)))}function Ot(e,t,r){if(t){let n=Wi(t)?t.size:Zi(t).length;e._socket?e._sender._bufferedBytes+=n:e._bufferedAmount+=n}if(r){let n=new Error(`WebSocket is not open: readyState ${e.readyState} (${B[e.readyState]})`);process.nextTick(r,n)}}function ts(e,t){let r=this[v];r._closeFrameReceived=!0,r._closeMessage=t,r._closeCode=e,r._socket[v]!==void 0&&(r._socket.removeListener("data",Ve),process.nextTick(Ur,r._socket),e===1005?r.close():r.close(e,t))}function rs(){let e=this[v];e.isPaused||e._socket.resume()}function ns(e){let t=this[v];t._socket[v]!==void 0&&(t._socket.removeListener("data",Ve),process.nextTick(Ur,t._socket),t.close(e[Hi])),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e))}function Dr(){this[v].emitClose()}function is(e,t){this[v].emit("message",e,t)}function ss(e){let t=this[v];t._autoPong&&t.pong(e,!this._isServer,Mr),t.emit("ping",e)}function os(e){this[v].emit("pong",e)}function Ur(e){e.resume()}function as(e){let t=this[v];t.readyState!==y.CLOSED&&(t.readyState===y.OPEN&&(t._readyState=y.CLOSING,jr(t)),this._socket.end(),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e)))}function jr(e){e._closeTimer=setTimeout(e._socket.destroy.bind(e._socket),e._closeTimeout)}function Fr(){let e=this[v];if(this.removeListener("close",Fr),this.removeListener("data",Ve),this.removeListener("end",Wr),e._readyState=y.CLOSING,!this._readableState.endEmitted&&!e._closeFrameReceived&&!e._receiver._writableState.errorEmitted&&this._readableState.length!==0){let t=this.read(this._readableState.length);e._receiver.write(t)}e._receiver.end(),this[v]=void 0,clearTimeout(e._closeTimer),e._receiver._writableState.finished||e._receiver._writableState.errorEmitted?e.emitClose():(e._receiver.on("error",Dr),e._receiver.on("finish",Dr))}function Ve(e){this[v]._receiver.write(e)||this.pause()}function Wr(){let e=this[v];e._readyState=y.CLOSING,e._receiver.end(),this.end()}function qr(){let e=this[v];this.removeListener("error",qr),this.on("error",Mr),e&&(e._readyState=y.CLOSING,this.destroy())}});var Jr=w((To,zr)=>{"use strict";var wo=Ge(),{Duplex:ls}=require("stream");function Gr(e){e.emit("close")}function cs(){!this.destroyed&&this._writableState.finished&&this.destroy()}function Hr(e){this.removeListener("error",Hr),this.destroy(),this.listenerCount("error")===0&&this.emit("error",e)}function fs(e,t){let r=!0,n=new ls({...t,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return e.on("message",function(s,o){let a=!o&&n._readableState.objectMode?s.toString():s;n.push(a)||e.pause()}),e.once("error",function(s){n.destroyed||(r=!1,n.destroy(s))}),e.once("close",function(){n.destroyed||n.push(null)}),n._destroy=function(i,s){if(e.readyState===e.CLOSED){s(i),process.nextTick(Gr,n);return}let o=!1;e.once("error",function(l){o=!0,s(l)}),e.once("close",function(){o||s(i),process.nextTick(Gr,n)}),r&&e.terminate()},n._final=function(i){if(e.readyState===e.CONNECTING){e.once("open",function(){n._final(i)});return}e._socket!==null&&(e._socket._writableState.finished?(i(),n._readableState.endEmitted&&n.destroy()):(e._socket.once("finish",function(){i()}),e.close()))},n._read=function(){e.isPaused&&e.resume()},n._write=function(i,s,o){if(e.readyState===e.CONNECTING){e.once("open",function(){n._write(i,s,o)});return}e.send(i,o)},n.on("end",cs),n.on("error",Hr),n}zr.exports=fs});var At=w((ko,Kr)=>{"use strict";var{tokenChars:us}=re();function ds(e){let t=new Set,r=-1,n=-1,i=0;for(i;i<e.length;i++){let o=e.charCodeAt(i);if(n===-1&&us[o]===1)r===-1&&(r=i);else if(i!==0&&(o===32||o===9))n===-1&&r!==-1&&(n=i);else if(o===44){if(r===-1)throw new SyntaxError(`Unexpected character at index ${i}`);n===-1&&(n=i);let a=e.slice(r,n);if(t.has(a))throw new SyntaxError(`The "${a}" subprotocol is duplicated`);t.add(a),r=n=-1}else throw new SyntaxError(`Unexpected character at index ${i}`)}if(r===-1||n!==-1)throw new SyntaxError("Unexpected end of input");let s=e.slice(r,i);if(t.has(s))throw new SyntaxError(`The "${s}" subprotocol is duplicated`);return t.add(s),t}Kr.exports={parse:ds}});var rn=w((Oo,tn)=>{"use strict";var hs=require("events"),He=require("http"),{Duplex:Co}=require("stream"),{createHash:ps}=require("crypto"),Yr=Fe(),J=te(),ms=At(),gs=Ge(),{CLOSE_TIMEOUT:_s,GUID:ys,kWebSocket:Ss}=R(),bs=/^[+/0-9A-Za-z]{22}==$/,Zr=0,Xr=1,en=2,Nt=class extends hs{constructor(t,r){if(super(),t={allowSynchronousEvents:!0,autoPong:!0,maxBufferedChunks:256*1024,maxFragments:16*1024,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:_s,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:gs,...t},t.port==null&&!t.server&&!t.noServer||t.port!=null&&(t.server||t.noServer)||t.server&&t.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(t.port!=null?(this._server=He.createServer((n,i)=>{let s=He.STATUS_CODES[426];i.writeHead(426,{"Content-Length":s.length,"Content-Type":"text/plain"}),i.end(s)}),this._server.listen(t.port,t.host,t.backlog,r)):t.server&&(this._server=t.server),this._server){let n=this.emit.bind(this,"connection");this._removeListeners=Es(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(i,s,o)=>{this.handleUpgrade(i,s,o,n)}})}t.perMessageDeflate===!0&&(t.perMessageDeflate={}),t.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=t,this._state=Zr}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(t){if(this._state===en){t&&this.once("close",()=>{t(new Error("The server is not running"))}),process.nextTick(ge,this);return}if(t&&this.once("close",t),this._state!==Xr)if(this._state=Xr,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(ge,this):process.nextTick(ge,this);else{let r=this._server;this._removeListeners(),this._removeListeners=this._server=null,r.close(()=>{ge(this)})}}shouldHandle(t){if(this.options.path){let r=t.url.indexOf("?");if((r!==-1?t.url.slice(0,r):t.url)!==this.options.path)return!1}return!0}handleUpgrade(t,r,n,i){r.on("error",Qr);let s=t.headers["sec-websocket-key"],o=t.headers.upgrade,a=+t.headers["sec-websocket-version"];if(t.method!=="GET"){K(this,t,r,405,"Invalid HTTP method");return}if(o===void 0||o.toLowerCase()!=="websocket"){K(this,t,r,400,"Invalid Upgrade header");return}if(s===void 0||!bs.test(s)){K(this,t,r,400,"Missing or invalid Sec-WebSocket-Key header");return}if(a!==13&&a!==8){K(this,t,r,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(t)){_e(r,400);return}let l=t.headers["sec-websocket-protocol"],c=new Set;if(l!==void 0)try{c=ms.parse(l)}catch{K(this,t,r,400,"Invalid Sec-WebSocket-Protocol header");return}let f=t.headers["sec-websocket-extensions"],d={};if(this.options.perMessageDeflate&&f!==void 0){let u=new J({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let h=Yr.parse(f);h[J.extensionName]&&(u.accept(h[J.extensionName]),d[J.extensionName]=u)}catch{K(this,t,r,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let u={origin:t.headers[`${a===8?"sec-websocket-origin":"origin"}`],secure:!!(t.socket.authorized||t.socket.encrypted),req:t};if(this.options.verifyClient.length===2){this.options.verifyClient(u,(h,g,m,S)=>{if(!h)return _e(r,g||401,m,S);this.completeUpgrade(d,s,c,t,r,n,i)});return}if(!this.options.verifyClient(u))return _e(r,401)}this.completeUpgrade(d,s,c,t,r,n,i)}completeUpgrade(t,r,n,i,s,o,a){if(!s.readable||!s.writable)return s.destroy();if(s[Ss])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>Zr)return _e(s,503);let c=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${ps("sha1").update(r+ys).digest("base64")}`],f=new this.options.WebSocket(null,void 0,this.options);if(n.size){let d=this.options.handleProtocols?this.options.handleProtocols(n,i):n.values().next().value;d&&(c.push(`Sec-WebSocket-Protocol: ${d}`),f._protocol=d)}if(t[J.extensionName]){let d=t[J.extensionName].params,u=Yr.format({[J.extensionName]:[d]});c.push(`Sec-WebSocket-Extensions: ${u}`),f._extensions=t}this.emit("headers",c,i),s.write(c.concat(`\r
2
+ "use strict";var di=Object.create;var St=Object.defineProperty;var hi=Object.getOwnPropertyDescriptor;var pi=Object.getOwnPropertyNames;var mi=Object.getPrototypeOf,gi=Object.prototype.hasOwnProperty;var y=(e,t)=>()=>(e&&(t=e(e=0)),t);var T=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),vt=(e,t)=>{for(var r in t)St(e,r,{get:t[r],enumerable:!0})},_i=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of pi(t))!gi.call(e,i)&&i!==r&&St(e,i,{get:()=>t[i],enumerable:!(n=hi(t,i))||n.enumerable});return e};var j=(e,t,r)=>(r=e!=null?di(mi(e)):{},_i(t||!e||!e.__esModule?St(r,"default",{value:e,enumerable:!0}):r,e));function x(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function ue(e){return new Promise((t,r)=>{let n=0,i=[],s=!1,o=(a,l)=>{s||(s=!0,i.length=0,r(Object.assign(new Error(l),{status:a})))};e.on("data",a=>{if(s)return;let l=Buffer.isBuffer(a)?a:Buffer.from(a);if(n+=l.length,n>256e3){o(413,"body too large");return}i.push(l)}),e.on("end",()=>{if(!s)try{let a=JSON.parse(Buffer.concat(i).toString("utf8")||"{}");if(!x(a)){o(400,"JSON body must be an object");return}s=!0,t(a)}catch{o(400,"Invalid JSON")}}),e.on("error",()=>o(400,"Request interrupted")),e.on("close",()=>{s||o(400,"Request interrupted")})})}var Re=y(()=>{"use strict"});function $e(e){return de.find(t=>t.name===e)}var V,yi,Et,bi,de,Me=y(()=>{"use strict";V={type:"object",description:"Semantic target: durable ref (@Hxxxx) or role/name/region query.",properties:{ref:{type:"string"},role:{type:"string"},name:{type:"string"},nameContains:{type:"string"},label:{type:"string"},region:{type:"string"}}},yi={type:"object",description:"Postcondition to verify after dispatch (url_changed, url_matches, element_appeared, element_disappeared, value_equals, value_changed, navigation_completed, etc.).",properties:{type:{type:"string",enum:["url_changed","url_matches","element_appeared","element_disappeared","value_equals","value_changed","checked","selection_changed","title_changed","navigation_completed","region_changed"]},value:{type:"string"},query:V,regionId:{type:"string"}},required:["type"],additionalProperties:!0},Et={type:"array",description:"Postconditions to verify after dispatch.",items:yi},bi={type:"object",description:"Single guarded action contract.",properties:{action:{type:"string",enum:["click","fill","select","press","scroll","navigate","back","forward","hover"]},target:V,value:{type:"string"},key:{type:"string"},url:{type:"string"},expect:Et,timeoutMs:{type:"number"}},required:["action"],additionalProperties:!0},de=[{name:"browser_observe",description:"Compact page/region digest of the controlled tab.",inputSchema:{type:"object",properties:{level:{type:"string"},regionId:{type:"string"},includeRecentDiff:{type:"boolean"}}},scope:"browser:read"},{name:"browser_find",description:"Fast semantic lookup returning durable refs.",inputSchema:{type:"object",properties:{role:{type:"string"},name:{type:"string"},nameContains:{type:"string"},region:{type:"string"}}},scope:"browser:read"},{name:"browser_click",description:"Click a semantic target (guarded, verified).",inputSchema:{type:"object",properties:{target:V,expect:Et},required:["target"]},scope:"browser:act"},{name:"browser_fill",description:"Fill a field and verify the value.",inputSchema:{type:"object",properties:{target:V,value:{type:"string"},expect:Et},required:["target","value"]},scope:"browser:act"},{name:"browser_select",description:"Choose a select option.",inputSchema:{type:"object",properties:{target:V,value:{type:"string"}},required:["target","value"]},scope:"browser:act"},{name:"browser_press",description:"Press a key on a target or the focused element.",inputSchema:{type:"object",properties:{target:V,key:{type:"string"}}},scope:"browser:act"},{name:"browser_scroll",description:"Scroll a target into view or scroll the page.",inputSchema:{type:"object",properties:{target:V,direction:{type:"string"}}},scope:"browser:act"},{name:"browser_navigate",description:"Navigate the controlled tab (site grant required).",inputSchema:{type:"object",properties:{url:{type:"string"}},required:["url"]},scope:"browser:act"},{name:"browser_back",description:"Tab history back.",inputSchema:{type:"object",properties:{}},scope:"browser:act"},{name:"browser_forward",description:"Tab history forward.",inputSchema:{type:"object",properties:{}},scope:"browser:act"},{name:"browser_tabs",description:"List open tabs.",inputSchema:{type:"object",properties:{}},scope:"browser:read"},{name:"browser_switch_tab",description:"Switch control to another tab.",inputSchema:{type:"object",properties:{tabId:{type:"number"}},required:["tabId"]},scope:"browser:act"},{name:"browser_screenshot",description:"Capture the visible tab (rate-limited fallback).",inputSchema:{type:"object",properties:{}},scope:"browser:read"},{name:"browser_extract",description:"Extract text/table data plus article body paragraphs (passwords never returned).",inputSchema:{type:"object",properties:{regionId:{type:"string"},maxRows:{type:"number"}}},scope:"browser:read"},{name:"browser_wait",description:"Wait for a condition or timeout.",inputSchema:{type:"object",properties:{timeoutMs:{type:"number"},urlMatches:{type:"string"}}},scope:"browser:read"},{name:"browser_plan",description:"Guarded micro-plan: multiple verified steps, one decision.",inputSchema:{type:"object",properties:{steps:{type:"array",description:"Ordered guarded steps (1-25).",items:bi},abortOn:{type:"array",description:"Abort conditions (defaults to all four).",items:{type:"string",enum:["navigation","ambiguous_target","permission_required","page_epoch_changed"]}}},required:["steps"]},scope:"browser:act"}]});var pr={};vt(pr,{extractBearer:()=>he,hasScope:()=>hr,tokenAllows:()=>pe});function he(e){let t=Array.isArray(e)?e[0]:e;if(!t)return null;let r=/^Bearer\s+(.+)$/i.exec(t.trim());return r?r[1].trim():null}function hr(e,t){return e.includes("*")||e.includes(t)}function pe(e,t){return e?hr(e.scopes,t):!1}var me=y(()=>{"use strict"});var $=T((Do,_r)=>{"use strict";var mr=["nodebuffer","arraybuffer","fragments"],gr=typeof Blob<"u";gr&&mr.push("blob");_r.exports={BINARY_TYPES:mr,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:gr,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var ge=T((Lo,Be)=>{"use strict";var{EMPTY_BUFFER:Si}=$(),wt=Buffer[Symbol.species];function vi(e,t){if(e.length===0)return Si;if(e.length===1)return e[0];let r=Buffer.allocUnsafe(t),n=0;for(let i=0;i<e.length;i++){let s=e[i];r.set(s,n),n+=s.length}return n<t?new wt(r.buffer,r.byteOffset,n):r}function yr(e,t,r,n,i){for(let s=0;s<i;s++)r[n+s]=e[s]^t[s&3]}function br(e,t){for(let r=0;r<e.length;r++)e[r]^=t[r&3]}function Ei(e){return e.length===e.buffer.byteLength?e.buffer:e.buffer.slice(e.byteOffset,e.byteOffset+e.length)}function xt(e){if(xt.readOnly=!0,Buffer.isBuffer(e))return e;let t;return e instanceof ArrayBuffer?t=new wt(e):ArrayBuffer.isView(e)?t=new wt(e.buffer,e.byteOffset,e.byteLength):(t=Buffer.from(e),xt.readOnly=!1),t}Be.exports={concat:vi,mask:yr,toArrayBuffer:Ei,toBuffer:xt,unmask:br};if(!process.env.WS_NO_BUFFER_UTIL)try{let e=require("bufferutil");Be.exports.mask=function(t,r,n,i,s){s<48?yr(t,r,n,i,s):e.mask(t,r,n,i,s)},Be.exports.unmask=function(t,r){t.length<32?br(t,r):e.unmask(t,r)}}catch{}});var Er=T((Ro,vr)=>{"use strict";var Sr=Symbol("kDone"),Tt=Symbol("kRun"),kt=class{constructor(t){this[Sr]=()=>{this.pending--,this[Tt]()},this.concurrency=t||1/0,this.jobs=[],this.pending=0}add(t){this.jobs.push(t),this[Tt]()}[Tt](){if(this.pending!==this.concurrency&&this.jobs.length){let t=this.jobs.shift();this.pending++,t(this[Sr])}}};vr.exports=kt});var ne=T(($o,kr)=>{"use strict";var _e=require("zlib"),wr=ge(),wi=Er(),{kStatusCode:xr}=$(),xi=Buffer[Symbol.species],Ti=Buffer.from([0,0,255,255]),je=Symbol("permessage-deflate"),M=Symbol("total-length"),te=Symbol("callback"),F=Symbol("buffers"),re=Symbol("error"),Ue,Ct=class{constructor(t){if(this._options=t||{},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,!Ue){let r=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;Ue=new wi(r)}}static get extensionName(){return"permessage-deflate"}offer(){let t={};return this._options.serverNoContextTakeover&&(t.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(t.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(t.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?t.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(t.client_max_window_bits=!0),t}accept(t){return t=this.normalizeParams(t),this.params=this._isServer?this.acceptAsServer(t):this.acceptAsClient(t),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let t=this._deflate[te];this._deflate.close(),this._deflate=null,t&&t(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(t){let r=this._options,n=t.find(i=>!(r.serverNoContextTakeover===!1&&i.server_no_context_takeover||i.server_max_window_bits&&(r.serverMaxWindowBits===!1||typeof r.serverMaxWindowBits=="number"&&r.serverMaxWindowBits>i.server_max_window_bits)||typeof r.clientMaxWindowBits=="number"&&(typeof i.client_max_window_bits=="number"?r.clientMaxWindowBits>i.client_max_window_bits:!i.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(t){let r=t[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(t){return t.forEach(r=>{Object.keys(r).forEach(n=>{let i=r[n];if(i.length>1)throw new Error(`Parameter "${n}" must have only a single value`);if(i=i[0],n==="client_max_window_bits"){if(i!==!0){let s=+i;if(!Number.isInteger(s)||s<8||s>15)throw new TypeError(`Invalid value for parameter "${n}": ${i}`);i=s}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${n}": ${i}`)}else if(n==="server_max_window_bits"){let s=+i;if(!Number.isInteger(s)||s<8||s>15)throw new TypeError(`Invalid value for parameter "${n}": ${i}`);i=s}else if(n==="client_no_context_takeover"||n==="server_no_context_takeover"){if(i!==!0)throw new TypeError(`Invalid value for parameter "${n}": ${i}`)}else throw new Error(`Unknown parameter "${n}"`);r[n]=i})}),t}decompress(t,r,n){Ue.add(i=>{this._decompress(t,r,(s,o)=>{i(),n(s,o)})})}compress(t,r,n){Ue.add(i=>{this._compress(t,r,(s,o)=>{i(),n(s,o)})})}_decompress(t,r,n){let i=this._isServer?"client":"server";if(!this._inflate){let s=`${i}_max_window_bits`,o=typeof this.params[s]!="number"?_e.Z_DEFAULT_WINDOWBITS:this.params[s];this._inflate=_e.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[je]=this,this._inflate[M]=0,this._inflate[F]=[],this._inflate.on("error",Ci),this._inflate.on("data",Tr)}this._inflate[te]=n,this._inflate.write(t),r&&this._inflate.write(Ti),this._inflate.flush(()=>{let s=this._inflate[re];if(s){this._inflate.close(),this._inflate=null,n(s);return}let o=wr.concat(this._inflate[F],this._inflate[M]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[M]=0,this._inflate[F]=[],r&&this.params[`${i}_no_context_takeover`]&&this._inflate.reset()),n(null,o)})}_compress(t,r,n){let i=this._isServer?"server":"client";if(!this._deflate){let s=`${i}_max_window_bits`,o=typeof this.params[s]!="number"?_e.Z_DEFAULT_WINDOWBITS:this.params[s];this._deflate=_e.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[M]=0,this._deflate[F]=[],this._deflate.on("data",ki)}this._deflate[te]=n,this._deflate.write(t),this._deflate.flush(_e.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let s=wr.concat(this._deflate[F],this._deflate[M]);r&&(s=new xi(s.buffer,s.byteOffset,s.length-4)),this._deflate[te]=null,this._deflate[M]=0,this._deflate[F]=[],r&&this.params[`${i}_no_context_takeover`]&&this._deflate.reset(),n(null,s)})}};kr.exports=Ct;function ki(e){this[F].push(e),this[M]+=e.length}function Tr(e){if(this[M]+=e.length,this[je]._maxPayload<1||this[M]<=this[je]._maxPayload){this[F].push(e);return}this[re]=new RangeError("Max payload size exceeded"),this[re].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[re][xr]=1009,this.removeListener("data",Tr),this.reset()}function Ci(e){if(this[je]._inflate=null,this[re]){this[te](this[re]);return}e[xr]=1007,this[te](e)}});var ie=T((Mo,Fe)=>{"use strict";var{isUtf8:Cr}=require("buffer"),{hasBlob:Oi}=$(),Ai=[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 Ni(e){return e>=1e3&&e<=1014&&e!==1004&&e!==1005&&e!==1006||e>=3e3&&e<=4999}function Ot(e){let t=e.length,r=0;for(;r<t;)if(!(e[r]&128))r++;else if((e[r]&224)===192){if(r+1===t||(e[r+1]&192)!==128||(e[r]&254)===192)return!1;r+=2}else if((e[r]&240)===224){if(r+2>=t||(e[r+1]&192)!==128||(e[r+2]&192)!==128||e[r]===224&&(e[r+1]&224)===128||e[r]===237&&(e[r+1]&224)===160)return!1;r+=3}else if((e[r]&248)===240){if(r+3>=t||(e[r+1]&192)!==128||(e[r+2]&192)!==128||(e[r+3]&192)!==128||e[r]===240&&(e[r+1]&240)===128||e[r]===244&&e[r+1]>143||e[r]>244)return!1;r+=4}else return!1;return!0}function Pi(e){return Oi&&typeof e=="object"&&typeof e.arrayBuffer=="function"&&typeof e.type=="string"&&typeof e.stream=="function"&&(e[Symbol.toStringTag]==="Blob"||e[Symbol.toStringTag]==="File")}Fe.exports={isBlob:Pi,isValidStatusCode:Ni,isValidUTF8:Ot,tokenChars:Ai};if(Cr)Fe.exports.isValidUTF8=function(e){return e.length<24?Ot(e):Cr(e)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let e=require("utf-8-validate");Fe.exports.isValidUTF8=function(t){return t.length<32?Ot(t):e(t)}}catch{}});var Dt=T((Bo,Lr)=>{"use strict";var{Writable:Ii}=require("stream"),Or=ne(),{BINARY_TYPES:Di,EMPTY_BUFFER:Ar,kStatusCode:Li,kWebSocket:Ri}=$(),{concat:At,toArrayBuffer:$i,unmask:Mi}=ge(),{isValidStatusCode:Bi,isValidUTF8:Nr}=ie(),We=Buffer[Symbol.species],A=0,Pr=1,Ir=2,Dr=3,Nt=4,Pt=5,qe=6,It=class extends Ii{constructor(t={}){super(),this._allowSynchronousEvents=t.allowSynchronousEvents!==void 0?t.allowSynchronousEvents:!0,this._binaryType=t.binaryType||Di[0],this._extensions=t.extensions||{},this._isServer=!!t.isServer,this._maxBufferedChunks=t.maxBufferedChunks|0,this._maxFragments=t.maxFragments|0,this._maxPayload=t.maxPayload|0,this._skipUTF8Validation=!!t.skipUTF8Validation,this[Ri]=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._numFragments=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=A}_write(t,r,n){if(this._opcode===8&&this._state==A)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+=t.length,this._buffers.push(t),this.startLoop(n)}consume(t){if(this._bufferedBytes-=t,t===this._buffers[0].length)return this._buffers.shift();if(t<this._buffers[0].length){let n=this._buffers[0];return this._buffers[0]=new We(n.buffer,n.byteOffset+t,n.length-t),new We(n.buffer,n.byteOffset,t)}let r=Buffer.allocUnsafe(t);do{let n=this._buffers[0],i=r.length-t;t>=n.length?r.set(this._buffers.shift(),i):(r.set(new Uint8Array(n.buffer,n.byteOffset,t),i),this._buffers[0]=new We(n.buffer,n.byteOffset+t,n.length-t)),t-=n.length}while(t>0);return r}startLoop(t){this._loop=!0;do switch(this._state){case A:this.getInfo(t);break;case Pr:this.getPayloadLength16(t);break;case Ir:this.getPayloadLength64(t);break;case Dr:this.getMask();break;case Nt:this.getData(t);break;case Pt:case qe:this._loop=!1;return}while(this._loop);this._errored||t()}getInfo(t){if(this._bufferedBytes<2){this._loop=!1;return}let r=this.consume(2);if(r[0]&48){let i=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");t(i);return}let n=(r[0]&64)===64;if(n&&!this._extensions[Or.extensionName]){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(i);return}if(this._fin=(r[0]&128)===128,this._opcode=r[0]&15,this._payloadLength=r[1]&127,this._opcode===0){if(n){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(i);return}if(!this._fragmented){let i=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");t(i);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let i=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(i);return}this._compressed=n}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let i=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");t(i);return}if(n){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(i);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let i=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");t(i);return}}else{let i=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(i);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(r[1]&128)===128,this._isServer){if(!this._masked){let i=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");t(i);return}}else if(this._masked){let i=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");t(i);return}this._payloadLength===126?this._state=Pr:this._payloadLength===127?this._state=Ir:this.haveLength(t)}getPayloadLength16(t){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(t)}getPayloadLength64(t){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 i=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");t(i);return}this._payloadLength=n*Math.pow(2,32)+r.readUInt32BE(4),this.haveLength(t)}haveLength(t){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");t(r);return}this._masked?this._state=Dr:this._state=Nt}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=Nt}getData(t){let r=Ar;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]&&Mi(r,this._mask)}if(this._opcode>7){this.controlMessage(r,t);return}if(this._maxFragments>0&&++this._numFragments>this._maxFragments){let n=this.createError(RangeError,"Too many message fragments",!1,1008,"WS_ERR_TOO_MANY_BUFFERED_PARTS");t(n);return}if(this._compressed){this._state=Pt,this.decompress(r,t);return}r.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(r)),this.dataMessage(t)}decompress(t,r){this._extensions[Or.extensionName].decompress(t,this._fin,(i,s)=>{if(i)return r(i);if(s.length){if(this._messageLength+=s.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}this._fragments.push(s)}this.dataMessage(r),this._state===A&&this.startLoop(r)})}dataMessage(t){if(!this._fin){this._state=A;return}let r=this._messageLength,n=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._numFragments=0,this._fragments=[],this._opcode===2){let i;this._binaryType==="nodebuffer"?i=At(n,r):this._binaryType==="arraybuffer"?i=$i(At(n,r)):this._binaryType==="blob"?i=new Blob(n):i=n,this._allowSynchronousEvents?(this.emit("message",i,!0),this._state=A):(this._state=qe,setImmediate(()=>{this.emit("message",i,!0),this._state=A,this.startLoop(t)}))}else{let i=At(n,r);if(!this._skipUTF8Validation&&!Nr(i)){let s=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");t(s);return}this._state===Pt||this._allowSynchronousEvents?(this.emit("message",i,!1),this._state=A):(this._state=qe,setImmediate(()=>{this.emit("message",i,!1),this._state=A,this.startLoop(t)}))}}controlMessage(t,r){if(this._opcode===8){if(t.length===0)this._loop=!1,this.emit("conclude",1005,Ar),this.end();else{let n=t.readUInt16BE(0);if(!Bi(n)){let s=this.createError(RangeError,`invalid status code ${n}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");r(s);return}let i=new We(t.buffer,t.byteOffset+2,t.length-2);if(!this._skipUTF8Validation&&!Nr(i)){let s=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");r(s);return}this._loop=!1,this.emit("conclude",n,i),this.end()}this._state=A;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",t),this._state=A):(this._state=qe,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",t),this._state=A,this.startLoop(r)}))}createError(t,r,n,i,s){this._loop=!1,this._errored=!0;let o=new t(n?`Invalid WebSocket frame: ${r}`:r);return Error.captureStackTrace(o,this.createError),o.code=s,o[Li]=i,o}};Lr.exports=It});var $t=T((jo,Mr)=>{"use strict";var{Duplex:Uo}=require("stream"),{randomFillSync:Ui}=require("crypto"),{types:{isUint8Array:ji}}=require("util"),Rr=ne(),{EMPTY_BUFFER:Fi,kWebSocket:Wi,NOOP:qi}=$(),{isBlob:se,isValidStatusCode:Gi}=ie(),{mask:$r,toBuffer:H}=ge(),N=Symbol("kByteLength"),Vi=Buffer.alloc(4),Ge=8*1024,z,oe=Ge,P=0,Hi=1,zi=2,Lt=class e{constructor(t,r,n){this._extensions=r||{},n&&(this._generateMask=n,this._maskBuffer=Buffer.alloc(4)),this._socket=t,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=P,this.onerror=qi,this[Wi]=void 0}static frame(t,r){let n,i=!1,s=2,o=!1;r.mask&&(n=r.maskBuffer||Vi,r.generateMask?r.generateMask(n):(oe===Ge&&(z===void 0&&(z=Buffer.alloc(Ge)),Ui(z,0,Ge),oe=0),n[0]=z[oe++],n[1]=z[oe++],n[2]=z[oe++],n[3]=z[oe++]),o=(n[0]|n[1]|n[2]|n[3])===0,s=6);let a;typeof t=="string"?(!r.mask||o)&&r[N]!==void 0?a=r[N]:(t=Buffer.from(t),a=t.length):(a=t.length,i=r.mask&&r.readOnly&&!o);let l=a;a>=65536?(s+=8,l=127):a>125&&(s+=2,l=126);let c=Buffer.allocUnsafe(i?a+s:s);return c[0]=r.fin?r.opcode|128:r.opcode,r.rsv1&&(c[0]|=64),c[1]=l,l===126?c.writeUInt16BE(a,2):l===127&&(c[2]=c[3]=0,c.writeUIntBE(a,4,6)),r.mask?(c[1]|=128,c[s-4]=n[0],c[s-3]=n[1],c[s-2]=n[2],c[s-1]=n[3],o?[c,t]:i?($r(t,n,c,s,a),[c]):($r(t,n,t,0,a),[c,t])):[c,t]}close(t,r,n,i){let s;if(t===void 0)s=Fi;else{if(typeof t!="number"||!Gi(t))throw new TypeError("First argument must be a valid error code number");if(r===void 0||!r.length)s=Buffer.allocUnsafe(2),s.writeUInt16BE(t,0);else{let a=Buffer.byteLength(r);if(a>123)throw new RangeError("The message must not be greater than 123 bytes");if(s=Buffer.allocUnsafe(2+a),s.writeUInt16BE(t,0),typeof r=="string")s.write(r,2);else if(ji(r))s.set(r,2);else throw new TypeError("Second argument must be a string or a Uint8Array")}}let o={[N]:s.length,fin:!0,generateMask:this._generateMask,mask:n,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==P?this.enqueue([this.dispatch,s,!1,o,i]):this.sendFrame(e.frame(s,o),i)}ping(t,r,n){let i,s;if(typeof t=="string"?(i=Buffer.byteLength(t),s=!1):se(t)?(i=t.size,s=!1):(t=H(t),i=t.length,s=H.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[N]:i,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:9,readOnly:s,rsv1:!1};se(t)?this._state!==P?this.enqueue([this.getBlobData,t,!1,o,n]):this.getBlobData(t,!1,o,n):this._state!==P?this.enqueue([this.dispatch,t,!1,o,n]):this.sendFrame(e.frame(t,o),n)}pong(t,r,n){let i,s;if(typeof t=="string"?(i=Buffer.byteLength(t),s=!1):se(t)?(i=t.size,s=!1):(t=H(t),i=t.length,s=H.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[N]:i,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:10,readOnly:s,rsv1:!1};se(t)?this._state!==P?this.enqueue([this.getBlobData,t,!1,o,n]):this.getBlobData(t,!1,o,n):this._state!==P?this.enqueue([this.dispatch,t,!1,o,n]):this.sendFrame(e.frame(t,o),n)}send(t,r,n){let i=this._extensions[Rr.extensionName],s=r.binary?2:1,o=r.compress,a,l;typeof t=="string"?(a=Buffer.byteLength(t),l=!1):se(t)?(a=t.size,l=!1):(t=H(t),a=t.length,l=H.readOnly),this._firstFragment?(this._firstFragment=!1,o&&i&&i.params[i._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(o=a>=i._threshold),this._compress=o):(o=!1,s=0),r.fin&&(this._firstFragment=!0);let c={[N]:a,fin:r.fin,generateMask:this._generateMask,mask:r.mask,maskBuffer:this._maskBuffer,opcode:s,readOnly:l,rsv1:o};se(t)?this._state!==P?this.enqueue([this.getBlobData,t,this._compress,c,n]):this.getBlobData(t,this._compress,c,n):this._state!==P?this.enqueue([this.dispatch,t,this._compress,c,n]):this.dispatch(t,this._compress,c,n)}getBlobData(t,r,n,i){this._bufferedBytes+=n[N],this._state=zi,t.arrayBuffer().then(s=>{if(this._socket.destroyed){let a=new Error("The socket was closed while the blob was being read");process.nextTick(Rt,this,a,i);return}this._bufferedBytes-=n[N];let o=H(s);r?this.dispatch(o,r,n,i):(this._state=P,this.sendFrame(e.frame(o,n),i),this.dequeue())}).catch(s=>{process.nextTick(Ji,this,s,i)})}dispatch(t,r,n,i){if(!r){this.sendFrame(e.frame(t,n),i);return}let s=this._extensions[Rr.extensionName];this._bufferedBytes+=n[N],this._state=Hi,s.compress(t,n.fin,(o,a)=>{if(this._socket.destroyed){let l=new Error("The socket was closed while data was being compressed");Rt(this,l,i);return}this._bufferedBytes-=n[N],this._state=P,n.readOnly=!1,this.sendFrame(e.frame(a,n),i),this.dequeue()})}dequeue(){for(;this._state===P&&this._queue.length;){let t=this._queue.shift();this._bufferedBytes-=t[3][N],Reflect.apply(t[0],this,t.slice(1))}}enqueue(t){this._bufferedBytes+=t[3][N],this._queue.push(t)}sendFrame(t,r){t.length===2?(this._socket.cork(),this._socket.write(t[0]),this._socket.write(t[1],r),this._socket.uncork()):this._socket.write(t[0],r)}};Mr.exports=Lt;function Rt(e,t,r){typeof r=="function"&&r(t);for(let n=0;n<e._queue.length;n++){let i=e._queue[n],s=i[i.length-1];typeof s=="function"&&s(t)}}function Ji(e,t,r){Rt(e,t,r),e.onerror(t)}});var Hr=T((Fo,Vr)=>{"use strict";var{kForOnEventAttribute:ye,kListener:Mt}=$(),Br=Symbol("kCode"),Ur=Symbol("kData"),jr=Symbol("kError"),Fr=Symbol("kMessage"),Wr=Symbol("kReason"),ae=Symbol("kTarget"),qr=Symbol("kType"),Gr=Symbol("kWasClean"),B=class{constructor(t){this[ae]=null,this[qr]=t}get target(){return this[ae]}get type(){return this[qr]}};Object.defineProperty(B.prototype,"target",{enumerable:!0});Object.defineProperty(B.prototype,"type",{enumerable:!0});var J=class extends B{constructor(t,r={}){super(t),this[Br]=r.code===void 0?0:r.code,this[Wr]=r.reason===void 0?"":r.reason,this[Gr]=r.wasClean===void 0?!1:r.wasClean}get code(){return this[Br]}get reason(){return this[Wr]}get wasClean(){return this[Gr]}};Object.defineProperty(J.prototype,"code",{enumerable:!0});Object.defineProperty(J.prototype,"reason",{enumerable:!0});Object.defineProperty(J.prototype,"wasClean",{enumerable:!0});var le=class extends B{constructor(t,r={}){super(t),this[jr]=r.error===void 0?null:r.error,this[Fr]=r.message===void 0?"":r.message}get error(){return this[jr]}get message(){return this[Fr]}};Object.defineProperty(le.prototype,"error",{enumerable:!0});Object.defineProperty(le.prototype,"message",{enumerable:!0});var be=class extends B{constructor(t,r={}){super(t),this[Ur]=r.data===void 0?null:r.data}get data(){return this[Ur]}};Object.defineProperty(be.prototype,"data",{enumerable:!0});var Ki={addEventListener(e,t,r={}){for(let i of this.listeners(e))if(!r[ye]&&i[Mt]===t&&!i[ye])return;let n;if(e==="message")n=function(s,o){let a=new be("message",{data:o?s:s.toString()});a[ae]=this,Ve(t,this,a)};else if(e==="close")n=function(s,o){let a=new J("close",{code:s,reason:o.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});a[ae]=this,Ve(t,this,a)};else if(e==="error")n=function(s){let o=new le("error",{error:s,message:s.message});o[ae]=this,Ve(t,this,o)};else if(e==="open")n=function(){let s=new B("open");s[ae]=this,Ve(t,this,s)};else return;n[ye]=!!r[ye],n[Mt]=t,r.once?this.once(e,n):this.on(e,n)},removeEventListener(e,t){for(let r of this.listeners(e))if(r[Mt]===t&&!r[ye]){this.removeListener(e,r);break}}};Vr.exports={CloseEvent:J,ErrorEvent:le,Event:B,EventTarget:Ki,MessageEvent:be};function Ve(e,t,r){typeof e=="object"&&e.handleEvent?e.handleEvent.call(e,r):e.call(t,r)}});var He=T((Wo,zr)=>{"use strict";var{tokenChars:Se}=ie();function R(e,t,r){e[t]===void 0?e[t]=[r]:e[t].push(r)}function Yi(e){let t=Object.create(null),r=Object.create(null),n=!1,i=!1,s=!1,o,a,l=-1,c=-1,u=-1,d=0;for(;d<e.length;d++)if(c=e.charCodeAt(d),o===void 0)if(u===-1&&Se[c]===1)l===-1&&(l=d);else if(d!==0&&(c===32||c===9))u===-1&&l!==-1&&(u=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);u===-1&&(u=d);let h=e.slice(l,u);c===44?(R(t,h,r),r=Object.create(null)):o=h,l=u=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);else if(a===void 0)if(u===-1&&Se[c]===1)l===-1&&(l=d);else if(c===32||c===9)u===-1&&l!==-1&&(u=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);u===-1&&(u=d),R(r,e.slice(l,u),!0),c===44&&(R(t,o,r),r=Object.create(null),o=void 0),l=u=-1}else if(c===61&&l!==-1&&u===-1)a=e.slice(l,d),l=u=-1;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(i){if(Se[c]!==1)throw new SyntaxError(`Unexpected character at index ${d}`);l===-1?l=d:n||(n=!0),i=!1}else if(s)if(Se[c]===1)l===-1&&(l=d);else if(c===34&&l!==-1)s=!1,u=d;else if(c===92)i=!0;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(c===34&&e.charCodeAt(d-1)===61)s=!0;else if(u===-1&&Se[c]===1)l===-1&&(l=d);else if(l!==-1&&(c===32||c===9))u===-1&&(u=d);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${d}`);u===-1&&(u=d);let h=e.slice(l,u);n&&(h=h.replace(/\\/g,""),n=!1),R(r,a,h),c===44&&(R(t,o,r),r=Object.create(null),o=void 0),a=void 0,l=u=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);if(l===-1||s||c===32||c===9)throw new SyntaxError("Unexpected end of input");u===-1&&(u=d);let f=e.slice(l,u);return o===void 0?R(t,f,r):(a===void 0?R(r,f,!0):n?R(r,a,f.replace(/\\/g,"")):R(r,a,f),R(t,o,r)),t}function Zi(e){return Object.keys(e).map(t=>{let r=e[t];return Array.isArray(r)||(r=[r]),r.map(n=>[t].concat(Object.keys(n).map(i=>{let s=n[i];return Array.isArray(s)||(s=[s]),s.map(o=>o===!0?i:`${i}=${o}`).join("; ")})).join("; ")).join(", ")}).join(", ")}zr.exports={format:Zi,parse:Yi}});var Ye=T((Vo,on)=>{"use strict";var Xi=require("events"),Qi=require("https"),es=require("http"),Yr=require("net"),ts=require("tls"),{randomBytes:rs,createHash:ns}=require("crypto"),{Duplex:qo,Readable:Go}=require("stream"),{URL:Bt}=require("url"),W=ne(),is=Dt(),ss=$t(),{isBlob:os}=ie(),{BINARY_TYPES:Jr,CLOSE_TIMEOUT:as,EMPTY_BUFFER:ze,GUID:ls,kForOnEventAttribute:Ut,kListener:cs,kStatusCode:fs,kWebSocket:w,NOOP:Zr}=$(),{EventTarget:{addEventListener:us,removeEventListener:ds}}=Hr(),{format:hs,parse:ps}=He(),{toBuffer:ms}=ge(),Xr=Symbol("kAborted"),jt=[8,13],U=["CONNECTING","OPEN","CLOSING","CLOSED"],gs=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,b=class e extends Xi{constructor(t,r,n){super(),this._binaryType=Jr[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=ze,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=e.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,t!==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]),Qr(this,t,r,n)):(this._autoPong=n.autoPong,this._closeTimeout=n.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(t){Jr.includes(t)&&(this._binaryType=t,this._receiver&&(this._receiver._binaryType=t))}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(t,r,n){let i=new is({allowSynchronousEvents:n.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxBufferedChunks:n.maxBufferedChunks,maxFragments:n.maxFragments,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation}),s=new ss(t,this._extensions,n.generateMask);this._receiver=i,this._sender=s,this._socket=t,i[w]=this,s[w]=this,t[w]=this,i.on("conclude",bs),i.on("drain",Ss),i.on("error",vs),i.on("message",Es),i.on("ping",ws),i.on("pong",xs),s.onerror=Ts,t.setTimeout&&t.setTimeout(0),t.setNoDelay&&t.setNoDelay(),r.length>0&&t.unshift(r),t.on("close",rn),t.on("data",Ke),t.on("end",nn),t.on("error",sn),this._readyState=e.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=e.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[W.extensionName]&&this._extensions[W.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=e.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(t,r){if(this.readyState!==e.CLOSED){if(this.readyState===e.CONNECTING){k(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===e.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=e.CLOSING,this._sender.close(t,r,!this._isServer,n=>{n||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),tn(this)}}pause(){this.readyState===e.CONNECTING||this.readyState===e.CLOSED||(this._paused=!0,this._socket.pause())}ping(t,r,n){if(this.readyState===e.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(n=t,t=r=void 0):typeof r=="function"&&(n=r,r=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==e.OPEN){Ft(this,t,n);return}r===void 0&&(r=!this._isServer),this._sender.ping(t||ze,r,n)}pong(t,r,n){if(this.readyState===e.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(n=t,t=r=void 0):typeof r=="function"&&(n=r,r=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==e.OPEN){Ft(this,t,n);return}r===void 0&&(r=!this._isServer),this._sender.pong(t||ze,r,n)}resume(){this.readyState===e.CONNECTING||this.readyState===e.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(t,r,n){if(this.readyState===e.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof r=="function"&&(n=r,r={}),typeof t=="number"&&(t=t.toString()),this.readyState!==e.OPEN){Ft(this,t,n);return}let i={binary:typeof t!="string",mask:!this._isServer,compress:!0,fin:!0,...r};this._extensions[W.extensionName]||(i.compress=!1),this._sender.send(t||ze,i,n)}terminate(){if(this.readyState!==e.CLOSED){if(this.readyState===e.CONNECTING){k(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=e.CLOSING,this._socket.destroy())}}};Object.defineProperty(b,"CONNECTING",{enumerable:!0,value:U.indexOf("CONNECTING")});Object.defineProperty(b.prototype,"CONNECTING",{enumerable:!0,value:U.indexOf("CONNECTING")});Object.defineProperty(b,"OPEN",{enumerable:!0,value:U.indexOf("OPEN")});Object.defineProperty(b.prototype,"OPEN",{enumerable:!0,value:U.indexOf("OPEN")});Object.defineProperty(b,"CLOSING",{enumerable:!0,value:U.indexOf("CLOSING")});Object.defineProperty(b.prototype,"CLOSING",{enumerable:!0,value:U.indexOf("CLOSING")});Object.defineProperty(b,"CLOSED",{enumerable:!0,value:U.indexOf("CLOSED")});Object.defineProperty(b.prototype,"CLOSED",{enumerable:!0,value:U.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(e=>{Object.defineProperty(b.prototype,e,{enumerable:!0})});["open","error","close","message"].forEach(e=>{Object.defineProperty(b.prototype,`on${e}`,{enumerable:!0,get(){for(let t of this.listeners(e))if(t[Ut])return t[cs];return null},set(t){for(let r of this.listeners(e))if(r[Ut]){this.removeListener(e,r);break}typeof t=="function"&&this.addEventListener(e,t,{[Ut]:!0})}})});b.prototype.addEventListener=us;b.prototype.removeEventListener=ds;on.exports=b;function Qr(e,t,r,n){let i={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:as,protocolVersion:jt[1],maxBufferedChunks:262144,maxFragments:16384,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(e._autoPong=i.autoPong,e._closeTimeout=i.closeTimeout,!jt.includes(i.protocolVersion))throw new RangeError(`Unsupported protocol version: ${i.protocolVersion} (supported versions: ${jt.join(", ")})`);let s;if(t instanceof Bt)s=t;else try{s=new Bt(t)}catch{throw new SyntaxError(`Invalid URL: ${t}`)}s.protocol==="http:"?s.protocol="ws:":s.protocol==="https:"&&(s.protocol="wss:"),e._url=s.href;let o=s.protocol==="wss:",a=s.protocol==="ws+unix:",l;if(s.protocol!=="ws:"&&!o&&!a?l=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:a&&!s.pathname?l="The URL's pathname is empty":s.hash&&(l="The URL contains a fragment identifier"),l){let m=new SyntaxError(l);if(e._redirects===0)throw m;Je(e,m);return}let c=o?443:80,u=rs(16).toString("base64"),d=o?Qi.request:es.request,f=new Set,h;if(i.createConnection=i.createConnection||(o?ys:_s),i.defaultPort=i.defaultPort||c,i.port=s.port||c,i.host=s.hostname.startsWith("[")?s.hostname.slice(1,-1):s.hostname,i.headers={...i.headers,"Sec-WebSocket-Version":i.protocolVersion,"Sec-WebSocket-Key":u,Connection:"Upgrade",Upgrade:"websocket"},i.path=s.pathname+s.search,i.timeout=i.handshakeTimeout,i.perMessageDeflate&&(h=new W({...i.perMessageDeflate,isServer:!1,maxPayload:i.maxPayload}),i.headers["Sec-WebSocket-Extensions"]=hs({[W.extensionName]:h.offer()})),r.length){for(let m of r){if(typeof m!="string"||!gs.test(m)||f.has(m))throw new SyntaxError("An invalid or duplicated subprotocol was specified");f.add(m)}i.headers["Sec-WebSocket-Protocol"]=r.join(",")}if(i.origin&&(i.protocolVersion<13?i.headers["Sec-WebSocket-Origin"]=i.origin:i.headers.Origin=i.origin),(s.username||s.password)&&(i.auth=`${s.username}:${s.password}`),a){let m=i.path.split(":");i.socketPath=m[0],i.path=m[1]}let g;if(i.followRedirects){if(e._redirects===0){e._originalIpc=a,e._originalSecure=o,e._originalHostOrSocketPath=a?i.socketPath:s.host;let m=n&&n.headers;if(n={...n,headers:{}},m)for(let[S,E]of Object.entries(m))n.headers[S.toLowerCase()]=E}else if(e.listenerCount("redirect")===0){let m=a?e._originalIpc?i.socketPath===e._originalHostOrSocketPath:!1:e._originalIpc?!1:s.host===e._originalHostOrSocketPath;(!m||e._originalSecure&&!o)&&(delete i.headers.authorization,delete i.headers.cookie,m||delete i.headers.host,i.auth=void 0)}i.auth&&!n.headers.authorization&&(n.headers.authorization="Basic "+Buffer.from(i.auth).toString("base64")),g=e._req=d(i),e._redirects&&e.emit("redirect",e.url,g)}else g=e._req=d(i);i.timeout&&g.on("timeout",()=>{k(e,g,"Opening handshake has timed out")}),g.on("error",m=>{g===null||g[Xr]||(g=e._req=null,Je(e,m))}),g.on("response",m=>{let S=m.headers.location,E=m.statusCode;if(S&&i.followRedirects&&E>=300&&E<400){if(++e._redirects>i.maxRedirects){k(e,g,"Maximum redirects exceeded");return}g.abort();let O;try{O=new Bt(S,t)}catch{let ee=new SyntaxError(`Invalid URL: ${S}`);Je(e,ee);return}Qr(e,O,r,n)}else e.emit("unexpected-response",g,m)||k(e,g,`Unexpected server response: ${m.statusCode}`)}),g.on("upgrade",(m,S,E)=>{if(e.emit("upgrade",m),e.readyState!==b.CONNECTING)return;g=e._req=null;let O=m.headers.upgrade;if(O===void 0||O.toLowerCase()!=="websocket"){k(e,S,"Invalid Upgrade header");return}let G=ns("sha1").update(u+ls).digest("base64");if(m.headers["sec-websocket-accept"]!==G){k(e,S,"Invalid Sec-WebSocket-Accept header");return}let ee=m.headers["sec-websocket-protocol"],fe;if(ee!==void 0?f.size?f.has(ee)||(fe="Server sent an invalid subprotocol"):fe="Server sent a subprotocol but none was requested":f.size&&(fe="Server sent no subprotocol"),fe){k(e,S,fe);return}ee&&(e._protocol=ee);let ur=m.headers["sec-websocket-extensions"];if(ur!==void 0){if(!h){k(e,S,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let yt;try{yt=ps(ur)}catch{k(e,S,"Invalid Sec-WebSocket-Extensions header");return}let dr=Object.keys(yt);if(dr.length!==1||dr[0]!==W.extensionName){k(e,S,"Server indicated an extension that was not requested");return}try{h.accept(yt[W.extensionName])}catch{k(e,S,"Invalid Sec-WebSocket-Extensions header");return}e._extensions[W.extensionName]=h}e.setSocket(S,E,{allowSynchronousEvents:i.allowSynchronousEvents,generateMask:i.generateMask,maxBufferedChunks:i.maxBufferedChunks,maxFragments:i.maxFragments,maxPayload:i.maxPayload,skipUTF8Validation:i.skipUTF8Validation})}),i.finishRequest?i.finishRequest(g,e):g.end()}function Je(e,t){e._readyState=b.CLOSING,e._errorEmitted=!0,e.emit("error",t),e.emitClose()}function _s(e){return e.path=e.socketPath,Yr.connect(e)}function ys(e){return e.path=void 0,!e.servername&&e.servername!==""&&(e.servername=Yr.isIP(e.host)?"":e.host),ts.connect(e)}function k(e,t,r){e._readyState=b.CLOSING;let n=new Error(r);Error.captureStackTrace(n,k),t.setHeader?(t[Xr]=!0,t.abort(),t.socket&&!t.socket.destroyed&&t.socket.destroy(),process.nextTick(Je,e,n)):(t.destroy(n),t.once("error",e.emit.bind(e,"error")),t.once("close",e.emitClose.bind(e)))}function Ft(e,t,r){if(t){let n=os(t)?t.size:ms(t).length;e._socket?e._sender._bufferedBytes+=n:e._bufferedAmount+=n}if(r){let n=new Error(`WebSocket is not open: readyState ${e.readyState} (${U[e.readyState]})`);process.nextTick(r,n)}}function bs(e,t){let r=this[w];r._closeFrameReceived=!0,r._closeMessage=t,r._closeCode=e,r._socket[w]!==void 0&&(r._socket.removeListener("data",Ke),process.nextTick(en,r._socket),e===1005?r.close():r.close(e,t))}function Ss(){let e=this[w];e.isPaused||e._socket.resume()}function vs(e){let t=this[w];t._socket[w]!==void 0&&(t._socket.removeListener("data",Ke),process.nextTick(en,t._socket),t.close(e[fs])),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e))}function Kr(){this[w].emitClose()}function Es(e,t){this[w].emit("message",e,t)}function ws(e){let t=this[w];t._autoPong&&t.pong(e,!this._isServer,Zr),t.emit("ping",e)}function xs(e){this[w].emit("pong",e)}function en(e){e.resume()}function Ts(e){let t=this[w];t.readyState!==b.CLOSED&&(t.readyState===b.OPEN&&(t._readyState=b.CLOSING,tn(t)),this._socket.end(),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e)))}function tn(e){e._closeTimer=setTimeout(e._socket.destroy.bind(e._socket),e._closeTimeout)}function rn(){let e=this[w];if(this.removeListener("close",rn),this.removeListener("data",Ke),this.removeListener("end",nn),e._readyState=b.CLOSING,!this._readableState.endEmitted&&!e._closeFrameReceived&&!e._receiver._writableState.errorEmitted&&this._readableState.length!==0){let t=this.read(this._readableState.length);e._receiver.write(t)}e._receiver.end(),this[w]=void 0,clearTimeout(e._closeTimer),e._receiver._writableState.finished||e._receiver._writableState.errorEmitted?e.emitClose():(e._receiver.on("error",Kr),e._receiver.on("finish",Kr))}function Ke(e){this[w]._receiver.write(e)||this.pause()}function nn(){let e=this[w];e._readyState=b.CLOSING,e._receiver.end(),this.end()}function sn(){let e=this[w];this.removeListener("error",sn),this.on("error",Zr),e&&(e._readyState=b.CLOSING,this.destroy())}});var fn=T((zo,cn)=>{"use strict";var Ho=Ye(),{Duplex:ks}=require("stream");function an(e){e.emit("close")}function Cs(){!this.destroyed&&this._writableState.finished&&this.destroy()}function ln(e){this.removeListener("error",ln),this.destroy(),this.listenerCount("error")===0&&this.emit("error",e)}function Os(e,t){let r=!0,n=new ks({...t,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return e.on("message",function(s,o){let a=!o&&n._readableState.objectMode?s.toString():s;n.push(a)||e.pause()}),e.once("error",function(s){n.destroyed||(r=!1,n.destroy(s))}),e.once("close",function(){n.destroyed||n.push(null)}),n._destroy=function(i,s){if(e.readyState===e.CLOSED){s(i),process.nextTick(an,n);return}let o=!1;e.once("error",function(l){o=!0,s(l)}),e.once("close",function(){o||s(i),process.nextTick(an,n)}),r&&e.terminate()},n._final=function(i){if(e.readyState===e.CONNECTING){e.once("open",function(){n._final(i)});return}e._socket!==null&&(e._socket._writableState.finished?(i(),n._readableState.endEmitted&&n.destroy()):(e._socket.once("finish",function(){i()}),e.close()))},n._read=function(){e.isPaused&&e.resume()},n._write=function(i,s,o){if(e.readyState===e.CONNECTING){e.once("open",function(){n._write(i,s,o)});return}e.send(i,o)},n.on("end",Cs),n.on("error",ln),n}cn.exports=Os});var Wt=T((Jo,un)=>{"use strict";var{tokenChars:As}=ie();function Ns(e){let t=new Set,r=-1,n=-1,i=0;for(i;i<e.length;i++){let o=e.charCodeAt(i);if(n===-1&&As[o]===1)r===-1&&(r=i);else if(i!==0&&(o===32||o===9))n===-1&&r!==-1&&(n=i);else if(o===44){if(r===-1)throw new SyntaxError(`Unexpected character at index ${i}`);n===-1&&(n=i);let a=e.slice(r,n);if(t.has(a))throw new SyntaxError(`The "${a}" subprotocol is duplicated`);t.add(a),r=n=-1}else throw new SyntaxError(`Unexpected character at index ${i}`)}if(r===-1||n!==-1)throw new SyntaxError("Unexpected end of input");let s=e.slice(r,i);if(t.has(s))throw new SyntaxError(`The "${s}" subprotocol is duplicated`);return t.add(s),t}un.exports={parse:Ns}});var yn=T((Yo,_n)=>{"use strict";var Ps=require("events"),Ze=require("http"),{Duplex:Ko}=require("stream"),{createHash:Is}=require("crypto"),dn=He(),K=ne(),Ds=Wt(),Ls=Ye(),{CLOSE_TIMEOUT:Rs,GUID:$s,kWebSocket:Ms}=$(),Bs=/^[+/0-9A-Za-z]{22}==$/,hn=0,pn=1,gn=2,qt=class extends Ps{constructor(t,r){if(super(),t={allowSynchronousEvents:!0,autoPong:!0,maxBufferedChunks:256*1024,maxFragments:16*1024,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:Rs,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:Ls,...t},t.port==null&&!t.server&&!t.noServer||t.port!=null&&(t.server||t.noServer)||t.server&&t.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(t.port!=null?(this._server=Ze.createServer((n,i)=>{let s=Ze.STATUS_CODES[426];i.writeHead(426,{"Content-Length":s.length,"Content-Type":"text/plain"}),i.end(s)}),this._server.listen(t.port,t.host,t.backlog,r)):t.server&&(this._server=t.server),this._server){let n=this.emit.bind(this,"connection");this._removeListeners=Us(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(i,s,o)=>{this.handleUpgrade(i,s,o,n)}})}t.perMessageDeflate===!0&&(t.perMessageDeflate={}),t.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=t,this._state=hn}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(t){if(this._state===gn){t&&this.once("close",()=>{t(new Error("The server is not running"))}),process.nextTick(ve,this);return}if(t&&this.once("close",t),this._state!==pn)if(this._state=pn,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(ve,this):process.nextTick(ve,this);else{let r=this._server;this._removeListeners(),this._removeListeners=this._server=null,r.close(()=>{ve(this)})}}shouldHandle(t){if(this.options.path){let r=t.url.indexOf("?");if((r!==-1?t.url.slice(0,r):t.url)!==this.options.path)return!1}return!0}handleUpgrade(t,r,n,i){r.on("error",mn);let s=t.headers["sec-websocket-key"],o=t.headers.upgrade,a=+t.headers["sec-websocket-version"];if(t.method!=="GET"){Y(this,t,r,405,"Invalid HTTP method");return}if(o===void 0||o.toLowerCase()!=="websocket"){Y(this,t,r,400,"Invalid Upgrade header");return}if(s===void 0||!Bs.test(s)){Y(this,t,r,400,"Missing or invalid Sec-WebSocket-Key header");return}if(a!==13&&a!==8){Y(this,t,r,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(t)){Ee(r,400);return}let l=t.headers["sec-websocket-protocol"],c=new Set;if(l!==void 0)try{c=Ds.parse(l)}catch{Y(this,t,r,400,"Invalid Sec-WebSocket-Protocol header");return}let u=t.headers["sec-websocket-extensions"],d={};if(this.options.perMessageDeflate&&u!==void 0){let f=new K({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let h=dn.parse(u);h[K.extensionName]&&(f.accept(h[K.extensionName]),d[K.extensionName]=f)}catch{Y(this,t,r,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let f={origin:t.headers[`${a===8?"sec-websocket-origin":"origin"}`],secure:!!(t.socket.authorized||t.socket.encrypted),req:t};if(this.options.verifyClient.length===2){this.options.verifyClient(f,(h,g,m,S)=>{if(!h)return Ee(r,g||401,m,S);this.completeUpgrade(d,s,c,t,r,n,i)});return}if(!this.options.verifyClient(f))return Ee(r,401)}this.completeUpgrade(d,s,c,t,r,n,i)}completeUpgrade(t,r,n,i,s,o,a){if(!s.readable||!s.writable)return s.destroy();if(s[Ms])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>hn)return Ee(s,503);let c=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${Is("sha1").update(r+$s).digest("base64")}`],u=new this.options.WebSocket(null,void 0,this.options);if(n.size){let d=this.options.handleProtocols?this.options.handleProtocols(n,i):n.values().next().value;d&&(c.push(`Sec-WebSocket-Protocol: ${d}`),u._protocol=d)}if(t[K.extensionName]){let d=t[K.extensionName].params,f=dn.format({[K.extensionName]:[d]});c.push(`Sec-WebSocket-Extensions: ${f}`),u._extensions=t}this.emit("headers",c,i),s.write(c.concat(`\r
3
3
  `).join(`\r
4
- `)),s.removeListener("error",Qr),f.setSocket(s,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(ge,this)})),a(f,i)}};tn.exports=Nt;function Es(e,t){for(let r of Object.keys(t))e.on(r,t[r]);return function(){for(let n of Object.keys(t))e.removeListener(n,t[n])}}function ge(e){e._state=en,e.emit("close")}function Qr(){this.destroy()}function _e(e,t,r,n){r=r||He.STATUS_CODES[t],n={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(r),...n},e.once("finish",e.destroy),e.end(`HTTP/1.1 ${t} ${He.STATUS_CODES[t]}\r
4
+ `)),s.removeListener("error",mn),u.setSocket(s,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(u),u.on("close",()=>{this.clients.delete(u),this._shouldEmitClose&&!this.clients.size&&process.nextTick(ve,this)})),a(u,i)}};_n.exports=qt;function Us(e,t){for(let r of Object.keys(t))e.on(r,t[r]);return function(){for(let n of Object.keys(t))e.removeListener(n,t[n])}}function ve(e){e._state=gn,e.emit("close")}function mn(){this.destroy()}function Ee(e,t,r,n){r=r||Ze.STATUS_CODES[t],n={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(r),...n},e.once("finish",e.destroy),e.end(`HTTP/1.1 ${t} ${Ze.STATUS_CODES[t]}\r
5
5
  `+Object.keys(n).map(i=>`${i}: ${n[i]}`).join(`\r
6
6
  `)+`\r
7
7
  \r
8
- `+r)}function K(e,t,r,n,i,s){if(e.listenerCount("wsClientError")){let o=new Error(i);Error.captureStackTrace(o,K),e.emit("wsClientError",o,r,t)}else _e(r,n,i,s)}});function pn(){let e=(0,hn.homedir)();return{platform:process.platform,home:e,appData:process.env.APPDATA??(0,b.join)(e,"AppData","Roaming"),localAppData:process.env.LOCALAPPDATA??(0,b.join)(e,"AppData","Local")}}function dn(e,t){let r=t?"Code - Insiders":"Code";return e.platform==="win32"?(0,b.join)(e.appData,r,"User"):e.platform==="darwin"?(0,b.join)(e.home,"Library","Application Support",r,"User"):(0,b.join)(e.home,".config",r,"User")}function js(e){return e.platform==="win32"?(0,b.join)(e.appData,"Claude","claude_desktop_config.json"):e.platform==="darwin"?(0,b.join)(e.home,"Library","Application Support","Claude","claude_desktop_config.json"):(0,b.join)(e.home,".config","Claude","claude_desktop_config.json")}function mn(e){let t=e.trim().toLowerCase();return Se.find(r=>r.id===t||r.aliases.includes(t))}function Qe(e,t){return{url:`${e}/mcp`,headers:{Authorization:`Bearer ${t}`}}}function Lt(e,t){return{type:"http",...Qe(e,t)}}function Dt(e,t){return{command:"npx",args:["-y","mcp-remote",`${e}/mcp`,"--allow-http","--header",`Authorization:Bearer ${t}`]}}function gn(e,t,r){switch(e){case"copilot-http":return Lt(t,r);case"stdio-remote":return Dt(t,r);case"http":default:return Qe(t,r)}}function _n(e,t){return`url = ${JSON.stringify(`${e}/mcp`)}
9
- http_headers = { "Authorization" = ${JSON.stringify(`Bearer ${t}`)} }`}function yn(e,t){return`mcp_servers:
8
+ `+r)}function Y(e,t,r,n,i,s){if(e.listenerCount("wsClientError")){let o=new Error(i);Error.captureStackTrace(o,Y),e.emit("wsClientError",o,r,t)}else Ee(r,n,i,s)}});var js,Fs,Ws,qs,Gs,Vs,Hs,Gt,bn=y(()=>{js=j(fn(),1),Fs=j(He(),1),Ws=j(ne(),1),qs=j(Dt(),1),Gs=j($t(),1),Vs=j(Wt(),1),Hs=j(Ye(),1),Gt=j(yn(),1)});function Sn(){return`m_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}function Xe(e,t,r){return{id:e,kind:"response",error:{code:t,message:r}}}var ce=y(()=>{"use strict"});function En(e){return String(e?Math.floor(1e5+e()*9e5):(0,et.randomInt)(1e5,1e6))}var et,q,wn,Qe,xn=y(()=>{"use strict";et=require("node:crypto"),q=require("node:fs"),wn=require("node:path");ce();Qe=class{sessions=new Map;tokens=new Map;lastRequestAt=new Map;persistPath;revokeListeners=new Set;onRevoke(t){this.revokeListeners.add(t)}revoked(t){for(let r of this.revokeListeners)r(t)}constructor(t={}){if(this.persistPath=t.persistPath,this.persistPath&&(0,q.existsSync)(this.persistPath))try{let r=JSON.parse((0,q.readFileSync)(this.persistPath,"utf8")),n=Date.now();for(let i of r){if(!i?.token||!i?.deviceId)continue;let s=typeof i.expiresAt=="number"?i.expiresAt:i.createdAt+7776e6;s<=n||this.tokens.set(i.token,{...i,expiresAt:s})}}catch{}}persist(){if(this.persistPath)try{(0,q.mkdirSync)((0,wn.dirname)(this.persistPath),{recursive:!0}),(0,q.writeFileSync)(this.persistPath,JSON.stringify([...this.tokens.values()]),{mode:384})}catch{}}requestPairing(t,r,n,i=Date.now(),s){this.scrub(i);let o=this.lastRequestAt.get(t);if(o!==void 0&&i>=o&&i-o<5e3)throw Object.assign(new Error("RATE_LIMITED: pairing requested too soon"),{code:"RATE_LIMITED"});if([...this.sessions.values()].filter(h=>h.deviceId===t&&!h.approved).length>=5)throw Object.assign(new Error("RATE_LIMITED: too many pending pairings for device"),{code:"RATE_LIMITED"});if(this.sessions.size>=100)throw Object.assign(new Error("RATE_LIMITED: pairing store full"),{code:"RATE_LIMITED"});let l=En(s),c=0;for(;this.sessions.has(l)&&c++<100;)l=En(s);if(this.sessions.has(l))throw Object.assign(new Error("RATE_LIMITED: code space exhausted"),{code:"RATE_LIMITED"});let u=String(r??"agent").slice(0,64)||"agent",d=(Array.isArray(n)?n:[]).map(String).slice(0,8),f={code:l,deviceId:t,clientName:u,scopes:d,createdAt:i,expiresAt:i+6e5,approved:!1};return this.sessions.set(l,f),this.lastRequestAt.set(t,i),f}approvePairing(t,r,n=Date.now()){let i=this.sessions.get(t);if(!i||i.deviceId!==r||i.expiresAt<=n)return null;if(i.approved&&i.token){let o=this.tokens.get(i.token);if(o&&o.expiresAt>n)return i.token}let s=(0,et.randomBytes)(24).toString("hex");return i.approved=!0,i.token=s,this.tokens.set(s,{token:s,deviceId:i.deviceId,clientName:i.clientName,scopes:i.scopes,createdAt:n,expiresAt:n+7776e6}),this.persist(),s}claimPairing(t,r=Date.now()){let n=this.sessions.get(t);return!n||n.expiresAt<=r?{status:"expired"}:n.approved&&n.token?{status:"approved",token:n.token}:{status:"pending"}}verifyToken(t,r=Date.now()){let n=this.tokens.get(t);return n?n.expiresAt<=r?(this.tokens.delete(t),this.persist(),null):n:null}revokeToken(t){let r=this.tokens.delete(t);return r&&(this.persist(),this.revoked(t)),r}revokeDevice(t){let r=0;for(let[n,i]of this.tokens)i.deviceId===t&&(this.tokens.delete(n),this.revoked(n),r++);return r>0&&this.persist(),r}pendingForDevice(t,r=Date.now()){return this.scrub(r),[...this.sessions.values()].filter(n=>n.deviceId===t&&!n.approved&&n.expiresAt>r)}scrub(t){for(let[r,n]of this.sessions)n.expiresAt<=t&&this.sessions.delete(r)}}});var tt,Tn=y(()=>{"use strict";ce();tt=class{devices=new Map;pending=new Map;registerDevice(t,r){let n=this.devices.get(t)??null;return this.devices.set(t,r),n&&n!==r?n:null}unregisterDevice(t,r){(!r||this.devices.get(t)===r)&&(this.devices.delete(t),this.failPendingForDevice(t,new Error(`DISCONNECTED: device ${t} offline`)))}failPendingForDevice(t,r){let n=0;for(let[i,s]of this.pending){if(s.deviceId!==t)continue;this.pending.delete(i),clearTimeout(s.timer);let o=r??new Error(`DISCONNECTED: device ${t} offline`);o.code??="DISCONNECTED",s.reject(o),n++}return n}isCurrentDevice(t,r){return this.devices.get(t)===r}isDeviceOnline(t){return this.devices.has(t)}onlineDevices(){return[...this.devices.keys()]}routeToDevice(t,r,n,i=13e4,s){let o=this.devices.get(t);if(!o)return Promise.reject(Object.assign(new Error(`DISCONNECTED: device ${t} offline`),{code:"DISCONNECTED"}));let a=Sn(),l={id:a,kind:"request",method:r,params:n,agentName:s?.agentName};return new Promise((c,u)=>{let d=setTimeout(()=>{this.pending.delete(a),u(Object.assign(new Error(`TIMEOUT waiting for device ${t}`),{code:"TIMEOUT"}))},i);d.unref?.(),this.pending.set(a,{deviceId:t,resolve:c,reject:u,timer:d});try{o(JSON.stringify(l))}catch(f){this.pending.delete(a),clearTimeout(d),u(f instanceof Error?f:new Error(String(f)))}})}settleResponse(t,r){let n=this.pending.get(t.id);return!n||r!==void 0&&n.deviceId!==r?!1:(this.pending.delete(t.id),clearTimeout(n.timer),t.error?n.reject(Object.assign(new Error(`${t.error.code}: ${t.error.message}`),{code:t.error.code})):n.resolve(t.result),!0)}pendingCount(){return this.pending.size}}});function Xs(e){let t=new URL(e.url??"/","http://localhost");return e.method==="POST"&&t.pathname==="/mcp"}async function kn(e,t,r){if(!Xs(e))return!1;let n=r.pairings.verifyToken(he(e.headers.authorization)??"");if(!n)return I(t,e,null,{error:{code:-32001,message:"Unauthorized: invalid or missing pairing token"}},401);let i;try{i=await ue(e)}catch(o){return I(t,e,null,{error:{code:-32600,message:o.message}},o.status??400)}let s=i;if(s.jsonrpc!=="2.0"||typeof s.method!="string")return I(t,e,s.id??null,{error:{code:-32600,message:"Invalid JSON-RPC request"}},400);if(s.method==="initialize")return I(t,e,s.id??null,{result:{protocolVersion:Zs,capabilities:{tools:{}},serverInfo:{name:"babtab-relay",version:"0.2.0"}}});if(s.method.startsWith("notifications/"))return t.writeHead(202).end(),!0;if(s.method==="tools/list")return I(t,e,s.id??null,{result:{tools:de.map(o=>({name:o.name,description:o.description,inputSchema:o.inputSchema}))}});if(s.method==="tools/call"){let o=String(s.params?.name??""),a=s.params?.arguments??{};if(!x(a))return I(t,e,s.id??null,{result:rt("Tool arguments must be an object")});let l=$e(o);if(!l)return I(t,e,s.id??null,{result:rt(`Unknown tool: ${o}`)});if(!pe(n,l.scope))return I(t,e,s.id??null,{result:rt(`Token lacks scope ${l.scope} for ${o}`)});try{let c=await r.registry.routeToDevice(n.deviceId,o,a,13e4,{agentName:n.clientName}),u=[];if(o==="browser_screenshot"&&x(c)&&typeof c.dataUrl=="string"){let h=/^data:(image\/(?:jpeg|png|webp));base64,([A-Za-z0-9+/=]+)$/.exec(c.dataUrl);h&&u.push({type:"image",mimeType:h[1],data:h[2]})}let d=Vt(c),f=JSON.stringify(d)??"null";return u.push({type:"text",text:f.length<=64e3?f:JSON.stringify({truncated:!0,originalLength:f.length,preview:f.slice(0,3e4)})}),I(t,e,s.id??null,{result:{content:u,...x(c)&&c.ok===!1?{isError:!0}:{}}})}catch(c){let u=c;return I(t,e,s.id??null,{result:rt(`${u.code??"DISCONNECTED"}: ${u.message}`,!0)})}}return I(t,e,s.id??null,{error:{code:-32601,message:`Method not found: ${s.method}`}},404)}function rt(e,t=!1){return{content:[{type:"text",text:e}],isError:!0,_meta:{retryable:t}}}function I(e,t,r,n,i=200){let s=JSON.stringify({jsonrpc:"2.0",id:r,...n});return String(t.headers.accept??"application/json").includes("text/event-stream")?(e.writeHead(i,{"content-type":"text/event-stream","cache-control":"no-cache","access-control-allow-origin":"*"}),e.end(`event: message
9
+ data: ${s}
10
+
11
+ `),!0):(e.writeHead(i,{"content-type":"application/json","access-control-allow-origin":"*"}),e.end(s),!0)}function Vt(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(Vt);let t={};for(let[r,n]of Object.entries(e)){if((r==="dataUrl"||r==="dataURL")&&typeof n=="string"&&n.length>8e3){t[r]=`[truncated ${r}: ${n.length} chars, image data omitted from text]`,t[`${r}Truncated`]=!0,t[`${r}Length`]=n.length;continue}t[r]=Vt(n)}return t}var Zs,Cn=y(()=>{"use strict";Re();me();Me();ce();Zs="2024-11-05"});function it(e={}){let t=new Qe({persistPath:e.tokenFile??process.env.BABTAB_TOKEN_FILE??"./data/relay-tokens.json"}),r=new tt,n,i=!1,s=new Map,o=new Map,a=(0,On.createServer)((f,h)=>{if(i){h.writeHead(503).end();return}eo(f,h,n).catch(g=>{h.headersSent||h.writeHead(g.status??500,{"content-type":"application/json"}),h.end(JSON.stringify({error:g.status?g.message:"Internal server error"}))})}),l=new Gt.default({server:a,maxPayload:8*1024*1024});l.on("error",()=>{}),l.on("connection",(f,h)=>{if(f.on("error",()=>f.terminate()),i){f.close(1001,"relay shutting down");return}let g=new URL(h.url??"/","http://localhost");if(g.pathname==="/device"){let m=g.searchParams.get("deviceId")??"",S=setTimeout(()=>f.close(1008,"device authentication required"),5e3);S.unref(),f.once("close",()=>clearTimeout(S)),f.once("message",E=>{clearTimeout(S);let O;try{O=JSON.parse(String(E))}catch{f.close(1008,"invalid authentication");return}if(!x(O)||O.kind!=="authenticate"||!no(m,O.token)){f.close(1008,"invalid device credential");return}let G=s.get(m);s.set(m,f),to(f,m,t,r),G?.close(1008,"device reconnected"),f.once("close",()=>{s.get(m)===f&&s.delete(m)}),f.send(JSON.stringify({kind:"authenticated"}))})}else if(g.pathname==="/client"){let m=g.searchParams.get("token")??"";o.set(f,m),f.once("close",()=>o.delete(f)),ro(f,m,t,r)}else f.close(1008,"unknown path")});let c=setInterval(()=>{for(let f of l.clients){let h=o.get(f);if(h&&!t.verifyToken(h)){f.close(1008,"token expired or revoked");continue}if(f.isAlive===!1){f.terminate();continue}f.isAlive=!1,f.ping()}},2e4);c.unref?.(),l.on("connection",f=>{f.isAlive=!0,f.on("pong",()=>{f.isAlive=!0})});let u=e.port??0;t.onRevoke(f=>{for(let[h,g]of o)g===f&&h.close(1008,"token revoked")}),a.listen(u,e.host??"127.0.0.1");let d;return n={server:a,pairings:t,registry:r,close:()=>d??=new Promise((f,h)=>{i=!0,clearInterval(c);for(let E of r.onlineDevices())r.failPendingForDevice(E);for(let E of l.clients)E.close(1001,"relay shutting down");let g=setTimeout(()=>{for(let E of l.clients)E.terminate();a.closeAllConnections()},1e3),m=new Promise((E,O)=>a.close(G=>G?O(G):E())),S=new Promise(E=>l.close(()=>E()));Promise.all([m,S]).then(()=>{clearTimeout(g),f()},E=>{clearTimeout(g),h(E)})})},n}async function eo(e,t,r){let n=new URL(e.url??"/","http://localhost");if(e.method==="OPTIONS"){t.writeHead(204,{"access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, OPTIONS","access-control-allow-headers":"content-type, authorization"}),t.end();return}let i=(s,o)=>{t.writeHead(s,{"content-type":"application/json","access-control-allow-origin":"*"}),t.end(JSON.stringify(o))};if(e.method==="GET"&&n.pathname==="/health"){i(200,{ok:!0,service:"babtab-relay",bridgeVersion:1,devices:r.registry.onlineDevices().length});return}if(e.method==="GET"&&n.pathname==="/client/status"){let s=r.pairings.verifyToken(he(e.headers.authorization)??"");if(!s){i(401,{error:"Unauthorized"});return}i(200,{deviceOnline:r.registry.isDeviceOnline(s.deviceId)});return}if(e.method==="POST"&&n.pathname==="/pairing/request"){let s=await ue(e),o=String(s.deviceId??"").slice(0,128);if(!o){i(400,{error:"deviceId required"});return}let a=Array.isArray(s.scopes)?s.scopes.map(String).slice(0,8):["browser:read","browser:act"];try{let l=r.pairings.requestPairing(o,String(s.clientName??"agent"),a);i(200,{code:l.code,expiresAt:l.expiresAt,deviceOnline:r.registry.isDeviceOnline(o)})}catch(l){if(l.code==="RATE_LIMITED"){i(429,{error:l.message});return}throw l}return}if(e.method==="POST"&&n.pathname==="/pairing/claim"){let s=await ue(e);i(200,r.pairings.claimPairing(String(s.code??"")));return}if(e.method==="POST"&&n.pathname==="/pairing/revoke"){let{extractBearer:s}=await Promise.resolve().then(()=>(me(),pr)),o=s(e.headers.authorization)??"",a=o?r.pairings.revokeToken(o):!1;i(200,{ok:a});return}await kn(e,t,r)||i(404,{error:"not found"})}function to(e,t,r,n){if(!t){e.close(1008,"deviceId required");return}let i=o=>{e.readyState===e.OPEN&&e.send(o)};n.registerDevice(t,i)&&n.failPendingForDevice(t),e.on("message",o=>{let a;try{a=JSON.parse(String(o))}catch{return}if(!An(a)){e.close(1008,"invalid envelope");return}if(n.isCurrentDevice(t,i)){if(a.kind==="response"){n.settleResponse(a,t);return}if(a.kind!=="pong"&&a.kind==="request"&&a.id){if(a.method==="pairing:pending"){let l=r.pendingForDevice(t).map(c=>({code:c.code,clientName:c.clientName,scopes:c.scopes,createdAt:c.createdAt,expiresAt:c.expiresAt}));e.send(JSON.stringify({id:a.id,kind:"response",result:l}));return}if(a.method==="pairing:approve"){let l=String(a.params?.code??""),c=r.approvePairing(l,t)!=null;e.send(JSON.stringify({id:a.id,kind:"response",result:{ok:c}}));return}if(a.method==="pairing:revoke-device"){let l=r.revokeDevice(t);e.send(JSON.stringify({id:a.id,kind:"response",result:{revoked:l}}));return}e.send(JSON.stringify(Xe(a.id,"UNSUPPORTED_OPERATION",`Unknown device method ${a.method}`)))}}}),e.on("close",()=>n.unregisterDevice(t,i))}function ro(e,t,r,n){let i=r.verifyToken(t);if(!i){e.close(1008,"invalid token");return}e.on("message",s=>{let o;try{o=JSON.parse(String(s))}catch{return}if(!An(o)){e.close(1008,"invalid envelope");return}if(o.kind!=="request"||!o.method)return;let a=r.verifyToken(t);if(!a){e.close(1008,"token expired or revoked");return}let l=$e(o.method);if(!l||!pe(a,l.scope)){e.send(JSON.stringify(Xe(o.id,"USER_REJECTED","Unknown tool or insufficient scope")));return}n.routeToDevice(i.deviceId,o.method,o.params,13e4,{agentName:i.clientName}).then(c=>{e.readyState===e.OPEN&&e.send(JSON.stringify({id:o.id,kind:"response",result:c}))}).catch(c=>{e.readyState===e.OPEN&&e.send(JSON.stringify(Xe(o.id,c.code??"DISCONNECTED",c.message)))})})}function no(e,t){if(!/^dev_v2_[a-f0-9]{64}$/.test(e)||typeof t!="string"||!/^[a-f0-9]{64}$/.test(t))return!1;let r=(0,nt.createHash)("sha256").update(t).digest();return(0,nt.timingSafeEqual)(r,Buffer.from(e.slice(7),"hex"))}function An(e){return x(e)?e.kind==="ping"||e.kind==="pong"?!0:typeof e.id!="string"||e.id.length>256?!1:e.kind==="request"?typeof e.method=="string"&&(e.params===void 0||x(e.params)):e.kind==="response"&&(e.error===void 0||x(e.error)&&typeof e.error.code=="string"&&typeof e.error.message=="string"):!1}var nt,On,Ht=y(()=>{"use strict";nt=require("node:crypto");Re();Me();me();On=require("node:http");bn();ce();xn();Tn();me();Cn()});var In={};vt(In,{LocalBridge:()=>ot,parseBridgeArgs:()=>io,runStdio:()=>so});function io(e){let t="",r="agent",n=3e3;for(let i=0;i<e.length;i++){let s=e[i],o=e[++i];if(!o||o.startsWith("--"))throw new Error(`Missing value for ${s}`);if(s==="--device")t=o;else if(s==="--client")r=o;else if(s==="--port")n=Number(o);else throw new Error(`Unknown option: ${s}`)}if(!/^dev_v2_[a-f0-9]{64}$/.test(t))throw new Error("A valid --device is required. Copy setup from the Babtab extension.");if(!Number.isInteger(n)||n<1||n>65535)throw new Error("Invalid --port: expected 1-65535");if(!/^[a-z0-9-]{1,64}$/i.test(r))throw new Error("Invalid --client name");return{deviceId:t,clientName:r,port:n}}async function so(e,t=process.stdin,r=process.stdout){let n=new ot(e,d=>process.stderr.write(`[babtab] ${d}
12
+ `)),i=setInterval(()=>{n.tick()},2e3);n.tick();let s=(d,f)=>r.write(`${JSON.stringify({jsonrpc:"2.0",id:d,...f})}
13
+ `),o=!1,a=()=>{},l=async d=>{let f;try{f=JSON.parse(d)}catch{s(null,{error:{code:-32700,message:"Parse error"}});return}if(!x(f)||f.jsonrpc!=="2.0"||typeof f.method!="string"||f.id!==void 0&&typeof f.id!="string"&&typeof f.id!="number"){s(null,{error:{code:-32600,message:"Invalid Request"}});return}if(f.id!==void 0)if(f.method==="initialize")s(f.id,{result:{protocolVersion:"2024-11-05",capabilities:{tools:{}},serverInfo:{name:"babtab",version:"0.2.0"},instructions:"If browser tools report pairing is needed, ask the user to open Babtab in Chrome and approve the connection."}});else if(f.method==="ping")s(f.id,{result:{}});else if(f.method==="tools/list")s(f.id,{result:{tools:de.map(({name:h,description:g,inputSchema:m})=>({name:h,description:g,inputSchema:m}))}});else if(f.method==="tools/call"){let h=await n.call(f);o||s(f.id,h.error?{error:h.error}:{result:h.result})}else s(f.id,{error:{code:-32601,message:`Method not found: ${f.method}`}})},c="";t.setEncoding("utf8");let u=d=>{c+=d;let f;for(;(f=c.indexOf(`
14
+ `))!==-1;){let h=c.slice(0,f);if(c=c.slice(f+1),Buffer.byteLength(h)>1048576){t.destroy(new Error("MCP message too large"));return}h.trim()&&l(h)}Buffer.byteLength(c)>1048576&&t.destroy(new Error("MCP message too large"))};try{await new Promise(d=>{a=()=>d(),t.on("data",u),t.once("end",a),t.once("close",a),t.once("error",a),process.once("SIGTERM",a),process.once("SIGINT",a)})}finally{o=!0,clearInterval(i),t.off("data",u),t.off("end",a),t.off("close",a),t.off("error",a),process.off("SIGTERM",a),process.off("SIGINT",a),t.pause(),await n.close()}}var Nn,D,Pn,st,ot,Dn=y(()=>{"use strict";Nn=require("node:crypto"),D=require("node:fs"),Pn=require("node:os"),st=require("node:path");Ht();Re();Me();ce();ot=class{opts;log;owned;token="";pending;tickPromise;stopped=!1;relayReady=!1;abort=new AbortController;nextPairAt=0;dataDir;credentialPath;base;status="Open Babtab in Chrome and approve the connection.";constructor(t,r){this.opts=t,this.log=r,this.base=`http://127.0.0.1:${t.port}`,this.dataDir=t.dataDir??process.env.BABTAB_DATA_DIR??(0,st.join)((0,Pn.homedir)(),".babtab");let n=(0,Nn.createHash)("sha256").update(`${this.base}/${t.deviceId}/${t.clientName}`).digest("hex");this.credentialPath=(0,st.join)(this.dataDir,`client-${n}.json`);try{let i=JSON.parse((0,D.readFileSync)(this.credentialPath,"utf8"));x(i)&&typeof i.token=="string"&&(this.token=i.token)}catch{}}async request(t,r,n){let i=new AbortController,s=()=>i.abort(),o=setTimeout(s,t==="/mcp"?135e3:1500);this.abort.signal.addEventListener("abort",s,{once:!0}),this.abort.signal.aborted&&s();try{return await fetch(`${this.base}${t}`,{method:r===void 0?"GET":"POST",headers:{"content-type":"application/json",...n?{authorization:`Bearer ${n}`}:{}},...r===void 0?{}:{body:JSON.stringify(r)},signal:i.signal,redirect:"error"})}finally{clearTimeout(o),this.abort.signal.removeEventListener("abort",s)}}async ensureRelay(){try{let r=await this.request("/health"),n=await r.json().catch(()=>null);if(!r.ok||!x(n)||n.service!=="babtab-relay"||n.bridgeVersion!==1)throw new Error(`Port ${this.opts.port} is in use by another service or an older Babtab. Stop the old relay or choose another port in Advanced connection settings.`);return}catch(r){if(!(r instanceof TypeError)&&!(r instanceof Error&&r.name==="AbortError"))throw r}if(this.stopped)return;(0,D.mkdirSync)(this.dataDir,{recursive:!0,mode:448});let t=it({port:this.opts.port,tokenFile:(0,st.join)(this.dataDir,"relay-tokens.json")});try{await new Promise((r,n)=>{t.server.once("listening",r),t.server.once("error",n)}),this.owned=t}catch(r){throw await t.close().catch(()=>{}),r.code!=="EADDRINUSE"?r:new Error("Waiting for the local bridge to start\u2026")}}tick(){return this.tickPromise??=this.update().finally(()=>{this.tickPromise=void 0})}async update(){if(!this.stopped){this.relayReady=!1;try{if(await this.ensureRelay(),this.stopped)return;if(this.relayReady=!0,this.token){let n=await this.request("/client/status",void 0,this.token);if(n.status===401)this.token="";else{if(!n.ok)throw new Error(`Connection check failed: HTTP ${n.status}`);let i=await n.json();this.status=i.deviceOnline?"Connected":"Open Chrome and Babtab to reconnect your browser.";return}}if(this.pending&&Date.now()<this.pending.expiresAt){let n=await this.request("/pairing/claim",{code:this.pending.code}),i=await n.json();if(n.ok&&i.status==="approved"&&i.token){this.token=i.token,this.pending=void 0,(0,D.mkdirSync)(this.dataDir,{recursive:!0,mode:448});let s=`${this.credentialPath}.${process.pid}.tmp`;(0,D.writeFileSync)(s,JSON.stringify({token:this.token}),{mode:384}),(0,D.chmodSync)(s,384),(0,D.renameSync)(s,this.credentialPath),this.status="Connected",this.log("Browser paired. Babtab is ready.")}else i.status==="expired"&&(this.pending=void 0);return}if(Date.now()<this.nextPairAt)return;let t=await this.request("/pairing/request",{deviceId:this.opts.deviceId,clientName:this.opts.clientName,scopes:["browser:read","browser:act"]});if(this.nextPairAt=Date.now()+5e3,!t.ok)throw new Error(`Pairing failed: HTTP ${t.status}`);let r=await t.json();this.pending=r,this.status=`Open Babtab in Chrome and approve ${this.opts.clientName} (code ${r.code}).`,this.log(this.status)}catch(t){this.relayReady=!1;let r=t.message;this.status!==r&&this.log(r),this.status=r}}}async call(t){if(await this.tick(),!this.relayReady||!this.token)return{result:{isError:!0,content:[{type:"text",text:this.status}]}};try{let r=await this.request("/mcp",t,this.token);if(r.status===401)throw this.token="",this.tick(),new Error("Pairing expired or was revoked. Open Babtab and approve the new connection.");let n=await r.json();if(!x(n))throw new Error("Invalid response from Babtab");return n}catch(r){return{result:{isError:!0,content:[{type:"text",text:r.message}]}}}}async close(){this.stopped=!0,this.abort.abort(),await this.tickPromise,await this.owned?.close()}}});function at(){let e=(0,Rn.homedir)();return{platform:process.platform,home:e,appData:process.env.APPDATA??(0,v.join)(e,"AppData","Roaming"),localAppData:process.env.LOCALAPPDATA??(0,v.join)(e,"AppData","Local")}}function Ln(e,t){let r=t?"Code - Insiders":"Code";return e.platform==="win32"?(0,v.join)(e.appData,r,"User"):e.platform==="darwin"?(0,v.join)(e.home,"Library","Application Support",r,"User"):(0,v.join)(e.home,".config",r,"User")}function oo(e){return e.platform==="win32"?(0,v.join)(e.appData,"Claude","claude_desktop_config.json"):e.platform==="darwin"?(0,v.join)(e.home,"Library","Application Support","Claude","claude_desktop_config.json"):(0,v.join)(e.home,".config","Claude","claude_desktop_config.json")}function $n(e){let t=e.trim().toLowerCase();return we.find(r=>r.id===t||r.aliases.includes(t))}function lt(e,t){return{url:`${e}/mcp`,headers:{Authorization:`Bearer ${t}`}}}function zt(e,t){return{type:"http",...lt(e,t)}}function Jt(e,t){return{command:"npx",args:["-y","mcp-remote",`${e}/mcp`,"--allow-http","--header",`Authorization:Bearer ${t}`]}}function Mn(e,t,r){switch(e){case"copilot-http":return zt(t,r);case"stdio-remote":return Jt(t,r);case"http":default:return lt(t,r)}}function Bn(e,t){return`url = ${JSON.stringify(`${e}/mcp`)}
15
+ http_headers = { "Authorization" = ${JSON.stringify(`Bearer ${t}`)} }`}function Un(e,t){return`mcp_servers:
10
16
  babtab:
11
17
  url: "${e}/mcp"
12
18
  headers:
13
- Authorization: "Bearer ${t}"`}function Sn(e,t){return`curl -s ${e}/mcp -H "Authorization: Bearer ${t}" -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"browser_observe","arguments":{}}}'`}var hn,b,Se,bn=x(()=>{"use strict";hn=require("node:os"),b=require("node:path");Se=[{id:"cursor",label:"Cursor",aliases:[],paths:e=>[(0,b.join)(e.home,".cursor","mcp.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Cursor: Settings \u2192 MCP \u2192 enable babtab (or restart Cursor)."},{id:"claude-code",label:"Claude Code",aliases:["claudecode"],paths:()=>[],action:{kind:"exec",argv:(e,t)=>["claude","mcp","add","--transport","http","babtab",`${e}/mcp`,"--header",`Authorization: Bearer ${t}`]},nextStep:"Verify with: claude mcp list"},{id:"windsurf",label:"Windsurf",aliases:[],paths:e=>[(0,b.join)(e.home,".codeium","windsurf","mcp_config.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Restart Windsurf (or reload MCP servers) to pick up babtab."},{id:"copilot",label:"Copilot (VS Code)",aliases:["vscode","code"],paths:e=>[(0,b.join)(dn(e,!1),"mcp.json")],action:{kind:"json",rootKey:"servers",entry:"copilot-http"},nextStep:"VS Code: reload window, then check MCP Servers view for babtab."},{id:"copilot-insiders",label:"Copilot (VS Code Insiders)",aliases:["vscode-insiders","code-insiders","insiders"],paths:e=>[(0,b.join)(dn(e,!0),"mcp.json")],action:{kind:"json",rootKey:"servers",entry:"copilot-http"},nextStep:"VS Code Insiders: reload window, then check MCP Servers view for babtab."},{id:"codex",label:"Codex",aliases:[],paths:e=>[(0,b.join)(e.home,".codex","config.toml")],action:{kind:"toml-codex"},nextStep:"Restart Codex to load the babtab server."},{id:"pi",label:"Pi",aliases:[],paths:()=>[],action:{kind:"print",what:"curl"},nextStep:"Pi has no native MCP \u2014 use the curl line above to verify (Pi bridge addon in progress)."},{id:"claude-desktop",label:"Claude Desktop",aliases:["claude","claude_desktop"],paths:e=>[js(e)],action:{kind:"json",rootKey:"mcpServers",entry:"stdio-remote"},nextStep:"Restart Claude Desktop to load babtab (via mcp-remote bridge)."},{id:"antigravity",label:"Antigravity",aliases:[],paths:e=>[(0,b.join)(e.home,".gemini","antigravity","mcp_config.json"),(0,b.join)(e.home,".gemini","config","mcp_config.json")],action:{kind:"json",rootKey:"mcpServers",entry:"stdio-remote"},nextStep:"Restart Antigravity (or Agent panel \u22EF \u2192 Manage MCP Servers \u2192 reload)."},{id:"devin",label:"Devin CLI",aliases:["devin-desktop","devin_desktop"],paths:e=>e.platform==="win32"?[(0,b.join)(e.appData,"devin","mcp_config.json")]:[(0,b.join)(e.home,".config","devin","mcp_config.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Restart Devin to load the babtab server."},{id:"kimi",label:"Kimi",aliases:["kimi-code","kimi-work","kimi_code"],paths:e=>[(0,b.join)(e.home,".kimi-code","mcp.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Restart Kimi to load the babtab server."},{id:"hermes",label:"Hermes",aliases:["hermes-desktop","hermes_desktop"],paths:e=>e.platform==="win32"?[(0,b.join)(e.home,".hermes","config.yaml"),(0,b.join)(e.localAppData,"hermes","config.yaml")]:[(0,b.join)(e.home,".hermes","config.yaml")],action:{kind:"yaml-hermes"},nextStep:"Restart Hermes to load the babtab server."},{id:"manual",label:"Manual / Other",aliases:["other","generic"],paths:()=>[],action:{kind:"print",what:"manual"},nextStep:"Paste the endpoint + header into your harness MCP settings."}]});function Fs(e,t){let r=e.slice(0,t).split(/\r?\n/);return[r.length,r.pop().length+1]}function Ws(e,t,r){let n=e.split(/\r?\n/),i="",s=(Math.log10(t+1)|0)+1;for(let o=t-1;o<=t+1;o++){let a=n[o-1];a&&(i+=o.toString().padEnd(s," "),i+=": ",i+=a,i+=`
19
+ Authorization: "Bearer ${t}"`}function jn(e,t){return`curl -s ${e}/mcp -H "Authorization: Bearer ${t}" -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"browser_observe","arguments":{}}}'`}var Rn,v,we,Kt=y(()=>{"use strict";Rn=require("node:os"),v=require("node:path");we=[{id:"cursor",label:"Cursor",aliases:[],paths:e=>[(0,v.join)(e.home,".cursor","mcp.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Cursor: Settings \u2192 MCP \u2192 enable babtab (or restart Cursor)."},{id:"claude-code",label:"Claude Code",aliases:["claudecode"],paths:()=>[],action:{kind:"exec",argv:(e,t)=>["claude","mcp","add","--transport","http","babtab",`${e}/mcp`,"--header",`Authorization: Bearer ${t}`]},nextStep:"Verify with: claude mcp list"},{id:"windsurf",label:"Windsurf",aliases:[],paths:e=>[(0,v.join)(e.home,".codeium","windsurf","mcp_config.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Restart Windsurf (or reload MCP servers) to pick up babtab."},{id:"copilot",label:"Copilot (VS Code)",aliases:["vscode","code"],paths:e=>[(0,v.join)(Ln(e,!1),"mcp.json")],action:{kind:"json",rootKey:"servers",entry:"copilot-http"},nextStep:"VS Code: reload window, then check MCP Servers view for babtab."},{id:"copilot-insiders",label:"Copilot (VS Code Insiders)",aliases:["vscode-insiders","code-insiders","insiders"],paths:e=>[(0,v.join)(Ln(e,!0),"mcp.json")],action:{kind:"json",rootKey:"servers",entry:"copilot-http"},nextStep:"VS Code Insiders: reload window, then check MCP Servers view for babtab."},{id:"codex",label:"Codex",aliases:[],paths:e=>[(0,v.join)(e.home,".codex","config.toml")],action:{kind:"toml-codex"},nextStep:"Restart Codex to load the babtab server."},{id:"pi",label:"Pi",aliases:[],paths:()=>[],action:{kind:"print",what:"curl"},nextStep:"Pi has no native MCP \u2014 use the curl line above to verify (Pi bridge addon in progress)."},{id:"claude-desktop",label:"Claude Desktop",aliases:["claude","claude_desktop"],paths:e=>[oo(e)],action:{kind:"json",rootKey:"mcpServers",entry:"stdio-remote"},nextStep:"Restart Claude Desktop to load babtab (via mcp-remote bridge)."},{id:"antigravity",label:"Antigravity",aliases:[],paths:e=>[(0,v.join)(e.home,".gemini","antigravity","mcp_config.json"),(0,v.join)(e.home,".gemini","config","mcp_config.json")],action:{kind:"json",rootKey:"mcpServers",entry:"stdio-remote"},nextStep:"Restart Antigravity (or Agent panel \u22EF \u2192 Manage MCP Servers \u2192 reload)."},{id:"devin",label:"Devin CLI",aliases:["devin-desktop","devin_desktop"],paths:e=>e.platform==="win32"?[(0,v.join)(e.appData,"devin","mcp_config.json")]:[(0,v.join)(e.home,".config","devin","mcp_config.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Restart Devin to load the babtab server."},{id:"kimi",label:"Kimi",aliases:["kimi-code","kimi-work","kimi_code"],paths:e=>[(0,v.join)(e.home,".kimi-code","mcp.json")],action:{kind:"json",rootKey:"mcpServers",entry:"http"},nextStep:"Restart Kimi to load the babtab server."},{id:"hermes",label:"Hermes",aliases:["hermes-desktop","hermes_desktop"],paths:e=>e.platform==="win32"?[(0,v.join)(e.home,".hermes","config.yaml"),(0,v.join)(e.localAppData,"hermes","config.yaml")]:[(0,v.join)(e.home,".hermes","config.yaml")],action:{kind:"yaml-hermes"},nextStep:"Restart Hermes to load the babtab server."},{id:"manual",label:"Manual / Other",aliases:["other","generic"],paths:()=>[],action:{kind:"print",what:"manual"},nextStep:"Paste the endpoint + header into your harness MCP settings."}]});function ao(e,t){let r=e.slice(0,t).split(/\r?\n/);return[r.length,r.pop().length+1]}function lo(e,t,r){let n=e.split(/\r?\n/),i="",s=(Math.log10(t+1)|0)+1;for(let o=t-1;o<=t+1;o++){let a=n[o-1];a&&(i+=o.toString().padEnd(s," "),i+=": ",i+=a,i+=`
14
20
  `,o===t&&(i+=" ".repeat(s+r+2),i+=`^
15
- `))}return i}var p,Y=x(()=>{p=class e extends Error{line;column;codeblock;constructor(t,r){let[n,i]=Fs(r.toml,r.ptr),s=Ws(r.toml,n,i);super(`Invalid TOML document: ${t}
21
+ `))}return i}var p,X=y(()=>{p=class e extends Error{line;column;codeblock;constructor(t,r){let[n,i]=ao(r.toml,r.ptr),s=lo(r.toml,n,i);super(`Invalid TOML document: ${t}
16
22
 
17
- ${s}`,r),this.line=n,this.column=i,this.codeblock=s}static x(t,r,n){throw new e(t,{toml:r.s,ptr:n??r.p})}}});function et(e){let t=e.p,r=e.s.charCodeAt(e.p++),n=r,i=r===39,s=r===e.s.charCodeAt(e.p)&&r===e.s.charCodeAt(e.p+1);s&&((r=e.s.charCodeAt(e.p+=2))===10?e.p++:r===13&&e.s.charCodeAt(e.p+1)===10&&(e.p+=2));let o="",a=e.p,l=0;for(;e.p<e.s.length;e.p++)if(r=e.s.charCodeAt(e.p),s&&(r===10||r===13&&e.s.charCodeAt(e.p+1)===10))l=l&&3;else if(r<32&&r!==9||r===127)p.x("control characters are not allowed in strings",e);else if((!l||l===3)&&r===n&&(!s||e.s.charCodeAt(e.p+1)===n&&e.s.charCodeAt(e.p+2)===n)){if(s&&(e.s.charCodeAt(e.p+3)===n&&e.p++,e.s.charCodeAt(e.p+3)===n&&e.p++),!l){let c=e.s.slice(a,e.p);o=o?o+c:c}return e.p+=s?3:1,o}else if(!l)!i&&r===92&&(o+=e.s.slice(a,a=e.p),l=1);else if(l===1)if(r===120||r===117||r===85){let c=e.p++-1,f=0,d=r===120?2:r===117?4:8;for(let u=0;u<d;u++,e.p++){let h=e.s.charCodeAt(e.p),g=h>=48&&h<=57?h-48:h>=65&&h<=70?h-65+10:h>=97&&h<=102?h-97+10:-1;g<0&&p.x("invalid non-hex character in unicode escape",e),f=f<<4|g}(f<0||f>1114111||f>=55296&&f<=57343)&&p.x("invalid unicode escape",e,c),o+=String.fromCodePoint(f),a=e.p--,l=0}else s&&(r===32||r===9)?l=2:(r===98?o+="\b":r===116?o+=" ":r===110?o+=`
18
- `:r===102?o+="\f":r===114?o+="\r":r===101?o+="\x1B":r===34?o+='"':r===92?o+="\\":p.x("unrecognised escape sequence",e),a=e.p+1,l=0);else r!==32&&r!==9&&(l===2&&p.x("invalid escape: only line-ending whitespace may be escaped",e,a),l=!i&&r===92?1:0,a=e.p);p.x("unfinished string",e,t)}var Rt=x(()=>{Y();});var qs,be,Mt=x(()=>{qs=/^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i,be=class e extends Date{#t=!1;#r=!1;#e=null;constructor(t,r,n){let i=!0,s=!0,o="Z",a;if(typeof t=="string")if(r)e:{if(r<3){if(+t.slice(11,13)>23){t="";break e}r===2?(o=null,t+="Z"):(a=t.charCodeAt(t.length-1))!==90&&a!==122&&(o=t.slice(t.length-6)),n&&(t=t.slice(0,10)+"T"+t.slice(11))}else r===4&&(t=+t.slice(0,2)>23?"":`0000-01-01T${t}Z`);i=r!==4,s=r!==3}else{let l=t.match(qs);l?(l[1]||(i=!1,t=`0000-01-01T${t}`),s=!!l[2],s&&t[10]===" "&&(t=t.replace(" ","T")),l[2]&&+l[2]>23?t="":(o=l[3]||null,!o&&s&&(t+="Z"))):t=""}super(t),isNaN(this.getTime())||(this.#t=i,this.#r=s,this.#e=o)}isDateTime(){return this.#t&&this.#r}isLocal(){return!this.#t||!this.#r||!this.#e}isDate(){return this.#t&&!this.#r}isTime(){return this.#r&&!this.#t}isValid(){return this.#t||this.#r}toISOString(){let t=super.toISOString();if(this.isDate())return t.slice(0,10);if(this.isTime())return t.slice(11,23);if(this.#e===null)return t.slice(0,-1);if(this.#e==="Z"||this.#e==="z")return t;let r=+this.#e.slice(1,3)*60+ +this.#e.slice(4,6);return r=this.#e[0]==="-"?r:-r,new Date(this.getTime()-r*6e4).toISOString().slice(0,-1)+this.#e}static wrapAsOffsetDateTime(t,r="Z"){let n=new e(t);return n.#e=r,n}static wrapAsLocalDateTime(t){let r=new e(t);return r.#e=null,r}static wrapAsLocalDate(t){let r=new e(t);return r.#r=!1,r.#e=null,r}static wrapAsLocalTime(t){let r=new e(t);return r.#t=!1,r.#e=null,r}}});function k(e,t=10){return t===16?e>47&&e<58||e>64&&e<71||e>96&&e<103:e>47&&e<48+t}function Bt(e,t){return e===32||e===9||e===10||e===13||t&&(e===t||e===44)||e===35}function ve(e,t){let r=e.p,n=e.s.charCodeAt(e.p);if(n===91||n===123){e.d--||p.x("document contains excessively nested structures. aborting.",e);let i=n===91?xn(e):vn(e);return e.d++,i}return n===34||n===39?et(e):n===116?((e.s.charCodeAt(++e.p)!==114||e.s.charCodeAt(++e.p)!==117||e.s.charCodeAt(++e.p)!==101)&&p.x("invalid value",e,r),e.p++,!0):n===102?((e.s.charCodeAt(++e.p)!==97||e.s.charCodeAt(++e.p)!==108||e.s.charCodeAt(++e.p)!==115||e.s.charCodeAt(++e.p)!==101)&&p.x("invalid value",e,r),e.p++,!1):n===43||n===45?tt(e,e.p,e.s.charCodeAt(++e.p),44-n,t):e.s.charCodeAt(e.p+4)===45&&e.s.charCodeAt(e.p+7)===45?Vs(e,n,t):e.s.charCodeAt(e.p+2)===58?Gs(e,n,t):tt(e,e.p,n,0,t)}function tt(e,t,r,n,i){let s=r,o=0,a=!1;if(s===105)return(e.s.charCodeAt(++e.p)!==110||e.s.charCodeAt(++e.p)!==102)&&p.x("invalid value",e,t),e.p++,(n||1)/0;if(s===110)return(e.s.charCodeAt(++e.p)!==97||e.s.charCodeAt(++e.p)!==110)&&p.x("invalid value",e,t),e.p++,NaN;if(s===48){if(++e.p>=e.s.length||Bt(s=e.s.charCodeAt(e.p),i))return e.bi===!0?0n:0;if(!n){if(s===120)return $t(e,t,16,i);if(s===98)return $t(e,t,2,i);if(s===111)return $t(e,t,8,i)}s===46?o=2:s===101||s===69?o=4:p.x("illegal leading zero",e,t)}else k(s)||p.x("invalid value",e,t);for(;++e.p<e.s.length&&(s=e.s.charCodeAt(e.p),!Bt(s,i));)o||(o=1),s===95?(o&1||p.x("illegal underscore",e),o+=11,a=!0):o===1&&s===46?o=2:(o===1||o===3)&&(s===101||s===69)?o=4:o===4&&(s===43||s===45)||(k(s)?o>9?o-=11:o&1||o++:p.x("illegal character in numeric literal",e));if(!o){let c=(r-48)*(n||1);return e.bi===!0?BigInt(c):c}o&1||p.x("unfinished numeric value",e,t);let l=e.s.slice(t,e.p);return a&&(l=l.replaceAll("_","")),o>1?parseFloat(l):En(e,l,10,t)}function $t(e,t,r,n){let i,s=1;for(;++e.p<e.s.length&&(i=e.s.charCodeAt(e.p),!Bt(i,n));)i===95?(s&1&&p.x("illegal underscore",e),s=3):k(i,r)?s&1&&s--:p.x("illegal character in numeric literal",e);s&1&&p.x("unfinished numeric value",e);let o=e.s.slice(t+2,e.p);return s&&(o=o.replaceAll("_","")),En(e,o,r,t)}function En(e,t,r,n){if(e.bi!==!0)e:{let i=parseInt(t,r);if(!Number.isSafeInteger(i)){if(e.bi)break e;p.x("integer value cannot be represented losslessly",e,n)}return i}return BigInt(r===10?t:(r===2?"0b":r===8?"0o":"0x")+t)}function Vs(e,t,r){let n=e.p++,i;if(!k(t)||!k(e.s.charCodeAt(e.p++))||!k(e.s.charCodeAt(e.p++))||!k(e.s.charCodeAt(e.p++)))return tt(e,e.p=n,t,0,r);if(e.p+=5,k(e.s.charCodeAt(e.p++))||p.x("invalid date-time: date part is malformed",e,n),e.p>=e.s.length||((t=e.s.charCodeAt(e.p))!==32||(i=!0,!k(e.s.charCodeAt(e.p+1))))&&t!==84&&t!==116){let o=e.s.slice(n,e.p);return Ee(e,o,3,!1,n)}if(e.s.charCodeAt(e.p+=3)!==58&&p.x("invalid date-time: time part is malformed",e,n),e.s.charCodeAt(e.p+=3)===58&&(e.p+=3),e.s.charCodeAt(e.p)===46)for(;k(e.s.charCodeAt(++e.p)););if(t=e.s.charCodeAt(e.p)){if(t===90||t===122){let o=e.s.slice(n,++e.p);return Ee(e,o,1,i,n,"[+00:00]")}if(t===43||t===45){let o=e.s.slice(n,e.p+=6);return Ee(e,o,1,i,n,!e.ld&&"["+e.s.slice(e.p-6,e.p)+"]")}}let s=e.s.slice(n,e.p);return Ee(e,s,2,i,n)}function Gs(e,t,r){let n=e.p;if(!k(t)||!k(e.s.charCodeAt(++e.p)))return tt(e,--e.p,t,0,r);if(e.s.charCodeAt(e.p+=4)===58&&(e.p+=3),e.s.charCodeAt(e.p)===46)for(;k(e.s.charCodeAt(++e.p)););let i=e.s.slice(n,e.p);return Ee(e,i,4,!1,n)}function Ee(e,t,r,n,i,s){if(e.ld){let o=new be(t,r,n);return o.isValid()||p.x("invalid date",e,i),o}try{switch(s&&(t+=s),r){case 1:return Temporal.ZonedDateTime.from(t);case 2:return Temporal.PlainDateTime.from(t);case 3:return Temporal.PlainDate.from(t);case 4:return Temporal.PlainTime.from(t)}}catch(o){p.x(o instanceof Error?o.message:""+o,e,i)}}var Ut=x(()=>{Rt();jt();Y();Mt();});function Hs(e){for(;e.p<e.s.length;e.p++){let t=e.s.charCodeAt(e.p);if(t===10)break;if(t===13&&e.s.charCodeAt(e.p+1)===10){e.p++;break}(t<32&&t!==9||t===127)&&p.x("control characters are not allowed in comments",e)}}function I(e,t,r){let n;for(;e.p<e.s.length;){for(;e.p<e.s.length&&((n=e.s.charCodeAt(e.p))===32||n===9||!t&&(n===10||n===13&&e.s.charCodeAt(e.p+1)===10));)e.p++;if(r||n!==35)break;Hs(e)}}var Ft=x(()=>{Y();});function rt(e,t=61){let r,n=0,i=[],s,o=e.s.charCodeAt(r=e.p);do{if(o===t)return n||p.x("unexpected end of key",e),n===1&&i.push(e.s.slice(s,e.p)),e.p++,i;o===46?(n||p.x("illegal empty bare key",e),n===1&&i.push(e.s.slice(s,e.p)),n=0):!n&&(o===34||o===39)?(o===e.s.charCodeAt(e.p+1)&&o===e.s.charCodeAt(e.p+2)&&p.x("illegal quoted key: multiline strings are not allowed",e),i.push(et(e)),n=2,e.p--):o===32||o===9?n===1&&(i.push(e.s.slice(s,e.p)),n=2):n===2||o<48&&o!==45||o>57&&o<65||o>90&&o<97&&o!==95||o>122?p.x("illegal character in key",e):n||(n=1,s=e.p)}while(o=e.s.charCodeAt(++e.p));p.x("incomplete key-value: cannot find end of key",e,r)}function vn(e){let t=e.p++,r=Object.create(null),n=new Set,i;for(;e.p<e.s.length;){if(I(e),(i=e.s.charCodeAt(e.p))===125)return e.p++,r;let s,o=r,a=!1,l=e.p,c=rt(e);for(let d=0;d<c.length;d++){d&&(o=a?o[s]:o[s]=Object.create(null)),s=c[d],(a=Object.hasOwn(o,s))&&(typeof o[s]!="object"||n.has(o[s]))&&p.x("trying to redefine an already defined value",e,l);let u=s==="__proto__";if(e.uk&&(u||s==="constructor")){o=e.uk!==1&&p.x("document contains an unsafe property",e,l);break}!a&&u&&Object.defineProperty(o,s,{enumerable:!0,configurable:!0,writable:!0})}a&&p.x("trying to redefine an already defined value",e,l),I(e,!0,!0);let f=ve(e,125);if(o&&typeof(o[s]=f)=="object"&&n.add(f),I(e),(i=e.s.charCodeAt(e.p++))===125)return r;i!==44&&p.x("expected comma or end of structure",e,e.p-1)}p.x("unfinished table",e,t)}function xn(e){let t=e.p++,r=[],n;for(;e.p<e.s.length;){if(I(e),(n=e.s.charCodeAt(e.p))===93)return e.p++,r;if(r.push(ve(e,93)),I(e),(n=e.s.charCodeAt(e.p++))===93)return r;n!==44&&p.x("expected comma or end of structure",e,e.p-1)}p.x("unfinished array",e,t)}var jt=x(()=>{Rt();Ut();Ft();Y();});function wn(e,t,r,n,i){let s=r,o=n,a,l=!1,c;for(let f=0;f<t.length;f++){if(f){if(s=l?s[a]:s[a]=Object.create(null),o=(c=o[a]).c,i===0&&(c.t===1||c.t===2))return null;if(c.t===2){let d=s.length-1;s=s[d],o=o[d].c}}if(a=t[f],(l=Object.hasOwn(s,a))&&o[a]?.t===0&&o[a]?.d)return null;if(!l){let d=a==="__proto__";if(e.uk&&(d||a==="constructor"))return!1;d&&(Object.defineProperty(s,a,{enumerable:!0,configurable:!0,writable:!0}),Object.defineProperty(o,a,{enumerable:!0,configurable:!0,writable:!0})),o[a]={t:f<t.length-1&&i===2?3:i,d:!1,i:0,c:Object.create(null)}}}if(c=o[a],c.t!==i&&!(i===1&&c.t===3)||(i===2&&(c.d||(c.d=!0,s[a]=[]),s[a].push(s=Object.create(null)),c.c[c.i++]=c={t:1,d:!1,i:0,c:Object.create(null)}),c.d))return null;if(c.d=!0,i===1)s=l?s[a]:s[a]=Object.create(null);else if(i===0&&l)return null;return[a,s,c.c]}function Tn(e,t,r){(t===null||e.uk===2)&&p.x(t===null?"trying to redefine an already defined table or value":"document contains an unsafe property",e,r)}function xe(e,t={}){let r={s:e,p:0,d:t.maxDepth??1e3,bi:t.integersAsBigInt??!1,ld:t.useLegacyDate??!0,uk:t.unsafeKeyBehaviour==="throw"?2:t.unsafeKeyBehaviour==="drop"?1:0},n=Object.create(null),i=Object.create(null),s,o=!1,a=n,l=i;for(e.charCodeAt(0)===65279&&r.p++,I(r);r.p<e.length;){if(e.charCodeAt(r.p)===91){let c=e.charCodeAt(++r.p)===91;s=r.p+=+c,o=!1;let f=rt(r,93);c&&(e.charCodeAt(r.p)!==93&&p.x("expected end of table array declaration",r),r.p++);let d=wn(r,f,n,i,c?2:1);d?(l=d[2],a=d[1]):(Tn(r,d,s),o=!0)}else{s=r.p;let c=rt(r),f=wn(r,c,a,l,0);!f&&!o&&Tn(r,f,s),I(r,!0,!0);let d=ve(r,void 0);f&&!o&&(f[1][f[0]]=d)}I(r,!0),r.p<e.length&&(s=e.charCodeAt(r.p))!==10&&(s!==13||e.charCodeAt(r.p+1)!==10)&&p.x("each key-value declaration must be followed by an end-of-line",r),I(r)}return n}var kn=x(()=>{jt();Ut();Ft();Y();});function we(e){let t=typeof e;if(t==="object"){if(Array.isArray(e))return"array";if(typeof e.getUTCDate=="function"&&e instanceof Date)return"date";if(globalThis.Temporal){if(e.until){if(e instanceof Temporal.ZonedDateTime)return"temporal/tz+uc";if(e instanceof Temporal.PlainDateTime||e instanceof Temporal.PlainDate)return"temporal/uc";if(e instanceof Temporal.PlainTime||e instanceof Temporal.Instant)return"temporal";if(e instanceof Temporal.PlainYearMonth)return"temporal/x"}else if(e.toPlainDate&&e instanceof Temporal.PlainMonthDay||e.negated&&e instanceof Temporal.Duration)return"temporal/x"}}return t}function Js(e){for(let t=0;t<e.length;t++)if(we(e[t])!=="object")return!1;return e.length!=0}function On(e){return JSON.stringify(e).replaceAll("\x7F","\\u007f")}function Ks(e){return On(Cn?e.toWellFormed():e)}function An(e){if(zs.test(e))return e;if(Cn&&!e.isWellFormed())throw new RangeError("key contains illegal lone surrogates");return On(e)}function Wt(e,t,r,n,i){if(r===0)throw new Error("Could not stringify the object: maximum object depth exceeded");switch(t){case"number":if(isNaN(e))return"nan";if(e===1/0)return"inf";if(e===-1/0)return"-inf";if(Number.isInteger(e)&&(n||!Number.isSafeInteger(e)))return e.toFixed(1);case"bigint":case"boolean":case"temporal":return e.toString();case"string":return Ks(e);case"date":if(isNaN(e.getTime()))throw new TypeError("cannot serialize invalid date");return e.toISOString();case"object":return Ys(e,r,n,i);case"array":return Zs(e,r,n,i);case"temporal/tz+uc":if(i){let s=e.timeZoneId,o=s.charCodeAt(0);if(o!==43&&o!==45&&(o!==85&&o!==71&&o!==90&&o!==69||s!=="UTC"&&s!=="UCT"&&s!=="Universal"&&s!=="Zulu"&&!s.startsWith("GMT")&&s!=="Greenwich"&&!s.startsWith("Etc/")))throw new TypeError("Temporal objects with an IANA timezone are not allowed in Temporal strict mode")}case"temporal/uc":if(i&&e.calendarId!=="iso8601")throw new TypeError("Temporal objects with a non-default calendar are not allowed in Temporal strict mode");return e.toString({calendarName:"never",timeZoneName:"never"});case"temporal/x":throw new TypeError("Unsupported "+e[Symbol.toStringTag])}}function Ys(e,t,r,n){let i=Object.keys(e);if(i.length===0)return"{}";let s="{ ";for(let o=0;o<i.length;o++){let a=i[o];o&&(s+=", "),s+=An(a)+" = "+Wt(e[a],we(e[a]),t-1,r,n)}return s+" }"}function Zs(e,t,r,n){if(e.length===0)return"[]";let i="[ ";for(let s=0;s<e.length;s++){if(s&&(i+=", "),e[s]===null||e[s]===void 0)throw new TypeError("arrays cannot contain null or undefined values");i+=Wt(e[s],we(e[s]),t-1,r,n)}return i+" ]"}function Xs(e,t,r,n,i){if(r===0)throw new Error("Could not stringify the object: maximum object depth exceeded");let s="";for(let o=0;o<e.length;o++)s+=`${s&&`
23
+ ${s}`,r),this.line=n,this.column=i,this.codeblock=s}static x(t,r,n){throw new e(t,{toml:r.s,ptr:n??r.p})}}});function ct(e){let t=e.p,r=e.s.charCodeAt(e.p++),n=r,i=r===39,s=r===e.s.charCodeAt(e.p)&&r===e.s.charCodeAt(e.p+1);s&&((r=e.s.charCodeAt(e.p+=2))===10?e.p++:r===13&&e.s.charCodeAt(e.p+1)===10&&(e.p+=2));let o="",a=e.p,l=0;for(;e.p<e.s.length;e.p++)if(r=e.s.charCodeAt(e.p),s&&(r===10||r===13&&e.s.charCodeAt(e.p+1)===10))l=l&&3;else if(r<32&&r!==9||r===127)p.x("control characters are not allowed in strings",e);else if((!l||l===3)&&r===n&&(!s||e.s.charCodeAt(e.p+1)===n&&e.s.charCodeAt(e.p+2)===n)){if(s&&(e.s.charCodeAt(e.p+3)===n&&e.p++,e.s.charCodeAt(e.p+3)===n&&e.p++),!l){let c=e.s.slice(a,e.p);o=o?o+c:c}return e.p+=s?3:1,o}else if(!l)!i&&r===92&&(o+=e.s.slice(a,a=e.p),l=1);else if(l===1)if(r===120||r===117||r===85){let c=e.p++-1,u=0,d=r===120?2:r===117?4:8;for(let f=0;f<d;f++,e.p++){let h=e.s.charCodeAt(e.p),g=h>=48&&h<=57?h-48:h>=65&&h<=70?h-65+10:h>=97&&h<=102?h-97+10:-1;g<0&&p.x("invalid non-hex character in unicode escape",e),u=u<<4|g}(u<0||u>1114111||u>=55296&&u<=57343)&&p.x("invalid unicode escape",e,c),o+=String.fromCodePoint(u),a=e.p--,l=0}else s&&(r===32||r===9)?l=2:(r===98?o+="\b":r===116?o+=" ":r===110?o+=`
24
+ `:r===102?o+="\f":r===114?o+="\r":r===101?o+="\x1B":r===34?o+='"':r===92?o+="\\":p.x("unrecognised escape sequence",e),a=e.p+1,l=0);else r!==32&&r!==9&&(l===2&&p.x("invalid escape: only line-ending whitespace may be escaped",e,a),l=!i&&r===92?1:0,a=e.p);p.x("unfinished string",e,t)}var Yt=y(()=>{X();});var co,xe,Zt=y(()=>{co=/^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i,xe=class e extends Date{#t=!1;#r=!1;#e=null;constructor(t,r,n){let i=!0,s=!0,o="Z",a;if(typeof t=="string")if(r)e:{if(r<3){if(+t.slice(11,13)>23){t="";break e}r===2?(o=null,t+="Z"):(a=t.charCodeAt(t.length-1))!==90&&a!==122&&(o=t.slice(t.length-6)),n&&(t=t.slice(0,10)+"T"+t.slice(11))}else r===4&&(t=+t.slice(0,2)>23?"":`0000-01-01T${t}Z`);i=r!==4,s=r!==3}else{let l=t.match(co);l?(l[1]||(i=!1,t=`0000-01-01T${t}`),s=!!l[2],s&&t[10]===" "&&(t=t.replace(" ","T")),l[2]&&+l[2]>23?t="":(o=l[3]||null,!o&&s&&(t+="Z"))):t=""}super(t),isNaN(this.getTime())||(this.#t=i,this.#r=s,this.#e=o)}isDateTime(){return this.#t&&this.#r}isLocal(){return!this.#t||!this.#r||!this.#e}isDate(){return this.#t&&!this.#r}isTime(){return this.#r&&!this.#t}isValid(){return this.#t||this.#r}toISOString(){let t=super.toISOString();if(this.isDate())return t.slice(0,10);if(this.isTime())return t.slice(11,23);if(this.#e===null)return t.slice(0,-1);if(this.#e==="Z"||this.#e==="z")return t;let r=+this.#e.slice(1,3)*60+ +this.#e.slice(4,6);return r=this.#e[0]==="-"?r:-r,new Date(this.getTime()-r*6e4).toISOString().slice(0,-1)+this.#e}static wrapAsOffsetDateTime(t,r="Z"){let n=new e(t);return n.#e=r,n}static wrapAsLocalDateTime(t){let r=new e(t);return r.#e=null,r}static wrapAsLocalDate(t){let r=new e(t);return r.#r=!1,r.#e=null,r}static wrapAsLocalTime(t){let r=new e(t);return r.#t=!1,r.#e=null,r}}});function C(e,t=10){return t===16?e>47&&e<58||e>64&&e<71||e>96&&e<103:e>47&&e<48+t}function Qt(e,t){return e===32||e===9||e===10||e===13||t&&(e===t||e===44)||e===35}function ke(e,t){let r=e.p,n=e.s.charCodeAt(e.p);if(n===91||n===123){e.d--||p.x("document contains excessively nested structures. aborting.",e);let i=n===91?qn(e):Wn(e);return e.d++,i}return n===34||n===39?ct(e):n===116?((e.s.charCodeAt(++e.p)!==114||e.s.charCodeAt(++e.p)!==117||e.s.charCodeAt(++e.p)!==101)&&p.x("invalid value",e,r),e.p++,!0):n===102?((e.s.charCodeAt(++e.p)!==97||e.s.charCodeAt(++e.p)!==108||e.s.charCodeAt(++e.p)!==115||e.s.charCodeAt(++e.p)!==101)&&p.x("invalid value",e,r),e.p++,!1):n===43||n===45?ft(e,e.p,e.s.charCodeAt(++e.p),44-n,t):e.s.charCodeAt(e.p+4)===45&&e.s.charCodeAt(e.p+7)===45?fo(e,n,t):e.s.charCodeAt(e.p+2)===58?uo(e,n,t):ft(e,e.p,n,0,t)}function ft(e,t,r,n,i){let s=r,o=0,a=!1;if(s===105)return(e.s.charCodeAt(++e.p)!==110||e.s.charCodeAt(++e.p)!==102)&&p.x("invalid value",e,t),e.p++,(n||1)/0;if(s===110)return(e.s.charCodeAt(++e.p)!==97||e.s.charCodeAt(++e.p)!==110)&&p.x("invalid value",e,t),e.p++,NaN;if(s===48){if(++e.p>=e.s.length||Qt(s=e.s.charCodeAt(e.p),i))return e.bi===!0?0n:0;if(!n){if(s===120)return Xt(e,t,16,i);if(s===98)return Xt(e,t,2,i);if(s===111)return Xt(e,t,8,i)}s===46?o=2:s===101||s===69?o=4:p.x("illegal leading zero",e,t)}else C(s)||p.x("invalid value",e,t);for(;++e.p<e.s.length&&(s=e.s.charCodeAt(e.p),!Qt(s,i));)o||(o=1),s===95?(o&1||p.x("illegal underscore",e),o+=11,a=!0):o===1&&s===46?o=2:(o===1||o===3)&&(s===101||s===69)?o=4:o===4&&(s===43||s===45)||(C(s)?o>9?o-=11:o&1||o++:p.x("illegal character in numeric literal",e));if(!o){let c=(r-48)*(n||1);return e.bi===!0?BigInt(c):c}o&1||p.x("unfinished numeric value",e,t);let l=e.s.slice(t,e.p);return a&&(l=l.replaceAll("_","")),o>1?parseFloat(l):Fn(e,l,10,t)}function Xt(e,t,r,n){let i,s=1;for(;++e.p<e.s.length&&(i=e.s.charCodeAt(e.p),!Qt(i,n));)i===95?(s&1&&p.x("illegal underscore",e),s=3):C(i,r)?s&1&&s--:p.x("illegal character in numeric literal",e);s&1&&p.x("unfinished numeric value",e);let o=e.s.slice(t+2,e.p);return s&&(o=o.replaceAll("_","")),Fn(e,o,r,t)}function Fn(e,t,r,n){if(e.bi!==!0)e:{let i=parseInt(t,r);if(!Number.isSafeInteger(i)){if(e.bi)break e;p.x("integer value cannot be represented losslessly",e,n)}return i}return BigInt(r===10?t:(r===2?"0b":r===8?"0o":"0x")+t)}function fo(e,t,r){let n=e.p++,i;if(!C(t)||!C(e.s.charCodeAt(e.p++))||!C(e.s.charCodeAt(e.p++))||!C(e.s.charCodeAt(e.p++)))return ft(e,e.p=n,t,0,r);if(e.p+=5,C(e.s.charCodeAt(e.p++))||p.x("invalid date-time: date part is malformed",e,n),e.p>=e.s.length||((t=e.s.charCodeAt(e.p))!==32||(i=!0,!C(e.s.charCodeAt(e.p+1))))&&t!==84&&t!==116){let o=e.s.slice(n,e.p);return Te(e,o,3,!1,n)}if(e.s.charCodeAt(e.p+=3)!==58&&p.x("invalid date-time: time part is malformed",e,n),e.s.charCodeAt(e.p+=3)===58&&(e.p+=3),e.s.charCodeAt(e.p)===46)for(;C(e.s.charCodeAt(++e.p)););if(t=e.s.charCodeAt(e.p)){if(t===90||t===122){let o=e.s.slice(n,++e.p);return Te(e,o,1,i,n,"[+00:00]")}if(t===43||t===45){let o=e.s.slice(n,e.p+=6);return Te(e,o,1,i,n,!e.ld&&"["+e.s.slice(e.p-6,e.p)+"]")}}let s=e.s.slice(n,e.p);return Te(e,s,2,i,n)}function uo(e,t,r){let n=e.p;if(!C(t)||!C(e.s.charCodeAt(++e.p)))return ft(e,--e.p,t,0,r);if(e.s.charCodeAt(e.p+=4)===58&&(e.p+=3),e.s.charCodeAt(e.p)===46)for(;C(e.s.charCodeAt(++e.p)););let i=e.s.slice(n,e.p);return Te(e,i,4,!1,n)}function Te(e,t,r,n,i,s){if(e.ld){let o=new xe(t,r,n);return o.isValid()||p.x("invalid date",e,i),o}try{switch(s&&(t+=s),r){case 1:return Temporal.ZonedDateTime.from(t);case 2:return Temporal.PlainDateTime.from(t);case 3:return Temporal.PlainDate.from(t);case 4:return Temporal.PlainTime.from(t)}}catch(o){p.x(o instanceof Error?o.message:""+o,e,i)}}var er=y(()=>{Yt();tr();X();Zt();});function ho(e){for(;e.p<e.s.length;e.p++){let t=e.s.charCodeAt(e.p);if(t===10)break;if(t===13&&e.s.charCodeAt(e.p+1)===10){e.p++;break}(t<32&&t!==9||t===127)&&p.x("control characters are not allowed in comments",e)}}function L(e,t,r){let n;for(;e.p<e.s.length;){for(;e.p<e.s.length&&((n=e.s.charCodeAt(e.p))===32||n===9||!t&&(n===10||n===13&&e.s.charCodeAt(e.p+1)===10));)e.p++;if(r||n!==35)break;ho(e)}}var rr=y(()=>{X();});function ut(e,t=61){let r,n=0,i=[],s,o=e.s.charCodeAt(r=e.p);do{if(o===t)return n||p.x("unexpected end of key",e),n===1&&i.push(e.s.slice(s,e.p)),e.p++,i;o===46?(n||p.x("illegal empty bare key",e),n===1&&i.push(e.s.slice(s,e.p)),n=0):!n&&(o===34||o===39)?(o===e.s.charCodeAt(e.p+1)&&o===e.s.charCodeAt(e.p+2)&&p.x("illegal quoted key: multiline strings are not allowed",e),i.push(ct(e)),n=2,e.p--):o===32||o===9?n===1&&(i.push(e.s.slice(s,e.p)),n=2):n===2||o<48&&o!==45||o>57&&o<65||o>90&&o<97&&o!==95||o>122?p.x("illegal character in key",e):n||(n=1,s=e.p)}while(o=e.s.charCodeAt(++e.p));p.x("incomplete key-value: cannot find end of key",e,r)}function Wn(e){let t=e.p++,r=Object.create(null),n=new Set,i;for(;e.p<e.s.length;){if(L(e),(i=e.s.charCodeAt(e.p))===125)return e.p++,r;let s,o=r,a=!1,l=e.p,c=ut(e);for(let d=0;d<c.length;d++){d&&(o=a?o[s]:o[s]=Object.create(null)),s=c[d],(a=Object.hasOwn(o,s))&&(typeof o[s]!="object"||n.has(o[s]))&&p.x("trying to redefine an already defined value",e,l);let f=s==="__proto__";if(e.uk&&(f||s==="constructor")){o=e.uk!==1&&p.x("document contains an unsafe property",e,l);break}!a&&f&&Object.defineProperty(o,s,{enumerable:!0,configurable:!0,writable:!0})}a&&p.x("trying to redefine an already defined value",e,l),L(e,!0,!0);let u=ke(e,125);if(o&&typeof(o[s]=u)=="object"&&n.add(u),L(e),(i=e.s.charCodeAt(e.p++))===125)return r;i!==44&&p.x("expected comma or end of structure",e,e.p-1)}p.x("unfinished table",e,t)}function qn(e){let t=e.p++,r=[],n;for(;e.p<e.s.length;){if(L(e),(n=e.s.charCodeAt(e.p))===93)return e.p++,r;if(r.push(ke(e,93)),L(e),(n=e.s.charCodeAt(e.p++))===93)return r;n!==44&&p.x("expected comma or end of structure",e,e.p-1)}p.x("unfinished array",e,t)}var tr=y(()=>{Yt();er();rr();X();});function Gn(e,t,r,n,i){let s=r,o=n,a,l=!1,c;for(let u=0;u<t.length;u++){if(u){if(s=l?s[a]:s[a]=Object.create(null),o=(c=o[a]).c,i===0&&(c.t===1||c.t===2))return null;if(c.t===2){let d=s.length-1;s=s[d],o=o[d].c}}if(a=t[u],(l=Object.hasOwn(s,a))&&o[a]?.t===0&&o[a]?.d)return null;if(!l){let d=a==="__proto__";if(e.uk&&(d||a==="constructor"))return!1;d&&(Object.defineProperty(s,a,{enumerable:!0,configurable:!0,writable:!0}),Object.defineProperty(o,a,{enumerable:!0,configurable:!0,writable:!0})),o[a]={t:u<t.length-1&&i===2?3:i,d:!1,i:0,c:Object.create(null)}}}if(c=o[a],c.t!==i&&!(i===1&&c.t===3)||(i===2&&(c.d||(c.d=!0,s[a]=[]),s[a].push(s=Object.create(null)),c.c[c.i++]=c={t:1,d:!1,i:0,c:Object.create(null)}),c.d))return null;if(c.d=!0,i===1)s=l?s[a]:s[a]=Object.create(null);else if(i===0&&l)return null;return[a,s,c.c]}function Vn(e,t,r){(t===null||e.uk===2)&&p.x(t===null?"trying to redefine an already defined table or value":"document contains an unsafe property",e,r)}function Ce(e,t={}){let r={s:e,p:0,d:t.maxDepth??1e3,bi:t.integersAsBigInt??!1,ld:t.useLegacyDate??!0,uk:t.unsafeKeyBehaviour==="throw"?2:t.unsafeKeyBehaviour==="drop"?1:0},n=Object.create(null),i=Object.create(null),s,o=!1,a=n,l=i;for(e.charCodeAt(0)===65279&&r.p++,L(r);r.p<e.length;){if(e.charCodeAt(r.p)===91){let c=e.charCodeAt(++r.p)===91;s=r.p+=+c,o=!1;let u=ut(r,93);c&&(e.charCodeAt(r.p)!==93&&p.x("expected end of table array declaration",r),r.p++);let d=Gn(r,u,n,i,c?2:1);d?(l=d[2],a=d[1]):(Vn(r,d,s),o=!0)}else{s=r.p;let c=ut(r),u=Gn(r,c,a,l,0);!u&&!o&&Vn(r,u,s),L(r,!0,!0);let d=ke(r,void 0);u&&!o&&(u[1][u[0]]=d)}L(r,!0),r.p<e.length&&(s=e.charCodeAt(r.p))!==10&&(s!==13||e.charCodeAt(r.p+1)!==10)&&p.x("each key-value declaration must be followed by an end-of-line",r),L(r)}return n}var Hn=y(()=>{tr();er();rr();X();});function Oe(e){let t=typeof e;if(t==="object"){if(Array.isArray(e))return"array";if(typeof e.getUTCDate=="function"&&e instanceof Date)return"date";if(globalThis.Temporal){if(e.until){if(e instanceof Temporal.ZonedDateTime)return"temporal/tz+uc";if(e instanceof Temporal.PlainDateTime||e instanceof Temporal.PlainDate)return"temporal/uc";if(e instanceof Temporal.PlainTime||e instanceof Temporal.Instant)return"temporal";if(e instanceof Temporal.PlainYearMonth)return"temporal/x"}else if(e.toPlainDate&&e instanceof Temporal.PlainMonthDay||e.negated&&e instanceof Temporal.Duration)return"temporal/x"}}return t}function mo(e){for(let t=0;t<e.length;t++)if(Oe(e[t])!=="object")return!1;return e.length!=0}function Jn(e){return JSON.stringify(e).replaceAll("\x7F","\\u007f")}function go(e){return Jn(zn?e.toWellFormed():e)}function Kn(e){if(po.test(e))return e;if(zn&&!e.isWellFormed())throw new RangeError("key contains illegal lone surrogates");return Jn(e)}function nr(e,t,r,n,i){if(r===0)throw new Error("Could not stringify the object: maximum object depth exceeded");switch(t){case"number":if(isNaN(e))return"nan";if(e===1/0)return"inf";if(e===-1/0)return"-inf";if(Number.isInteger(e)&&(n||!Number.isSafeInteger(e)))return e.toFixed(1);case"bigint":case"boolean":case"temporal":return e.toString();case"string":return go(e);case"date":if(isNaN(e.getTime()))throw new TypeError("cannot serialize invalid date");return e.toISOString();case"object":return _o(e,r,n,i);case"array":return yo(e,r,n,i);case"temporal/tz+uc":if(i){let s=e.timeZoneId,o=s.charCodeAt(0);if(o!==43&&o!==45&&(o!==85&&o!==71&&o!==90&&o!==69||s!=="UTC"&&s!=="UCT"&&s!=="Universal"&&s!=="Zulu"&&!s.startsWith("GMT")&&s!=="Greenwich"&&!s.startsWith("Etc/")))throw new TypeError("Temporal objects with an IANA timezone are not allowed in Temporal strict mode")}case"temporal/uc":if(i&&e.calendarId!=="iso8601")throw new TypeError("Temporal objects with a non-default calendar are not allowed in Temporal strict mode");return e.toString({calendarName:"never",timeZoneName:"never"});case"temporal/x":throw new TypeError("Unsupported "+e[Symbol.toStringTag])}}function _o(e,t,r,n){let i=Object.keys(e);if(i.length===0)return"{}";let s="{ ";for(let o=0;o<i.length;o++){let a=i[o];o&&(s+=", "),s+=Kn(a)+" = "+nr(e[a],Oe(e[a]),t-1,r,n)}return s+" }"}function yo(e,t,r,n){if(e.length===0)return"[]";let i="[ ";for(let s=0;s<e.length;s++){if(s&&(i+=", "),e[s]===null||e[s]===void 0)throw new TypeError("arrays cannot contain null or undefined values");i+=nr(e[s],Oe(e[s]),t-1,r,n)}return i+" ]"}function bo(e,t,r,n,i){if(r===0)throw new Error("Could not stringify the object: maximum object depth exceeded");let s="";for(let o=0;o<e.length;o++)s+=`${s&&`
19
25
  `}[[${t}]]
20
- `,s+=qt(0,e[o],t,r,n,i);return s}function qt(e,t,r,n,i,s){if(n===0)throw new Error("Could not stringify the object: maximum object depth exceeded");let o="",a="",l=Object.keys(t);for(let c=0;c<l.length;c++){let f=l[c];if(t[f]!==null&&t[f]!==void 0){let d=we(t[f]);if(d==="symbol"||d==="function")throw new TypeError(`cannot serialize values of type '${d}'`);let u=An(f);if(d==="array"&&Js(t[f]))a+=(a&&`
21
- `)+Xs(t[f],r?`${r}.${u}`:u,n-1,i,s);else if(d==="object"){let h=r?`${r}.${u}`:u;a+=(a&&`
22
- `)+qt(h,t[f],h,n-1,i,s)}else o+=u,o+=" = ",o+=Wt(t[f],d,n,i,s),o+=`
26
+ `,s+=ir(0,e[o],t,r,n,i);return s}function ir(e,t,r,n,i,s){if(n===0)throw new Error("Could not stringify the object: maximum object depth exceeded");let o="",a="",l=Object.keys(t);for(let c=0;c<l.length;c++){let u=l[c];if(t[u]!==null&&t[u]!==void 0){let d=Oe(t[u]);if(d==="symbol"||d==="function")throw new TypeError(`cannot serialize values of type '${d}'`);let f=Kn(u);if(d==="array"&&mo(t[u]))a+=(a&&`
27
+ `)+bo(t[u],r?`${r}.${f}`:f,n-1,i,s);else if(d==="object"){let h=r?`${r}.${f}`:f;a+=(a&&`
28
+ `)+ir(h,t[u],h,n-1,i,s)}else o+=f,o+=" = ",o+=nr(t[u],d,n,i,s),o+=`
23
29
  `}}return e&&(o||!a)&&(o=o?`[${e}]
24
30
  ${o}`:`[${e}]`),o&&a?`${o}
25
- ${a}`:o||a}function Vt(e,{maxDepth:t=1e3,numbersAsFloat:r=!1,strictTemporal:n=!1}={}){if(we(e)!=="object")throw new TypeError("stringify can only be called with an object");let i=qt(0,e,"",t,r,n);return i[i.length-1]!==`
31
+ ${a}`:o||a}function sr(e,{maxDepth:t=1e3,numbersAsFloat:r=!1,strictTemporal:n=!1}={}){if(Oe(e)!=="object")throw new TypeError("stringify can only be called with an object");let i=ir(0,e,"",t,r,n);return i[i.length-1]!==`
26
32
  `?i+`
27
- `:i}var zs,Cn,Nn=x(()=>{zs=/^[a-z0-9-_]+$/i,Cn=!!"".isWellFormed});var Pn=x(()=>{kn();Nn();Mt();Y();});function Ln(e,t){let r=e.paths(t);if(r.length===0)return null;for(let n of r)try{if((0,_.statSync)((0,Te.dirname)(n)).isDirectory())return n}catch{}return r[0]}function Qs(e){let t="",r=0,n=!1,i=!1;for(;r<e.length;){let s=e[r],o=e[r+1];if(n){t+=s,i?i=!1:s==="\\"?i=!0:s==='"'&&(n=!1),r++;continue}if(s==='"'){n=!0,t+=s,r++;continue}if(s==="/"&&o==="/"){for(;r<e.length&&e[r]!==`
33
+ `:i}var po,zn,Yn=y(()=>{po=/^[a-z0-9-_]+$/i,zn=!!"".isWellFormed});var Zn=y(()=>{Hn();Yn();Zt();X();});function ht(e,t){let r=e.paths(t);if(r.length===0)return null;for(let n of r)try{if((0,_.statSync)((0,Ae.dirname)(n)).isDirectory())return n}catch{}return r[0]}function So(e){let t="",r=0,n=!1,i=!1;for(;r<e.length;){let s=e[r],o=e[r+1];if(n){t+=s,i?i=!1:s==="\\"?i=!0:s==='"'&&(n=!1),r++;continue}if(s==='"'){n=!0,t+=s,r++;continue}if(s==="/"&&o==="/"){for(;r<e.length&&e[r]!==`
28
34
  `;)r++;continue}if(s==="/"&&o==="*"){for(r+=2;r<e.length&&!(e[r]==="*"&&e[r+1]==="/");)e[r]===`
29
35
  `&&(t+=`
30
- `),r++;r+=2;continue}t+=s,r++}return t}function nt(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function ke(e){try{return(0,_.existsSync)(e)?((0,_.writeFileSync)(`${e}.bak`,(0,_.readFileSync)(e)),!0):!1}catch{return!1}}function Dn(e){let{path:t,rootKey:r,serverName:n,entry:i}=e,s=(0,_.existsSync)(t),o={};if(s){let c=(0,_.readFileSync)(t,"utf8"),f;try{f=JSON.parse(c.trim()===""?"{}":Qs(c))}catch{throw new Error(`Existing config is not valid JSON: ${t}
31
- Fix or rename it first (setup left it untouched).`)}if(!nt(f))throw new Error(`Existing config root must be an object: ${t} (left untouched).`);o=f;let d=o[r];if(d!==void 0&&!nt(d))throw new Error(`Existing "${r}" is not an object: ${t} (left untouched).`)}let a=nt(o[r])?o[r]:{};a[n]=i,o[r]=a,(0,_.mkdirSync)((0,Te.dirname)(t),{recursive:!0});let l=s?ke(t):!1;return(0,_.writeFileSync)(t,`${JSON.stringify(o,null,2)}
32
- `,{mode:384}),{path:t,created:!s,backedUp:l}}function Rn(e,t){let r=(0,_.existsSync)(e),n=r?xe((0,_.readFileSync)(e,"utf8")):{},i=xe(`${eo}
36
+ `),r++;r+=2;continue}t+=s,r++}return t}function dt(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Ne(e){try{return(0,_.existsSync)(e)?((0,_.writeFileSync)(`${e}.bak`,(0,_.readFileSync)(e)),!0):!1}catch{return!1}}function pt(e){let{path:t,rootKey:r,serverName:n,entry:i}=e,s=(0,_.existsSync)(t),o={};if(s){let c=(0,_.readFileSync)(t,"utf8"),u;try{u=JSON.parse(c.trim()===""?"{}":So(c))}catch{throw new Error(`Existing config is not valid JSON: ${t}
37
+ Fix or rename it first (setup left it untouched).`)}if(!dt(u))throw new Error(`Existing config root must be an object: ${t} (left untouched).`);o=u;let d=o[r];if(d!==void 0&&!dt(d))throw new Error(`Existing "${r}" is not an object: ${t} (left untouched).`)}let a=dt(o[r])?o[r]:{};a[n]=i,o[r]=a,(0,_.mkdirSync)((0,Ae.dirname)(t),{recursive:!0});let l=s?Ne(t):!1;return(0,_.writeFileSync)(t,`${JSON.stringify(o,null,2)}
38
+ `,{mode:384}),{path:t,created:!s,backedUp:l}}function mt(e,t){let r=(0,_.existsSync)(e),n=r?Ce((0,_.readFileSync)(e,"utf8")):{},i=Ce(`${vo}
33
39
  ${t}
34
- `);if(n.mcp_servers!==void 0&&!nt(n.mcp_servers))throw new Error("Existing mcp_servers must be a table (left untouched)");let s=n.mcp_servers??{};s.babtab=i.mcp_servers.babtab,n.mcp_servers=s;let o=Vt(n);xe(o),(0,_.mkdirSync)((0,Te.dirname)(e),{recursive:!0});let a=r?ke(e):!1;if(r&&!a)throw new Error(`Cannot back up ${e}; left untouched`);let l=`${e}.${(0,In.randomUUID)()}.tmp`;try{(0,_.writeFileSync)(l,o,{mode:384,flag:"wx"}),(0,_.renameSync)(l,e)}finally{(0,_.rmSync)(l,{force:!0})}return{path:e,created:!r,backedUp:a}}function Mn(e,t){let r=(0,_.existsSync)(e),n;if(!r)n=`${t}
40
+ `);if(n.mcp_servers!==void 0&&!dt(n.mcp_servers))throw new Error("Existing mcp_servers must be a table (left untouched)");let s=n.mcp_servers??{};s.babtab=i.mcp_servers.babtab,n.mcp_servers=s;let o=sr(n);Ce(o),(0,_.mkdirSync)((0,Ae.dirname)(e),{recursive:!0});let a=r?Ne(e):!1;if(r&&!a)throw new Error(`Cannot back up ${e}; left untouched`);let l=`${e}.${(0,Xn.randomUUID)()}.tmp`;try{(0,_.writeFileSync)(l,o,{mode:384,flag:"wx"}),(0,_.renameSync)(l,e)}finally{(0,_.rmSync)(l,{force:!0})}return{path:e,created:!r,backedUp:a}}function gt(e,t){let r=(0,_.existsSync)(e),n;if(!r)n=`${t}
35
41
  `;else{let s=(0,_.readFileSync)(e,"utf8").split(`
36
42
  `),o=s.findIndex(a=>/^mcp_servers\s*:\s*(#.*)?$/.test(a));if(o===-1){let a=s.length>0&&s[s.length-1].trim()!==""?`
37
43
  `:"";n=`${s.join(`
38
44
  `)}${a}
39
45
  ${t}
40
- `}else{let a=o+1;for(;a<s.length&&(s[a].trim()===""||/^\s+/.test(s[a]));)a++;let l=s.slice(o+1,a),c=l.findIndex(u=>/^\s*babtab\s*:\s*(#.*)?$/.test(u)),f=t.split(`
46
+ `}else{let a=o+1;for(;a<s.length&&(s[a].trim()===""||/^\s+/.test(s[a]));)a++;let l=s.slice(o+1,a),c=l.findIndex(f=>/^\s*babtab\s*:\s*(#.*)?$/.test(f)),u=t.split(`
41
47
  `).slice(1).join(`
42
- `),d;if(c===-1)d=[...l,f];else{let u=l[c].match(/^\s*/)?.[0].length??2,h=c+1;for(;h<l.length&&(l[h].trim()===""||(l[h].match(/^\s*/)?.[0].length??0)>u);)h++;d=[...l.slice(0,c),f,...l.slice(h)]}n=[...s.slice(0,o+1),...d,...s.slice(a)].join(`
48
+ `),d;if(c===-1)d=[...l,u];else{let f=l[c].match(/^\s*/)?.[0].length??2,h=c+1;for(;h<l.length&&(l[h].trim()===""||(l[h].match(/^\s*/)?.[0].length??0)>f);)h++;d=[...l.slice(0,c),u,...l.slice(h)]}n=[...s.slice(0,o+1),...d,...s.slice(a)].join(`
43
49
  `),n.endsWith(`
44
50
  `)||(n+=`
45
- `)}}(0,_.mkdirSync)((0,Te.dirname)(e),{recursive:!0});let i=r?ke(e):!1;return(0,_.writeFileSync)(e,n,{mode:384}),{path:e,created:!r,backedUp:i}}var In,_,Te,eo,$n=x(()=>{"use strict";Pn();In=require("node:crypto"),_=require("node:fs"),Te=require("node:path");eo="[mcp_servers.babtab]"});async function Bn(e,t,r){let n;try{n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(r)})}catch(s){throw new Z(`Cannot reach relay at ${e}: ${String(s)}`)}let i={};try{i=await n.json()}catch{}return{status:n.status,json:i}}async function Gt(e){let t;try{t=await fetch(`${e}/health`,{signal:AbortSignal.timeout(3e3)})}catch(n){throw new Z(`Cannot reach relay at ${e}/health: ${String(n)}`)}if(!t.ok)throw new Z(`Relay health check failed: HTTP ${t.status}`);let r=await t.json();return{ok:r.ok===!0,devices:typeof r.devices=="number"?r.devices:0}}async function Un(e,t,r){let{status:n,json:i}=await Bn(`${e}/pairing/request`,{deviceId:t,clientName:r,scopes:["browser:read","browser:act"]},3e3);if(n===429)throw new Ce(String(i.error??"rate limited, wait and retry"));if(n!==200||typeof i.code!="string")throw new Error(`Pairing request failed: HTTP ${n} ${String(i.error??"")}`.trim());return{code:i.code,expiresAt:typeof i.expiresAt=="number"?i.expiresAt:0,deviceOnline:i.deviceOnline===!0}}async function jn(e,t,r={}){let n=r.intervalMs??2e3,i=r.timeoutMs??3e5,s=Date.now()+i;for(;;){let{json:o}=await Bn(`${e}/pairing/claim`,{code:t},3e3),a=String(o.status??"");if(a==="approved"&&typeof o.token=="string")return o.token;if(a==="expired")throw new Oe("Pairing code expired \u2014 run the setup command again.");if(Date.now()>=s)throw new Ae("Timed out waiting for approval \u2014 run the setup command again.");await new Promise(l=>setTimeout(l,n))}}var Z,Ce,Oe,Ae,Fn=x(()=>{"use strict";Z=class extends Error{},Ce=class extends Error{},Oe=class extends Error{},Ae=class extends Error{}});var zt={};Zt(zt,{DEFAULT_PORT:()=>Ne,SERVER_NAME:()=>qn,VERIFY_SENTENCE:()=>it,backupFile:()=>ke,copilotJsonEntry:()=>Lt,httpJsonEntry:()=>Qe,listTargetCommands:()=>Gn,parseSetupArgs:()=>Vn,runSetup:()=>ro,setupHelp:()=>Ht,stdioRemoteJsonEntry:()=>Dt});function Vn(e){let t={target:"",port:Number(process.env.PORT??Ne),relayUrl:null,deviceId:null,help:!1,listTargets:!1},r=(n,i)=>{let s=e[n];if(s===void 0||s==="")throw new Error(`Missing value for ${i}`);return s};for(let n=0;n<e.length;n++){let i=e[n],[s,o]=i.includes("=")?i.split("=",2):[i,void 0],a=l=>o??r(++n,l);switch(s){case"--target":case"-t":t.target=a("--target");break;case"--port":case"-p":{let l=Number(a("--port"));if(!Number.isInteger(l)||l<1||l>65535)throw new Error("Invalid --port: expected 1-65535");t.port=l;break}case"--device":case"-d":t.deviceId=a("--device");break;case"--relay-url":t.relayUrl=a("--relay-url").replace(/\/+$/,"");break;case"--list-targets":case"--list":t.listTargets=!0;break;case"--help":case"-h":t.help=!0;break;default:throw new Error(`Unknown option: ${i} (see --help)`)}}if(!Number.isInteger(t.port)||t.port<1||t.port>65535)throw new Error(`Invalid PORT: expected 1-65535 (got ${process.env.PORT})`);return t}function to(e){let t=e.action.kind==="print"?"":" --device <deviceId>";return`npx -y @babtab/relay setup --target ${e.id} --port ${Ne}${t}`}function Ht(){return["babtab setup \u2014 pair + write your harness MCP config in one step","","Usage:"," npx -y @babtab/relay setup --target <id> --port <port> --device <deviceId>"," (Copy the exact line from the Babtab Side Panel \u2192 Step 2; it has your port + device.)","","Targets:",Se.map(t=>` ${t.id.padEnd(17)} ${t.label}`).join(`
46
- `),"","Options:"," --target, -t <id> Harness to configure (required, see list above)",` --port, -p <n> Relay port (default ${Ne}, or $PORT)`," --device, -d <id> Extension device id (from Side Panel Step 2)"," --relay-url <url> Override http base for a remote relay (VPS), e.g. https://relay.example.com:3000"," --list-targets Print one ready-to-paste command per target and exit"," --help, -h Show this help","","Flow:"," 1. Make sure the relay is running: npx -y @babtab/relay"," 2. Finish Side Panel Step 1 (Save & Connect) so your Chrome is online."," 3. Run the Step 2 command, approve the 6-digit code in the Side Panel.",` 4. Reload MCP in your harness, then ask: "${it}".`,""].join(`
47
- `)}function Gn(){return Se.map(e=>`# ${e.label}
48
- ${to(e)}`).join(`
51
+ `)}}(0,_.mkdirSync)((0,Ae.dirname)(e),{recursive:!0});let i=r?Ne(e):!1;return(0,_.writeFileSync)(e,n,{mode:384}),{path:e,created:!r,backedUp:i}}var Xn,_,Ae,vo,or=y(()=>{"use strict";Zn();Xn=require("node:crypto"),_=require("node:fs"),Ae=require("node:path");vo="[mcp_servers.babtab]"});function wo(e,t,r){if(!/^dev_v2_[a-f0-9]{64}$/.test(e))throw new Error("Invalid device ID. Copy the command from the Babtab extension.");return{command:"npx",args:["-y",Eo,"stdio","--device",e,"--client",t,"--port",String(r)]}}function ei(e,t,r,n=at()){let i=wo(t,e.id,r),s=e.action;if(s.kind==="exec"){let o=["mcp","add","--transport","stdio","--scope","user","babtab","--",i.command,...i.args],a=(0,Qn.spawnSync)("claude",o,{stdio:"inherit",shell:process.platform==="win32"});if(a.error||a.status!==0)throw new Error("Could not add Babtab to Claude Code. Check that the claude CLI is installed; if babtab already exists, remove its old MCP entry and retry.")}else{let o=ht(e,n);if(!o)throw new Error(`Automatic setup is unavailable for ${e.label}`);s.kind==="json"?pt({path:o,rootKey:s.rootKey,serverName:"babtab",entry:{...i,...s.entry==="copilot-http"?{type:"stdio"}:{}}}):s.kind==="toml-codex"?mt(o,`command = ${JSON.stringify(i.command)}
52
+ args = ${JSON.stringify(i.args)}`):s.kind==="yaml-hermes"&&gt(o,`mcp_servers:
53
+ babtab:
54
+ command: ${JSON.stringify(i.command)}
55
+ args: ${JSON.stringify(i.args)}`),console.log(`Configured ${o} (existing settings preserved; backup created when replacing a file).`)}return console.log(`
56
+ ${e.nextStep.replace(" (via mcp-remote bridge)","")}
57
+ Your AI tool starts Babtab automatically. Open Babtab in Chrome and approve the first connection.
58
+ Then ask: "Use babtab to observe the current tab".`),0}var Qn,Eo,ti=y(()=>{"use strict";Qn=require("node:child_process");Kt();or();Eo="@babtab/relay@0.2.0"});async function ri(e,t,r){let n;try{n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(r)})}catch(s){throw new Q(`Cannot reach relay at ${e}: ${String(s)}`)}let i={};try{i=await n.json()}catch{}return{status:n.status,json:i}}async function ar(e){let t;try{t=await fetch(`${e}/health`,{signal:AbortSignal.timeout(3e3)})}catch(n){throw new Q(`Cannot reach relay at ${e}/health: ${String(n)}`)}if(!t.ok)throw new Q(`Relay health check failed: HTTP ${t.status}`);let r=await t.json();return{ok:r.ok===!0,devices:typeof r.devices=="number"?r.devices:0}}async function ni(e,t,r){let{status:n,json:i}=await ri(`${e}/pairing/request`,{deviceId:t,clientName:r,scopes:["browser:read","browser:act"]},3e3);if(n===429)throw new Pe(String(i.error??"rate limited, wait and retry"));if(n!==200||typeof i.code!="string")throw new Error(`Pairing request failed: HTTP ${n} ${String(i.error??"")}`.trim());return{code:i.code,expiresAt:typeof i.expiresAt=="number"?i.expiresAt:0,deviceOnline:i.deviceOnline===!0}}async function ii(e,t,r={}){let n=r.intervalMs??2e3,i=r.timeoutMs??3e5,s=Date.now()+i;for(;;){let{json:o}=await ri(`${e}/pairing/claim`,{code:t},3e3),a=String(o.status??"");if(a==="approved"&&typeof o.token=="string")return o.token;if(a==="expired")throw new Ie("Pairing code expired \u2014 run the setup command again.");if(Date.now()>=s)throw new De("Timed out waiting for approval \u2014 run the setup command again.");await new Promise(l=>setTimeout(l,n))}}var Q,Pe,Ie,De,si=y(()=>{"use strict";Q=class extends Error{},Pe=class extends Error{},Ie=class extends Error{},De=class extends Error{}});var cr={};vt(cr,{DEFAULT_PORT:()=>Le,SERVER_NAME:()=>ai,VERIFY_SENTENCE:()=>_t,backupFile:()=>Ne,copilotJsonEntry:()=>zt,httpJsonEntry:()=>lt,listTargetCommands:()=>ci,parseSetupArgs:()=>li,runSetup:()=>To,setupHelp:()=>lr,stdioRemoteJsonEntry:()=>Jt});function li(e){let t={target:"",port:Number(process.env.PORT??Le),relayUrl:null,deviceId:null,help:!1,listTargets:!1},r=(n,i)=>{let s=e[n];if(s===void 0||s==="")throw new Error(`Missing value for ${i}`);return s};for(let n=0;n<e.length;n++){let i=e[n],[s,o]=i.includes("=")?i.split("=",2):[i,void 0],a=l=>o??r(++n,l);switch(s){case"--target":case"-t":t.target=a("--target");break;case"--port":case"-p":{let l=Number(a("--port"));if(!Number.isInteger(l)||l<1||l>65535)throw new Error("Invalid --port: expected 1-65535");t.port=l;break}case"--device":case"-d":t.deviceId=a("--device");break;case"--relay-url":t.relayUrl=a("--relay-url").replace(/\/+$/,"");break;case"--list-targets":case"--list":t.listTargets=!0;break;case"--help":case"-h":t.help=!0;break;default:throw new Error(`Unknown option: ${i} (see --help)`)}}if(!Number.isInteger(t.port)||t.port<1||t.port>65535)throw new Error(`Invalid PORT: expected 1-65535 (got ${process.env.PORT})`);return t}function xo(e){let t=e.action.kind==="print"?"":" --device <deviceId>";return`npx -y @babtab/relay setup --target ${e.id} --port ${Le}${t}`}function lr(){return["babtab setup \u2014 configure your AI tool to start Babtab automatically","","Usage:"," npx -y @babtab/relay setup --target <id> --port <port> --device <deviceId>"," (Copy the exact line from the Babtab Side Panel \u2192 Other AI tools / install with a command; it has your port + device.)","","Targets:",we.map(t=>` ${t.id.padEnd(17)} ${t.label}`).join(`
59
+ `),"","Options:"," --target, -t <id> Harness to configure (required, see list above)",` --port, -p <n> Relay port (default ${Le}, or $PORT)`," --device, -d <id> Extension device id (from the Babtab extension)"," --relay-url <url> Override http base for a remote relay (VPS), e.g. https://relay.example.com:3000"," --list-targets Print one ready-to-paste command per target and exit"," --help, -h Show this help","","Flow:"," 1. Copy the setup command from the Babtab extension and run it once."," 2. Enable / reload MCP in your AI tool; it starts Babtab automatically."," 3. Open Babtab in Chrome and approve the first connection.",` 4. Ask: "${_t}".`," Remote --relay-url connections still require an already-running relay and pairing.",""].join(`
60
+ `)}function ci(){return we.map(e=>`# ${e.label}
61
+ ${xo(e)}`).join(`
49
62
 
50
63
  `)+`
51
- `}function Hn(e){return e===Ne?"npx -y @babtab/relay":`PORT=${e} npx -y @babtab/relay`}async function ro(e){let t;try{t=Vn(e)}catch(o){return console.error(`Error: ${o.message}
52
- `),console.error(Ht()),1}if(t.help)return console.log(Ht()),0;if(t.listTargets)return console.log(Gn()),0;let r=mn(t.target);if(!r)return console.error(`Error: unknown --target "${t.target}". Pick one of:
53
- `),console.error(Se.map(o=>` ${o.id}`).join(`
54
- `)),1;let n=t.relayUrl??`http://127.0.0.1:${t.port}`;if(r.action.kind==="print")return no(r,n,t);if(!t.deviceId)return console.error(`Error: --device is required.
55
- Copy the full command from the Babtab Side Panel \u2192 Step 2 (it includes --device).`),1;try{await Gt(n)}catch(o){if(o instanceof Z)return console.error(`Error: relay is not reachable at ${n}.
64
+ `}function fi(e){return e===Le?"npx -y @babtab/relay":`PORT=${e} npx -y @babtab/relay`}async function To(e){let t;try{t=li(e)}catch(o){return console.error(`Error: ${o.message}
65
+ `),console.error(lr()),1}if(t.help)return console.log(lr()),0;if(t.listTargets)return console.log(ci()),0;let r=$n(t.target);if(!r)return console.error(`Error: unknown --target "${t.target}". Pick one of:
66
+ `),console.error(we.map(o=>` ${o.id}`).join(`
67
+ `)),1;let n=t.relayUrl??`http://127.0.0.1:${t.port}`;if(r.action.kind==="print")return ko(r,n,t);if(!t.deviceId)return console.error(`Error: --device is required.
68
+ Copy the full command from the Babtab Side Panel \u2192 Other AI tools / install with a command (it includes --device).`),1;if(!t.relayUrl)try{return ei(r,t.deviceId,t.port)}catch(o){return console.error(`Error: ${o.message}`),4}try{await ar(n)}catch(o){if(o instanceof Q)return console.error(`Error: relay is not reachable at ${n}.
56
69
  Start it first in another terminal:
57
70
 
58
- ${Hn(t.port)}
59
- `),2;throw o}let i;try{let o=await Un(n,t.deviceId,r.id);if(!o.deviceOnline)return console.error(`Error: your Chrome is not connected to the relay.
60
- Finish Side Panel Step 1 (Save & Connect) first, then re-run this command.`),3;i=o.code}catch(o){return o instanceof Ce?(console.error(`Error: ${o.message}. Wait a few seconds and re-run.`),3):(console.error(`Error: pairing request failed: ${o.message}`),3)}console.log(""),console.log(`Pairing code: ${i}`),console.log("Approve it in the Babtab Side Panel (a pairing banner appears at the top)."),console.log("Waiting for approval\u2026");let s;try{s=await jn(n,i)}catch(o){return o instanceof Oe||o instanceof Ae?(console.error(`Error: ${o.message}`),3):(console.error(`Error: claim failed: ${o.message}`),3)}console.log("Approved \u2713");try{return io(r,n,s)}catch(o){return console.error(`Error: ${o.message}`),4}}async function no(e,t,r){if(e.action.kind!=="print")return 1;try{await Gt(t)}catch{console.log(`Note: relay is not reachable at ${t} yet \u2014 start it with:
71
+ ${fi(t.port)}
72
+ `),2;throw o}let i;try{let o=await ni(n,t.deviceId,r.id);if(!o.deviceOnline)return console.error(`Error: your Chrome is not connected to the relay.
73
+ Open Advanced connection settings and use Save & Connect first, then re-run this command.`),3;i=o.code}catch(o){return o instanceof Pe?(console.error(`Error: ${o.message}. Wait a few seconds and re-run.`),3):(console.error(`Error: pairing request failed: ${o.message}`),3)}console.log(""),console.log(`Pairing code: ${i}`),console.log("Approve it in the Babtab Side Panel (a pairing banner appears at the top)."),console.log("Waiting for approval\u2026");let s;try{s=await ii(n,i)}catch(o){return o instanceof Ie||o instanceof De?(console.error(`Error: ${o.message}`),3):(console.error(`Error: claim failed: ${o.message}`),3)}console.log("Approved \u2713");try{return Co(r,n,s)}catch(o){return console.error(`Error: ${o.message}`),4}}async function ko(e,t,r){if(e.action.kind!=="print")return 1;try{await ar(t)}catch{console.log(`Note: relay is not reachable at ${t} yet \u2014 start it with:
61
74
 
62
- ${Hn(r.port)}
63
- `)}return e.action.what==="curl"?(console.log("Pi has no native MCP support. You need a token first:"),console.log(" 1. In the Side Panel, use Step 2 \u2192 Manual to pair and copy a token."),console.log(` 2. Verify the relay with (replace <token>):
64
- `),console.log(` ${Sn(t,"<token>")}
75
+ ${fi(r.port)}
76
+ `)}return e.action.what==="curl"?(console.log("Pi has no native MCP support. You need a token first:"),console.log(" 1. In the Side Panel, choose Other AI tools \u2192 Manual to pair and copy a token."),console.log(` 2. Verify the relay with (replace <token>):
77
+ `),console.log(` ${jn(t,"<token>")}
65
78
  `)):(console.log("Standard MCP (Streamable HTTP):"),console.log(` Endpoint: ${t}/mcp`),console.log(` Header: Authorization: Bearer <token>
66
- `),console.log("Get a token: Side Panel \u2192 Step 2 \u2192 Manual \u2192 Copy config (pairing runs automatically)."),console.log("Flow: initialize \u2192 tools/list \u2192 tools/call (JSON-RPC 2.0).")),0}function io(e,t,r){let n=e.action;if(n.kind==="exec"){let l=n.argv(t,r),c=(0,Wn.spawnSync)(l[0],l.slice(1),{stdio:"inherit",shell:process.platform==="win32"});if(c.error){let f=c.error.code==="ENOENT";return console.error(f?`The "${l[0]}" CLI was not found. Install it, then run:
79
+ `),console.log("Get a token: Side Panel \u2192 Other AI tools \u2192 Manual \u2192 Manual HTTP configuration (pairing runs automatically)."),console.log("Flow: initialize \u2192 tools/list \u2192 tools/call (JSON-RPC 2.0).")),0}function Co(e,t,r){let n=e.action;if(n.kind==="exec"){let l=n.argv(t,r),c=(0,oi.spawnSync)(l[0],l.slice(1),{stdio:"inherit",shell:process.platform==="win32"});if(c.error){let u=c.error.code==="ENOENT";return console.error(u?`The "${l[0]}" CLI was not found. Install it, then run:
67
80
 
68
81
  ${l.join(" ")}
69
82
  `:`Failed to run "${l[0]}": ${c.error.message}`),4}return c.status!==0?(console.error(`"${l[0]}" exited with code ${c.status}. Re-run the setup command to retry.`),4):(console.log(`
70
- Configured ${e.label} \u2713`),console.log(e.nextStep),console.log(`Then ask: "${it}".`),0)}let i=pn(),s=Ln(e,i);if(!s)return console.error(`Error: no config path for target "${e.id}".`),4;let o,a;if(n.kind==="json"){let l=gn(n.entry,t,r);({created:o,backedUp:a}=Dn({path:s,rootKey:n.rootKey,serverName:qn,entry:l}))}else if(n.kind==="toml-codex")({created:o,backedUp:a}=Rn(s,_n(t,r)));else if(n.kind==="yaml-hermes")({created:o,backedUp:a}=Mn(s,yn(t,r)));else return console.error(`Error: unsupported action for target "${e.id}".`),4;return console.log(`
71
- Wrote ${s} ${o?"(created)":"(updated, babtab entry replaced)"} \u2713`),a&&console.log(`Backup: ${s}.bak`),console.log(e.nextStep),console.log(`Then ask: "${it}".`),0}var Wn,Ne,qn,it,Jt=x(()=>{"use strict";Wn=require("node:child_process");bn();$n();Fn();Ne=3e3,qn="babtab",it="Use babtab to observe the current tab"});var Xe=require("node:crypto");function L(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function le(e){return new Promise((t,r)=>{let n=0,i=[],s=!1,o=(a,l)=>{s||(s=!0,i.length=0,r(Object.assign(new Error(l),{status:a})))};e.on("data",a=>{if(s)return;let l=Buffer.isBuffer(a)?a:Buffer.from(a);if(n+=l.length,n>256e3){o(413,"body too large");return}i.push(l)}),e.on("end",()=>{if(!s)try{let a=JSON.parse(Buffer.concat(i).toString("utf8")||"{}");if(!L(a)){o(400,"JSON body must be an object");return}s=!0,t(a)}catch{o(400,"Invalid JSON")}}),e.on("error",()=>o(400,"Request interrupted")),e.on("close",()=>{s||o(400,"Request interrupted")})})}var V={type:"object",description:"Semantic target: durable ref (@Hxxxx) or role/name/region query.",properties:{ref:{type:"string"},role:{type:"string"},name:{type:"string"},nameContains:{type:"string"},label:{type:"string"},region:{type:"string"}}},ei={type:"object",description:"Postcondition to verify after dispatch (url_changed, url_matches, element_appeared, element_disappeared, value_equals, value_changed, navigation_completed, etc.).",properties:{type:{type:"string",enum:["url_changed","url_matches","element_appeared","element_disappeared","value_equals","value_changed","checked","selection_changed","title_changed","navigation_completed","region_changed"]},value:{type:"string"},query:V,regionId:{type:"string"}},required:["type"],additionalProperties:!0},lt={type:"array",description:"Postconditions to verify after dispatch.",items:ei},ti={type:"object",description:"Single guarded action contract.",properties:{action:{type:"string",enum:["click","fill","select","press","scroll","navigate","back","forward","hover"]},target:V,value:{type:"string"},key:{type:"string"},url:{type:"string"},expect:lt,timeoutMs:{type:"number"}},required:["action"],additionalProperties:!0},ct=[{name:"browser_observe",description:"Compact page/region digest of the controlled tab.",inputSchema:{type:"object",properties:{level:{type:"string"},regionId:{type:"string"},includeRecentDiff:{type:"boolean"}}},scope:"browser:read"},{name:"browser_find",description:"Fast semantic lookup returning durable refs.",inputSchema:{type:"object",properties:{role:{type:"string"},name:{type:"string"},nameContains:{type:"string"},region:{type:"string"}}},scope:"browser:read"},{name:"browser_click",description:"Click a semantic target (guarded, verified).",inputSchema:{type:"object",properties:{target:V,expect:lt},required:["target"]},scope:"browser:act"},{name:"browser_fill",description:"Fill a field and verify the value.",inputSchema:{type:"object",properties:{target:V,value:{type:"string"},expect:lt},required:["target","value"]},scope:"browser:act"},{name:"browser_select",description:"Choose a select option.",inputSchema:{type:"object",properties:{target:V,value:{type:"string"}},required:["target","value"]},scope:"browser:act"},{name:"browser_press",description:"Press a key on a target or the focused element.",inputSchema:{type:"object",properties:{target:V,key:{type:"string"}}},scope:"browser:act"},{name:"browser_scroll",description:"Scroll a target into view or scroll the page.",inputSchema:{type:"object",properties:{target:V,direction:{type:"string"}}},scope:"browser:act"},{name:"browser_navigate",description:"Navigate the controlled tab (site grant required).",inputSchema:{type:"object",properties:{url:{type:"string"}},required:["url"]},scope:"browser:act"},{name:"browser_back",description:"Tab history back.",inputSchema:{type:"object",properties:{}},scope:"browser:act"},{name:"browser_forward",description:"Tab history forward.",inputSchema:{type:"object",properties:{}},scope:"browser:act"},{name:"browser_tabs",description:"List open tabs.",inputSchema:{type:"object",properties:{}},scope:"browser:read"},{name:"browser_switch_tab",description:"Switch control to another tab.",inputSchema:{type:"object",properties:{tabId:{type:"number"}},required:["tabId"]},scope:"browser:act"},{name:"browser_screenshot",description:"Capture the visible tab (rate-limited fallback).",inputSchema:{type:"object",properties:{}},scope:"browser:read"},{name:"browser_extract",description:"Extract text/table data plus article body paragraphs (passwords never returned).",inputSchema:{type:"object",properties:{regionId:{type:"string"},maxRows:{type:"number"}}},scope:"browser:read"},{name:"browser_wait",description:"Wait for a condition or timeout.",inputSchema:{type:"object",properties:{timeoutMs:{type:"number"},urlMatches:{type:"string"}}},scope:"browser:read"},{name:"browser_plan",description:"Guarded micro-plan: multiple verified steps, one decision.",inputSchema:{type:"object",properties:{steps:{type:"array",description:"Ordered guarded steps (1-25).",items:ti},abortOn:{type:"array",description:"Abort conditions (defaults to all four).",items:{type:"string",enum:["navigation","ambiguous_target","permission_required","page_epoch_changed"]}}},required:["steps"]},scope:"browser:act"}];function Pe(e){return ct.find(t=>t.name===e)}fe();var cn=require("node:http");var vs=U(Jr(),1),xs=U(Fe(),1),ws=U(te(),1),Ts=U(bt(),1),ks=U(xt(),1),Cs=U(At(),1),Os=U(Ge(),1),Pt=U(rn(),1);function nn(){return`m_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}function ze(e,t,r){return{id:e,kind:"response",error:{code:t,message:r}}}var Ke=require("node:crypto"),W=require("node:fs"),an=require("node:path");function on(e){return String(e?Math.floor(1e5+e()*9e5):(0,Ke.randomInt)(1e5,1e6))}var Je=class{sessions=new Map;tokens=new Map;lastRequestAt=new Map;persistPath;revokeListeners=new Set;onRevoke(t){this.revokeListeners.add(t)}revoked(t){for(let r of this.revokeListeners)r(t)}constructor(t={}){if(this.persistPath=t.persistPath,this.persistPath&&(0,W.existsSync)(this.persistPath))try{let r=JSON.parse((0,W.readFileSync)(this.persistPath,"utf8")),n=Date.now();for(let i of r){if(!i?.token||!i?.deviceId)continue;let s=typeof i.expiresAt=="number"?i.expiresAt:i.createdAt+7776e6;s<=n||this.tokens.set(i.token,{...i,expiresAt:s})}}catch{}}persist(){if(this.persistPath)try{(0,W.mkdirSync)((0,an.dirname)(this.persistPath),{recursive:!0}),(0,W.writeFileSync)(this.persistPath,JSON.stringify([...this.tokens.values()]),{mode:384})}catch{}}requestPairing(t,r,n,i=Date.now(),s){this.scrub(i);let o=this.lastRequestAt.get(t);if(o!==void 0&&i>=o&&i-o<5e3)throw Object.assign(new Error("RATE_LIMITED: pairing requested too soon"),{code:"RATE_LIMITED"});if([...this.sessions.values()].filter(h=>h.deviceId===t&&!h.approved).length>=5)throw Object.assign(new Error("RATE_LIMITED: too many pending pairings for device"),{code:"RATE_LIMITED"});if(this.sessions.size>=100)throw Object.assign(new Error("RATE_LIMITED: pairing store full"),{code:"RATE_LIMITED"});let l=on(s),c=0;for(;this.sessions.has(l)&&c++<100;)l=on(s);if(this.sessions.has(l))throw Object.assign(new Error("RATE_LIMITED: code space exhausted"),{code:"RATE_LIMITED"});let f=String(r??"agent").slice(0,64)||"agent",d=(Array.isArray(n)?n:[]).map(String).slice(0,8),u={code:l,deviceId:t,clientName:f,scopes:d,createdAt:i,expiresAt:i+6e5,approved:!1};return this.sessions.set(l,u),this.lastRequestAt.set(t,i),u}approvePairing(t,r,n=Date.now()){let i=this.sessions.get(t);if(!i||i.deviceId!==r||i.expiresAt<=n)return null;if(i.approved&&i.token){let o=this.tokens.get(i.token);if(o&&o.expiresAt>n)return i.token}let s=(0,Ke.randomBytes)(24).toString("hex");return i.approved=!0,i.token=s,this.tokens.set(s,{token:s,deviceId:i.deviceId,clientName:i.clientName,scopes:i.scopes,createdAt:n,expiresAt:n+7776e6}),this.persist(),s}claimPairing(t,r=Date.now()){let n=this.sessions.get(t);return!n||n.expiresAt<=r?{status:"expired"}:n.approved&&n.token?{status:"approved",token:n.token}:{status:"pending"}}verifyToken(t,r=Date.now()){let n=this.tokens.get(t);return n?n.expiresAt<=r?(this.tokens.delete(t),this.persist(),null):n:null}revokeToken(t){let r=this.tokens.delete(t);return r&&(this.persist(),this.revoked(t)),r}revokeDevice(t){let r=0;for(let[n,i]of this.tokens)i.deviceId===t&&(this.tokens.delete(n),this.revoked(n),r++);return r>0&&this.persist(),r}pendingForDevice(t,r=Date.now()){return this.scrub(r),[...this.sessions.values()].filter(n=>n.deviceId===t&&!n.approved&&n.expiresAt>r)}scrub(t){for(let[r,n]of this.sessions)n.expiresAt<=t&&this.sessions.delete(r)}};var Ye=class{devices=new Map;pending=new Map;registerDevice(t,r){let n=this.devices.get(t)??null;return this.devices.set(t,r),n&&n!==r?n:null}unregisterDevice(t,r){(!r||this.devices.get(t)===r)&&(this.devices.delete(t),this.failPendingForDevice(t,new Error(`DISCONNECTED: device ${t} offline`)))}failPendingForDevice(t,r){let n=0;for(let[i,s]of this.pending){if(s.deviceId!==t)continue;this.pending.delete(i),clearTimeout(s.timer);let o=r??new Error(`DISCONNECTED: device ${t} offline`);o.code??="DISCONNECTED",s.reject(o),n++}return n}isCurrentDevice(t,r){return this.devices.get(t)===r}isDeviceOnline(t){return this.devices.has(t)}onlineDevices(){return[...this.devices.keys()]}routeToDevice(t,r,n,i=13e4,s){let o=this.devices.get(t);if(!o)return Promise.reject(Object.assign(new Error(`DISCONNECTED: device ${t} offline`),{code:"DISCONNECTED"}));let a=nn(),l={id:a,kind:"request",method:r,params:n,agentName:s?.agentName};return new Promise((c,f)=>{let d=setTimeout(()=>{this.pending.delete(a),f(Object.assign(new Error(`TIMEOUT waiting for device ${t}`),{code:"TIMEOUT"}))},i);d.unref?.(),this.pending.set(a,{deviceId:t,resolve:c,reject:f,timer:d});try{o(JSON.stringify(l))}catch(u){this.pending.delete(a),clearTimeout(d),f(u instanceof Error?u:new Error(String(u)))}})}settleResponse(t,r){let n=this.pending.get(t.id);return!n||r!==void 0&&n.deviceId!==r?!1:(this.pending.delete(t.id),clearTimeout(n.timer),t.error?n.reject(Object.assign(new Error(`${t.error.code}: ${t.error.message}`),{code:t.error.code})):n.resolve(t.result),!0)}pendingCount(){return this.pending.size}};fe();fe();var Ls="2024-11-05";function Ds(e){let t=new URL(e.url??"/","http://localhost");return e.method==="POST"&&t.pathname==="/mcp"}async function ln(e,t,r){if(!Ds(e))return!1;let n=r.pairings.verifyToken(Ie(e.headers.authorization)??"");if(!n)return P(t,e,null,{error:{code:-32001,message:"Unauthorized: invalid or missing pairing token"}},401);let i;try{i=await le(e)}catch(o){return P(t,e,null,{error:{code:-32600,message:o.message}},o.status??400)}let s=i;if(s.jsonrpc!=="2.0"||typeof s.method!="string")return P(t,e,s.id??null,{error:{code:-32600,message:"Invalid JSON-RPC request"}},400);if(s.method==="initialize")return P(t,e,s.id??null,{result:{protocolVersion:Ls,capabilities:{tools:{}},serverInfo:{name:"babtab-relay",version:"0.1.1"}}});if(s.method.startsWith("notifications/"))return t.writeHead(202).end(),!0;if(s.method==="tools/list")return P(t,e,s.id??null,{result:{tools:ct.map(o=>({name:o.name,description:o.description,inputSchema:o.inputSchema}))}});if(s.method==="tools/call"){let o=String(s.params?.name??""),a=s.params?.arguments??{};if(!L(a))return P(t,e,s.id??null,{result:Ze("Tool arguments must be an object")});let l=Pe(o);if(!l)return P(t,e,s.id??null,{result:Ze(`Unknown tool: ${o}`)});if(!ce(n,l.scope))return P(t,e,s.id??null,{result:Ze(`Token lacks scope ${l.scope} for ${o}`)});try{let c=await r.registry.routeToDevice(n.deviceId,o,a,13e4,{agentName:n.clientName}),f=[];if(o==="browser_screenshot"&&L(c)&&typeof c.dataUrl=="string"){let h=/^data:(image\/(?:jpeg|png|webp));base64,([A-Za-z0-9+/=]+)$/.exec(c.dataUrl);h&&f.push({type:"image",mimeType:h[1],data:h[2]})}let d=It(c),u=JSON.stringify(d)??"null";return f.push({type:"text",text:u.length<=64e3?u:JSON.stringify({truncated:!0,originalLength:u.length,preview:u.slice(0,3e4)})}),P(t,e,s.id??null,{result:{content:f,...L(c)&&c.ok===!1?{isError:!0}:{}}})}catch(c){let f=c;return P(t,e,s.id??null,{result:Ze(`${f.code??"DISCONNECTED"}: ${f.message}`,!0)})}}return P(t,e,s.id??null,{error:{code:-32601,message:`Method not found: ${s.method}`}},404)}function Ze(e,t=!1){return{content:[{type:"text",text:e}],isError:!0,_meta:{retryable:t}}}function P(e,t,r,n,i=200){let s=JSON.stringify({jsonrpc:"2.0",id:r,...n});return String(t.headers.accept??"application/json").includes("text/event-stream")?(e.writeHead(i,{"content-type":"text/event-stream","cache-control":"no-cache","access-control-allow-origin":"*"}),e.end(`event: message
72
- data: ${s}
73
-
74
- `),!0):(e.writeHead(i,{"content-type":"application/json","access-control-allow-origin":"*"}),e.end(s),!0)}function It(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(It);let t={};for(let[r,n]of Object.entries(e)){if((r==="dataUrl"||r==="dataURL")&&typeof n=="string"&&n.length>8e3){t[r]=`[truncated ${r}: ${n.length} chars, image data omitted from text]`,t[`${r}Truncated`]=!0,t[`${r}Length`]=n.length;continue}t[r]=It(n)}return t}function fn(e={}){let t=new Je({persistPath:e.tokenFile??process.env.BABTAB_TOKEN_FILE??"./data/relay-tokens.json"}),r=new Ye,n,i=!1,s=new Map,o=new Map,a=(0,cn.createServer)((u,h)=>{if(i){h.writeHead(503).end();return}Ms(u,h,n).catch(g=>{h.headersSent||h.writeHead(g.status??500,{"content-type":"application/json"}),h.end(JSON.stringify({error:g.status?g.message:"Internal server error"}))})}),l=new Pt.default({server:a,maxPayload:8*1024*1024});l.on("connection",(u,h)=>{if(u.on("error",()=>u.terminate()),i){u.close(1001,"relay shutting down");return}let g=new URL(h.url??"/","http://localhost");if(g.pathname==="/device"){let m=g.searchParams.get("deviceId")??"",S=setTimeout(()=>u.close(1008,"device authentication required"),5e3);S.unref(),u.once("close",()=>clearTimeout(S)),u.once("message",E=>{clearTimeout(S);let C;try{C=JSON.parse(String(E))}catch{u.close(1008,"invalid authentication");return}if(!L(C)||C.kind!=="authenticate"||!Us(m,C.token)){u.close(1008,"invalid device credential");return}let q=s.get(m);s.set(m,u),$s(u,m,t,r),q?.close(1008,"device reconnected"),u.once("close",()=>{s.get(m)===u&&s.delete(m)}),u.send(JSON.stringify({kind:"authenticated"}))})}else if(g.pathname==="/client"){let m=g.searchParams.get("token")??"";o.set(u,m),u.once("close",()=>o.delete(u)),Bs(u,m,t,r)}else u.close(1008,"unknown path")});let c=setInterval(()=>{for(let u of l.clients){let h=o.get(u);if(h&&!t.verifyToken(h)){u.close(1008,"token expired or revoked");continue}if(u.isAlive===!1){u.terminate();continue}u.isAlive=!1,u.ping()}},2e4);c.unref?.(),l.on("connection",u=>{u.isAlive=!0,u.on("pong",()=>{u.isAlive=!0})});let f=e.port??0;t.onRevoke(u=>{for(let[h,g]of o)g===u&&h.close(1008,"token revoked")}),a.listen(f,e.host??"127.0.0.1");let d;return n={server:a,pairings:t,registry:r,close:()=>d??=new Promise((u,h)=>{i=!0,clearInterval(c);for(let E of r.onlineDevices())r.failPendingForDevice(E);for(let E of l.clients)E.close(1001,"relay shutting down");let g=setTimeout(()=>{for(let E of l.clients)E.terminate();a.closeAllConnections()},1e3),m=new Promise((E,C)=>a.close(q=>q?C(q):E())),S=new Promise(E=>l.close(()=>E()));Promise.all([m,S]).then(()=>{clearTimeout(g),u()},E=>{clearTimeout(g),h(E)})})},n}async function Ms(e,t,r){let n=new URL(e.url??"/","http://localhost");if(e.method==="OPTIONS"){t.writeHead(204,{"access-control-allow-origin":"*","access-control-allow-methods":"GET, POST, OPTIONS","access-control-allow-headers":"content-type, authorization"}),t.end();return}let i=(s,o)=>{t.writeHead(s,{"content-type":"application/json","access-control-allow-origin":"*"}),t.end(JSON.stringify(o))};if(e.method==="GET"&&n.pathname==="/health"){i(200,{ok:!0,devices:r.registry.onlineDevices().length});return}if(e.method==="POST"&&n.pathname==="/pairing/request"){let s=await le(e),o=String(s.deviceId??"").slice(0,128);if(!o){i(400,{error:"deviceId required"});return}let a=Array.isArray(s.scopes)?s.scopes.map(String).slice(0,8):["browser:read","browser:act"];try{let l=r.pairings.requestPairing(o,String(s.clientName??"agent"),a);i(200,{code:l.code,expiresAt:l.expiresAt,deviceOnline:r.registry.isDeviceOnline(o)})}catch(l){if(l.code==="RATE_LIMITED"){i(429,{error:l.message});return}throw l}return}if(e.method==="POST"&&n.pathname==="/pairing/claim"){let s=await le(e);i(200,r.pairings.claimPairing(String(s.code??"")));return}if(e.method==="POST"&&n.pathname==="/pairing/revoke"){let{extractBearer:s}=await Promise.resolve().then(()=>(fe(),Qt)),o=s(e.headers.authorization)??"",a=o?r.pairings.revokeToken(o):!1;i(200,{ok:a});return}await ln(e,t,r)||i(404,{error:"not found"})}function $s(e,t,r,n){if(!t){e.close(1008,"deviceId required");return}let i=o=>{e.readyState===e.OPEN&&e.send(o)};n.registerDevice(t,i)&&n.failPendingForDevice(t),e.on("message",o=>{let a;try{a=JSON.parse(String(o))}catch{return}if(!un(a)){e.close(1008,"invalid envelope");return}if(n.isCurrentDevice(t,i)){if(a.kind==="response"){n.settleResponse(a,t);return}if(a.kind!=="pong"&&a.kind==="request"&&a.id){if(a.method==="pairing:pending"){let l=r.pendingForDevice(t).map(c=>({code:c.code,clientName:c.clientName,scopes:c.scopes,createdAt:c.createdAt,expiresAt:c.expiresAt}));e.send(JSON.stringify({id:a.id,kind:"response",result:l}));return}if(a.method==="pairing:approve"){let l=String(a.params?.code??""),c=r.approvePairing(l,t)!=null;e.send(JSON.stringify({id:a.id,kind:"response",result:{ok:c}}));return}if(a.method==="pairing:revoke-device"){let l=r.revokeDevice(t);e.send(JSON.stringify({id:a.id,kind:"response",result:{revoked:l}}));return}e.send(JSON.stringify(ze(a.id,"UNSUPPORTED_OPERATION",`Unknown device method ${a.method}`)))}}}),e.on("close",()=>n.unregisterDevice(t,i))}function Bs(e,t,r,n){let i=r.verifyToken(t);if(!i){e.close(1008,"invalid token");return}e.on("message",s=>{let o;try{o=JSON.parse(String(s))}catch{return}if(!un(o)){e.close(1008,"invalid envelope");return}if(o.kind!=="request"||!o.method)return;let a=r.verifyToken(t);if(!a){e.close(1008,"token expired or revoked");return}let l=Pe(o.method);if(!l||!ce(a,l.scope)){e.send(JSON.stringify(ze(o.id,"USER_REJECTED","Unknown tool or insufficient scope")));return}n.routeToDevice(i.deviceId,o.method,o.params,13e4,{agentName:i.clientName}).then(c=>{e.readyState===e.OPEN&&e.send(JSON.stringify({id:o.id,kind:"response",result:c}))}).catch(c=>{e.readyState===e.OPEN&&e.send(JSON.stringify(ze(o.id,c.code??"DISCONNECTED",c.message)))})})}function Us(e,t){if(!/^dev_v2_[a-f0-9]{64}$/.test(e)||typeof t!="string"||!/^[a-f0-9]{64}$/.test(t))return!1;let r=(0,Xe.createHash)("sha256").update(t).digest();return(0,Xe.timingSafeEqual)(r,Buffer.from(e.slice(7),"hex"))}function un(e){return L(e)?e.kind==="ping"||e.kind==="pong"?!0:typeof e.id!="string"||e.id.length>256?!1:e.kind==="request"?typeof e.method=="string"&&(e.params===void 0||L(e.params)):e.kind==="response"&&(e.error===void 0||L(e.error)&&typeof e.error.code=="string"&&typeof e.error.message=="string"):!1}async function so(){let e=process.argv[2];if(e==="setup"){let{runSetup:t}=await Promise.resolve().then(()=>(Jt(),zt));process.exitCode=await t(process.argv.slice(3))}else if(e==="help"||e==="--help"||e==="-h"){let{setupHelp:t}=await Promise.resolve().then(()=>(Jt(),zt));console.log(`babtab-relay \u2014 local bridge between your AI agent and Chrome
83
+ Configured ${e.label} \u2713`),console.log(e.nextStep),console.log(`Then ask: "${_t}".`),0)}let i=at(),s=ht(e,i);if(!s)return console.error(`Error: no config path for target "${e.id}".`),4;let o,a;if(n.kind==="json"){let l=Mn(n.entry,t,r);({created:o,backedUp:a}=pt({path:s,rootKey:n.rootKey,serverName:ai,entry:l}))}else if(n.kind==="toml-codex")({created:o,backedUp:a}=mt(s,Bn(t,r)));else if(n.kind==="yaml-hermes")({created:o,backedUp:a}=gt(s,Un(t,r)));else return console.error(`Error: unsupported action for target "${e.id}".`),4;return console.log(`
84
+ Wrote ${s} ${o?"(created)":"(updated, babtab entry replaced)"} \u2713`),a&&console.log(`Backup: ${s}.bak`),console.log(e.nextStep),console.log(`Then ask: "${_t}".`),0}var oi,Le,ai,_t,fr=y(()=>{"use strict";oi=require("node:child_process");ti();Kt();or();si();Le=3e3,ai="babtab",_t="Use babtab to observe the current tab"});Ht();async function Oo(){let e=process.argv[2];if(e==="stdio"){let{runStdio:t,parseBridgeArgs:r}=await Promise.resolve().then(()=>(Dn(),In));await t(r(process.argv.slice(3)))}else if(e==="setup"){let{runSetup:t}=await Promise.resolve().then(()=>(fr(),cr));process.exitCode=await t(process.argv.slice(3))}else if(e==="help"||e==="--help"||e==="-h"){let{setupHelp:t}=await Promise.resolve().then(()=>(fr(),cr));console.log(`babtab-relay \u2014 local bridge between your AI agent and Chrome
75
85
 
76
86
  Start the relay:
77
87
  npx -y @babtab/relay (env: PORT=3000 BABTAB_TOKEN_FILE=./data/relay-tokens.json)
78
88
 
79
89
  `+t())}else e!==void 0?(console.error(`Unknown command: ${e}
80
- Run \`npx -y @babtab/relay help\` for usage.`),process.exitCode=1):oo()}so();function oo(){let e=Number(process.env.PORT??3e3),t=fn({port:e,host:process.env.HOST??"127.0.0.1"});t.server.on("listening",()=>{let n=t.server.address(),i=typeof n=="object"&&n?n.port:e;console.log(`[babtab-relay] listening on http://${process.env.HOST??"127.0.0.1"}:${i}`),console.log("[babtab-relay] health: GET /health \xB7 mcp: POST /mcp"),console.log(`[babtab-relay] Side Panel \u2192 Relay URL = ws://127.0.0.1:${i} \u2192 Save & Connect`)});let r=()=>{t.close().then(()=>process.exit(0))};process.on("SIGINT",r),process.on("SIGTERM",r)}
90
+ Run \`npx -y @babtab/relay help\` for usage.`),process.exitCode=1):Ao()}Oo().catch(e=>{console.error(`[babtab] ${e.message}`),process.exitCode=1});function Ao(){let e=Number(process.env.PORT??3e3),t=it({port:e,host:process.env.HOST??"127.0.0.1"});t.server.on("listening",()=>{let n=t.server.address(),i=typeof n=="object"&&n?n.port:e;console.log(`[babtab-relay] listening on http://${process.env.HOST??"127.0.0.1"}:${i}`),console.log("[babtab-relay] health: GET /health \xB7 mcp: POST /mcp"),console.log(`[babtab-relay] Side Panel \u2192 Relay URL = ws://127.0.0.1:${i} \u2192 Save & Connect`)});let r=()=>{t.close().then(()=>process.exit(0))};process.on("SIGINT",r),process.on("SIGTERM",r)}
81
91
  /*! Bundled license information:
82
92
 
83
93
  smol-toml/dist/error.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babtab/relay",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Babtab local relay: auth, pairing, WSS routing, Streamable HTTP MCP for the Babtab Chrome extension. No DOM, no grounding, no page storage.",
5
5
  "type": "module",
6
6
  "bin": {