@babtab/relay 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -1
- package/README.es.md +7 -5
- package/README.hi.md +7 -5
- package/README.ja.md +7 -5
- package/README.ko.md +7 -5
- package/README.md +8 -6
- package/README.pt-BR.md +7 -5
- package/README.zh-TW.md +8 -6
- package/dist/relay.cjs +40 -39
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,50 @@ and [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## [0.3.1] — 2026-10-05
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Docs: link the published Chrome Web Store listing
|
|
14
|
+
(https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
15
|
+
from all 7 READMEs and the privacy page footer; replaced the outdated
|
|
16
|
+
"Load unpacked / pending store publication" steps with store install.
|
|
17
|
+
No code changes — still pairs with extension 0.3.0; no re-pairing needed.
|
|
18
|
+
- Install links and setup commands pin `@babtab/relay@0.3.1`.
|
|
19
|
+
|
|
20
|
+
## [0.3.0] — 2026-10-03
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- Multitab tools: `browser_tabs`, `browser_switch_tab`, `browser_open_tab`,
|
|
25
|
+
`browser_close_tab` (session-scoped; close only touches tabs the session controls).
|
|
26
|
+
- `browser_assert`: structured QA assertions over live elements
|
|
27
|
+
(exists / not_exists / text_contains / text_equals / count / visible /
|
|
28
|
+
value_equals / checked). Never throws — failures return ok:false with actuals.
|
|
29
|
+
- `browser_extract`: schema-first extraction via fields[].
|
|
30
|
+
- Richer target queries: `label`, `placeholder`, and `text` matching plus `nth`
|
|
31
|
+
ordinal selection and `near` proximity hints; documented postcondition
|
|
32
|
+
vocabulary (`element_appeared` / `element_disappeared` are delta checks
|
|
33
|
+
against a pre-dispatch snapshot).
|
|
34
|
+
- Token accounting helpers shared by extension and relay (chars/4 estimator,
|
|
35
|
+
stable JSON sizing for prompt-cache friendliness).
|
|
36
|
+
- One-click install for Hermes Desktop (`hermes://mcp/install` deeplink);
|
|
37
|
+
one-click copy installers for Codex (`codex mcp add` — the desktop app
|
|
38
|
+
shares the CLI config) and Antigravity (mcp_config.json snippet).
|
|
39
|
+
- Protocol unit tests (14) covering the shared extension↔relay contract.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- Install links and setup commands pin `@babtab/relay@0.3.0`.
|
|
44
|
+
**Update the relay and extension together** — 0.3.0 pairs with extension 0.3.0.
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- Audit-index crash on malformed input.
|
|
49
|
+
|
|
50
|
+
## [0.2.0] — 2026-09-30
|
|
51
|
+
|
|
52
|
+
### Automatic local onboarding
|
|
10
53
|
|
|
11
54
|
- MCP-owned `stdio` bridge starts / reuses a local relay, reconnects after owner
|
|
12
55
|
exit, and stores credentials under `~/.babtab/` instead of the working directory.
|
package/README.es.md
CHANGED
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@babtab/relay)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
> **Requiere la extensión Babtab:** [Instalar Babtab desde Chrome Web Store](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
9
|
+
|
|
10
|
+
El **servidor relay local** para la [extensión Babtab de Chrome](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb): conecta tu agente de IA (Cursor / Pi / Claude Code / …) con tu Chrome real.
|
|
9
11
|
|
|
10
12
|
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
13
|
|
|
12
|
-
## Instalación recomendada (0.
|
|
14
|
+
## Instalación recomendada (0.3.1)
|
|
13
15
|
|
|
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**.
|
|
16
|
+
Requiere Node.js 20+. Instala la extensión desde [Chrome Web Store](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb) y pulsa **Add to Cursor** / **Add to VS Code** / **Add to Hermes** (botones de un clic) en Babtab; **Add to Codex** / **Add to Antigravity** copian un fragmento de instalación. 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
17
|
|
|
16
18
|
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
19
|
|
|
@@ -30,9 +32,9 @@ Agente de IA (Cursor / Pi …) ←→ Relay (local :3000) ←→ Extensión de C
|
|
|
30
32
|
|
|
31
33
|
### Paso 1: Instala la extensión de Chrome
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
[Instala Babtab desde Chrome Web Store](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb).
|
|
34
36
|
|
|
35
|
-
>
|
|
37
|
+
> El modo de desarrollador / Cargar descomprimida es solo para desarrollo local.
|
|
36
38
|
|
|
37
39
|
### Paso 2: Inicia el relay (elige una, mismo resultado)
|
|
38
40
|
|
package/README.hi.md
CHANGED
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@babtab/relay)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
Babtab
|
|
8
|
+
> **Babtab एक्सटेंशन आवश्यक है:** [Chrome Web Store से Babtab इंस्टॉल करें](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
9
|
+
|
|
10
|
+
[Babtab Chrome एक्सटेंशन](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb) के लिए **लोकल relay सर्वर**: यह आपके AI एजेंट (Cursor / Pi / Claude Code / …) को आपके असली Chrome से जोड़ता है।
|
|
9
11
|
|
|
10
12
|
MV3 एक्सटेंशन स्वयं किसी पोर्ट पर listen नहीं कर सकते, इसलिए यह छोटा प्रोग्राम bridge का काम करता है। यह `localhost` पर चलता है, इसलिए ट्रैफ़िक आपकी मशीन से बाहर कभी नहीं जाता। Relay अनुरोध और परिणाम सिर्फ़ मेमोरी में आगे बढ़ाता है (पेज अवलोकन और स्क्रीनशॉट सहित); यह पेज सामग्री को store नहीं करता।
|
|
11
13
|
|
|
12
|
-
## अनुशंसित सेटअप (0.
|
|
14
|
+
## अनुशंसित सेटअप (0.3.1)
|
|
13
15
|
|
|
14
|
-
Node.js 20+ आवश्यक है। Chrome Web Store से एक्सटेंशन इंस्टॉल करें और Babtab में **Add to Cursor**
|
|
16
|
+
Node.js 20+ आवश्यक है। [Chrome Web Store से एक्सटेंशन इंस्टॉल करें](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb) और Babtab में **Add to Cursor** / **Add to VS Code** / **Add to Hermes** जैसे वन-क्लिक बटन दबाएँ (**Add to Codex** / **Add to Antigravity** इंस्टॉल स्निपेट कॉपी करते हैं)। Cursor में जोड़ने और सक्षम करने की पुष्टि करें, फिर Chrome में लौटकर **Approve** दबाएँ। AI टूल Relay को अपने आप शुरू करता है; टर्मिनल खुला रखने की जरूरत नहीं है। अन्य टूल के लिए **Other AI tools / install with a command** चुनें।
|
|
15
17
|
|
|
16
18
|
बदलने से पहले पुराना मैन्युअल Relay बंद करें। [नवीनतम गाइड](README.md) देखें। नीचे दिए गए निर्देश मैन्युअल HTTP कनेक्शन के लिए हैं।
|
|
17
19
|
|
|
@@ -30,9 +32,9 @@ AI एजेंट (Cursor / Pi …) ←→ Relay (लोकल :3000) ←→ Ch
|
|
|
30
32
|
|
|
31
33
|
### चरण 1: Chrome एक्सटेंशन इंस्टॉल करें
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
[Chrome Web Store से Babtab इंस्टॉल करें](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)।
|
|
34
36
|
|
|
35
|
-
>
|
|
37
|
+
> Developer mode / Load unpacked सिर्फ़ स्थानीय विकास के लिए है।
|
|
36
38
|
|
|
37
39
|
### चरण 2: Relay शुरू करें (कोई एक चुनें, परिणाम समान)
|
|
38
40
|
|
package/README.ja.md
CHANGED
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@babtab/relay)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
Babtab Chrome
|
|
8
|
+
> **Babtab 拡張機能が必要です:**[Chrome ウェブストアから Babtab をインストール](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
9
|
+
|
|
10
|
+
[Babtab Chrome 拡張機能](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)のための**ローカル中継サーバー**です。あなたの AI エージェント(Cursor / Pi / Claude Code / …)を、実際の Chrome につなぎます。
|
|
9
11
|
|
|
10
12
|
MV3 の拡張機能は自分でポートを listen できないため、この小さなプログラムが橋渡しをします。`localhost` 上で動作するので、通信が PC の外に出ることはありません。Relay はリクエストと結果をメモリ上でのみ転送します(ページ観測やスクリーンショットを含みます)。ページ内容を保存することはありません。
|
|
11
13
|
|
|
12
|
-
## 推奨セットアップ(0.
|
|
14
|
+
## 推奨セットアップ(0.3.1)
|
|
13
15
|
|
|
14
|
-
Node.js 20+ が必要です。Chrome
|
|
16
|
+
Node.js 20+ が必要です。[Chrome ウェブストアから拡張機能をインストール](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)し、Babtab の **Add to Cursor**/**Add to VS Code**/**Add to Hermes** などのワンクリックボタンを押します(**Add to Codex**/**Add to Antigravity** はインストール用スニペットのコピーです)。Cursor で追加・有効化し、Chrome に戻って **Approve** を押してください。Relay は AI ツールが自動起動するため、ターミナルを開いたままにする必要はありません。ほかの AI ツールは **Other AI tools / install with a command** から設定できます。
|
|
15
17
|
|
|
16
18
|
旧版の手動 Relay を終了してから切り替えてください。詳細は [最新ガイド](README.md) を参照してください。以下は手動 HTTP 接続用の手順です。
|
|
17
19
|
|
|
@@ -30,9 +32,9 @@ AI エージェント(Cursor / Pi …) ←→ Relay(ローカル :3000)
|
|
|
30
32
|
|
|
31
33
|
### ステップ 1:Chrome 拡張機能をインストール
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
[Chrome ウェブストアから Babtab をインストール](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)してください。
|
|
34
36
|
|
|
35
|
-
>
|
|
37
|
+
> デベロッパーモード / パッケージ化されていない拡張機能の読み込みはローカル開発用です。
|
|
36
38
|
|
|
37
39
|
### ステップ 2:Relay を起動する(どちらか一方、結果は同じ)
|
|
38
40
|
|
package/README.ko.md
CHANGED
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@babtab/relay)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
Babtab
|
|
8
|
+
> **Babtab 확장 프로그램이 필요합니다:** [Chrome 웹 스토어에서 Babtab 설치](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
9
|
+
|
|
10
|
+
[Babtab Chrome 확장 프로그램](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)을 위한 **로컬 중계 서버**입니다. AI 에이전트(Cursor / Pi / Claude Code / …)를 실제 Chrome에 연결해 줍니다.
|
|
9
11
|
|
|
10
12
|
MV3 확장 프로그램은 스스로 포트를 listen 할 수 없기 때문에, 이 작은 프로그램이 다리 역할을 합니다. `localhost`에서 동작하므로 트래픽이 컴퓨터 밖으로 나가지 않습니다. Relay는 요청과 결과를 메모리에서만 전달합니다(페이지 관찰 및 스크린샷 포함). 페이지 내용을 저장하지 않습니다.
|
|
11
13
|
|
|
12
|
-
## 권장 설치 방법 (0.
|
|
14
|
+
## 권장 설치 방법 (0.3.1)
|
|
13
15
|
|
|
14
|
-
Node.js 20+가 필요합니다. Chrome 웹 스토어에서 확장 프로그램을
|
|
16
|
+
Node.js 20+가 필요합니다. [Chrome 웹 스토어에서 확장 프로그램을 설치](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)하고 Babtab의 **Add to Cursor** / **Add to VS Code** / **Add to Hermes** 등 원클릭 버튼을 누르세요(**Add to Codex** / **Add to Antigravity**는 설치 스니펫 복사입니다). Cursor에서 추가 / 활성화한 뒤 Chrome으로 돌아와 **Approve**를 누르세요. AI 도구가 Relay를 자동으로 실행하므로 터미널을 계속 열어 둘 필요가 없습니다. 다른 도구는 **Other AI tools / install with a command**에서 설정할 수 있습니다.
|
|
15
17
|
|
|
16
18
|
전환 전에 기존 수동 Relay를 종료하세요. 자세한 내용은 [최신 가이드](README.md)를 참조하세요. 아래는 수동 HTTP 연결용 절차입니다.
|
|
17
19
|
|
|
@@ -30,9 +32,9 @@ AI 에이전트(Cursor / Pi …) ←→ Relay(로컬 :3000) ←→ Chrome 확장
|
|
|
30
32
|
|
|
31
33
|
### 1단계: Chrome 확장 프로그램 설치
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
[Chrome 웹 스토어에서 Babtab을 설치](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)하세요.
|
|
34
36
|
|
|
35
|
-
>
|
|
37
|
+
> 개발자 모드 / 압축해제된 확장 프로그램 로드는 로컬 개발용입니다.
|
|
36
38
|
|
|
37
39
|
### 2단계: Relay 실행 (둘 중 하나, 결과는 동일)
|
|
38
40
|
|
package/README.md
CHANGED
|
@@ -5,16 +5,18 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@babtab/relay)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
> **Requires the Babtab extension:** [Install Babtab from the Chrome Web Store](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
9
|
+
|
|
10
|
+
The **local relay server** for the [Babtab Chrome extension](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb): it connects your AI agent (Cursor / Pi / Claude Code / …) to your real Chrome.
|
|
9
11
|
|
|
10
12
|
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
13
|
|
|
12
|
-
## Quick start (0.
|
|
14
|
+
## Quick start (0.3.1)
|
|
13
15
|
|
|
14
|
-
Requires Node.js 20+ and the matching Babtab extension. Install the extension from the **Chrome Web Store
|
|
16
|
+
Requires Node.js 20+ and the matching [Babtab extension](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb). Install the extension from the [**Chrome Web Store**](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb); Developer mode is for local development only.
|
|
15
17
|
|
|
16
|
-
1. Open Babtab in Chrome and click **Add to Cursor
|
|
17
|
-
2. Confirm Add / Enable in
|
|
18
|
+
1. Open Babtab in Chrome and click **Add to Cursor** (or **Add to VS Code** / **VS Code Insiders** / **Add to Hermes** — all one-click).
|
|
19
|
+
2. Confirm Add / Enable in your AI tool. It starts the local bridge automatically. **Add to Codex** / **Add to Antigravity** copy a one-step install snippet instead (Codex: paste in a terminal — the desktop app shares the CLI config; Antigravity: paste into mcp_config.json and restart the IDE).
|
|
18
20
|
3. Return to Babtab and **Approve** the first connection.
|
|
19
21
|
4. On a regular website, ask your agent: **Use babtab to observe the current tab**. Approve site access in Babtab if asked.
|
|
20
22
|
|
|
@@ -26,7 +28,7 @@ The first npm download requires internet access. Pairing credentials are stored
|
|
|
26
28
|
Open **Other AI tools / install with a command**, choose your tool and copy its personalized command:
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
|
-
npx -y @babtab/relay@0.
|
|
31
|
+
npx -y @babtab/relay@0.3.1 setup --target windsurf --port 3000 --device <device-id-from-extension>
|
|
30
32
|
```
|
|
31
33
|
|
|
32
34
|
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.
|
package/README.pt-BR.md
CHANGED
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@babtab/relay)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
> **Requer a extensão Babtab:** [Instalar o Babtab pela Chrome Web Store](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
9
|
+
|
|
10
|
+
O **servidor relay local** para a [extensão Babtab do Chrome](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb): conecta seu agente de IA (Cursor / Pi / Claude Code / …) ao seu Chrome de verdade.
|
|
9
11
|
|
|
10
12
|
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
13
|
|
|
12
|
-
## Instalação recomendada (0.
|
|
14
|
+
## Instalação recomendada (0.3.1)
|
|
13
15
|
|
|
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**.
|
|
16
|
+
Requer Node.js 20+. Instale a extensão pela [Chrome Web Store](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb) e clique em **Add to Cursor** / **Add to VS Code** / **Add to Hermes** (botões de um clique) no Babtab; **Add to Codex** / **Add to Antigravity** copiam um trecho de instalação. 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
17
|
|
|
16
18
|
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
19
|
|
|
@@ -30,9 +32,9 @@ Agente de IA (Cursor / Pi …) ←→ Relay (local :3000) ←→ Extensão do Ch
|
|
|
30
32
|
|
|
31
33
|
### Passo 1: Instale a extensão do Chrome
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
[Instale o Babtab pela Chrome Web Store](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb).
|
|
34
36
|
|
|
35
|
-
>
|
|
37
|
+
> O modo do desenvolvedor / Carregar sem compactação é apenas para desenvolvimento local.
|
|
36
38
|
|
|
37
39
|
### Passo 2: Inicie o relay (escolha um, mesmo resultado)
|
|
38
40
|
|
package/README.zh-TW.md
CHANGED
|
@@ -5,16 +5,18 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@babtab/relay)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
> **需要先安裝 Babtab 外掛:**[從 Chrome 線上應用程式商店安裝 Babtab](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)
|
|
9
|
+
|
|
10
|
+
[Babtab Chrome 擴充功能](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)的**本機中轉伺服器**:把你的 AI Agent(Cursor / Pi / Claude Code / …)接到你真正的 Chrome 上。
|
|
9
11
|
|
|
10
12
|
MV3 擴充功能自己不能 listen port,所以需要這支小程式當橋樑。跑在 `localhost`,流量不出你的電腦;Relay 會在記憶體中轉發請求與結果(包含頁面觀察及截圖),不會儲存頁面內容。
|
|
11
13
|
|
|
12
|
-
## 使用者快速開始(0.
|
|
14
|
+
## 使用者快速開始(0.3.1)
|
|
13
15
|
|
|
14
|
-
需要 Node.js 20+ 與對應新版外掛。一般使用者從 **Chrome Web Store 安裝 Babtab**;開發者模式只供本機測試。
|
|
16
|
+
需要 Node.js 20+ 與對應新版外掛。一般使用者從 **[Chrome Web Store 安裝 Babtab](https://chromewebstore.google.com/detail/babtab/pnapkckkiphkbciihimdkhofdabnmjhb)**;開發者模式只供本機測試。
|
|
15
17
|
|
|
16
|
-
1. 開啟 Babtab Side Panel,按 **Add to Cursor
|
|
17
|
-
2. 在
|
|
18
|
+
1. 開啟 Babtab Side Panel,按 **Add to Cursor**(或 **Add to VS Code**/**VS Code Insiders**/**Add to Hermes**,都是一鍵安裝)。
|
|
19
|
+
2. 在 AI 工具確認加入/啟用 Babtab;它會自動啟動本機橋接程式。**Add to Codex**/**Add to Antigravity** 則是一鍵複製安裝片段(Codex:貼上終端機執行,桌機版共用設定;Antigravity:貼進 mcp_config.json 後重啟 IDE)。
|
|
18
20
|
3. 回到外掛,確認工具名稱後按 **Approve**。
|
|
19
21
|
4. 在一般網站分頁,對 AI 說 **Use babtab to observe the current tab**;需要網站授權時在外掛批准。
|
|
20
22
|
|
|
@@ -26,7 +28,7 @@ MV3 擴充功能自己不能 listen port,所以需要這支小程式當橋樑
|
|
|
26
28
|
開啟 **Other AI tools / install with a command**,選工具並複製專屬指令:
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
|
-
npx -y @babtab/relay@0.
|
|
31
|
+
npx -y @babtab/relay@0.3.1 setup --target windsurf --port 3000 --device <外掛提供的deviceId>
|
|
30
32
|
```
|
|
31
33
|
|
|
32
34
|
只需執行一次。指令保留其他 server、備份舊設定,寫入由 AI 工具自動啟動的 MCP 設定。
|
package/dist/relay.cjs
CHANGED
|
@@ -1,93 +1,94 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
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
|
|
2
|
+
"use strict";var ui=Object.create;var wt=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),pr=(e,t)=>{for(var r in t)wt(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&&wt(e,i,{get:()=>t[i],enumerable:!(n=hi(t,i))||n.enumerable});return e};var j=(e,t,r)=>(r=e!=null?ui(mi(e)):{},_i(t||!e||!e.__esModule?wt(r,"default",{value:e,enumerable:!0}):r,e));function x(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function de(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 Le(e){return ue.find(t=>t.name===e)}var F,yi,De,bi,ue,Me=y(()=>{"use strict";F={type:"object",description:"Semantic target: durable ref (@Hxxxx) or role/name/region query. On AMBIGUOUS_TARGET, next call MUST use a ranked candidate ref or add region/nth/near.",properties:{ref:{type:"string",description:"Durable handle from find/observe (@Hxxxx)."},role:{type:"string"},name:{type:"string",description:"Exact accessible name."},nameContains:{type:"string"},label:{type:"string"},region:{type:"string",description:"Semantic region id (main, dialog, navigation, \u2026)."},nth:{type:"number",description:"1-based ordinal among ranked matches (disambiguates duplicates)."},near:{type:"string",description:"Soft proximity hint (nearby heading text or region id)."}}},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","boolean"],description:"Boolean for checked; string for URL/value conditions."},query:F,regionId:{type:"string"}},required:["type"],additionalProperties:!0},De={type:"array",description:"Strongly recommended for click/navigate. Without expect, success is dispatch_only (not business success). Prefer url_matches / element_appeared / value_equals.",items:yi},bi={type:"object",description:"Single guarded action contract.",properties:{action:{type:"string",enum:["click","fill","select","press","scroll","navigate","back","forward","hover","open_tab","close_tab"]},target:F,value:{type:"string"},key:{type:"string"},url:{type:"string"},tab:{type:["number","string"],description:"P2 multi-tab: explicit tab id or a plan-local ref bound by tabRef. Omit to run on the plan's current tab."},tabRef:{type:"string",description:"P2 multi-tab: bind this step's tab to a ref name for later steps."},active:{type:"boolean",description:"open_tab: focus the new tab (default true)."},expect:De,timeoutMs:{type:"number"}},required:["action"],additionalProperties:!0},ue=[{name:"browser_observe",description:"Pull-mode digest: default to page_digest (regions+counts ~100 tokens). Drill via browser_find or region_digest. level=full requires explicit need \u2014 prefer find. Returns recommendedNext + overBudget when useful.",inputSchema:{type:"object",properties:{level:{type:"string",enum:["page_digest","region_digest","interactive","full"],description:"Default page_digest. Avoid full."},regionId:{type:"string"},includeRecentDiff:{type:"boolean"},limit:{type:"number",description:"Cap for interactive[] (default 30, max 120)."}}},scope:"browser:read"},{name:"browser_find",description:"Pull-mode lookup: matching elements as durable refs. Prefer over observe level=full. Use nth/near/region when labels collide. On AMBIGUOUS, ranked candidates include score+region \u2014 next act MUST use ref.",inputSchema:{type:"object",properties:{role:{type:"string"},name:{type:"string"},nameContains:{type:"string"},region:{type:"string"},nth:{type:"number",description:"1-based ordinal among ranked matches."},near:{type:"string",description:"Nearby heading / region hint."}}},scope:"browser:read"},{name:"browser_click",description:"Click a semantic target (guarded). Strongly recommend expect (url_matches / element_appeared; element_* are delta checks vs pre-click state). Without expect, result.verifiedMode=dispatch_only.",inputSchema:{type:"object",properties:{target:F,expect:De},required:["target"]},scope:"browser:act"},{name:"browser_fill",description:"Fill a field and verify the value. Prefer expect value_equals when possible.",inputSchema:{type:"object",properties:{target:F,value:{type:"string"},expect:De},required:["target","value"]},scope:"browser:act"},{name:"browser_select",description:"Choose a select option.",inputSchema:{type:"object",properties:{target:F,value:{type:"string"}},required:["target","value"]},scope:"browser:act"},{name:"browser_press",description:"Press a key on a target or the focused element. Prefer for canvas editors (Docs/Sheets) over clicking tiles.",inputSchema:{type:"object",properties:{target:F,key:{type:"string"}}},scope:"browser:act"},{name:"browser_scroll",description:"Scroll a target into view or scroll the page. Use before re-find on virtualized lists.",inputSchema:{type:"object",properties:{target:F,direction:{type:"string"}}},scope:"browser:act"},{name:"browser_navigate",description:"Navigate the controlled tab (site grant required). Strongly recommend expect url_matches (URI-decoded).",inputSchema:{type:"object",properties:{url:{type:"string"},expect:De},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_open_tab",description:"Open a new tab (http(s) only) and drive it. Refuses javascript:/file: URLs.",inputSchema:{type:"object",properties:{url:{type:"string"},active:{type:"boolean",description:"Focus the new tab (default true)."}},required:["url"]},scope:"browser:act"},{name:"browser_close_tab",description:"Close a tab this session controls (default: current). Refuses the last tab; refuses tabs not leased/controlled by this session.",inputSchema:{type:"object",properties:{tabId:{type:"number"}}},scope:"browser:act"},{name:"browser_assert",description:"QA assertion: structured pass/fail over live elements (exists/not_exists/text_contains/text_equals/count/visible/value_equals/checked). Never throws \u2014 failures return ok:false with actuals.",inputSchema:{type:"object",properties:{kind:{type:"string",enum:["exists","not_exists","text_contains","text_equals","count","visible","value_equals","checked"]},target:F,expected:{type:["string","number","boolean"],description:"Required for text_*/value_equals/count; optional boolean (default true) for visible/checked; ignored otherwise."}},required:["kind","target"]},scope:"browser:read"},{name:"browser_screenshot",description:"Capture the visible tab (rate-limited fallback).",inputSchema:{type:"object",properties:{}},scope:"browser:read"},{name:"browser_extract",description:"Schema-first extract: pass fields[] to get only declared values as data (cheapest). Without fields, returns region text + article paragraphs (nav/header/footer excluded).",inputSchema:{type:"object",properties:{regionId:{type:"string"},maxRows:{type:"number"},fields:{type:"array",description:"Declared fields (max 20): [{name, role?, nameContains?, label?, region?, ref?, attr?: text|value|name}].",items:{type:"object",properties:{name:{type:"string"},role:{type:"string"},nameContains:{type:"string"},label:{type:"string"},region:{type:"string"},ref:{type:"string"},attr:{type:"string",enum:["text","value","name"]}},required:["name"]}}}},scope:"browser:read"},{name:"browser_wait",description:"Wait for a condition or timeout. urlMatches is URI-decoded (non-ASCII paths ok).",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. REQUIRED when \u22653 consecutive fill/click/select steps (forms, search\u2192result, login). Prefer over step-by-step tool spam.",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"}]});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 vi(e,t){return e.includes("*")||e.includes(t)}function $e(e,t){return e?vi(e.scopes,t):!1}var Be=y(()=>{"use strict"});var M=T((Lo,_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 pe=T((Mo,Ue)=>{"use strict";var{EMPTY_BUFFER:Si}=M(),Et=Buffer[Symbol.species];function wi(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 Et(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 Et(e):ArrayBuffer.isView(e)?t=new Et(e.buffer,e.byteOffset,e.byteLength):(t=Buffer.from(e),xt.readOnly=!1),t}Ue.exports={concat:wi,mask:yr,toArrayBuffer:Ei,toBuffer:xt,unmask:br};if(!process.env.WS_NO_BUFFER_UTIL)try{let e=require("bufferutil");Ue.exports.mask=function(t,r,n,i,s){s<48?yr(t,r,n,i,s):e.mask(t,r,n,i,s)},Ue.exports.unmask=function(t,r){t.length<32?br(t,r):e.unmask(t,r)}}catch{}});var wr=T(($o,Sr)=>{"use strict";var vr=Symbol("kDone"),Tt=Symbol("kRun"),kt=class{constructor(t){this[vr]=()=>{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[vr])}}};Sr.exports=kt});var ne=T((Bo,kr)=>{"use strict";var me=require("zlib"),Er=pe(),xi=wr(),{kStatusCode:xr}=M(),Ti=Buffer[Symbol.species],ki=Buffer.from([0,0,255,255]),Fe=Symbol("permessage-deflate"),$=Symbol("total-length"),te=Symbol("callback"),W=Symbol("buffers"),re=Symbol("error"),je,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,!je){let r=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;je=new xi(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){je.add(i=>{this._decompress(t,r,(s,o)=>{i(),n(s,o)})})}compress(t,r,n){je.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"?me.Z_DEFAULT_WINDOWBITS:this.params[s];this._inflate=me.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[Fe]=this,this._inflate[$]=0,this._inflate[W]=[],this._inflate.on("error",Oi),this._inflate.on("data",Tr)}this._inflate[te]=n,this._inflate.write(t),r&&this._inflate.write(ki),this._inflate.flush(()=>{let s=this._inflate[re];if(s){this._inflate.close(),this._inflate=null,n(s);return}let o=Er.concat(this._inflate[W],this._inflate[$]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[$]=0,this._inflate[W]=[],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"?me.Z_DEFAULT_WINDOWBITS:this.params[s];this._deflate=me.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[$]=0,this._deflate[W]=[],this._deflate.on("data",Ci)}this._deflate[te]=n,this._deflate.write(t),this._deflate.flush(me.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let s=Er.concat(this._deflate[W],this._deflate[$]);r&&(s=new Ti(s.buffer,s.byteOffset,s.length-4)),this._deflate[te]=null,this._deflate[$]=0,this._deflate[W]=[],r&&this.params[`${i}_no_context_takeover`]&&this._deflate.reset(),n(null,s)})}};kr.exports=Ct;function Ci(e){this[W].push(e),this[$]+=e.length}function Tr(e){if(this[$]+=e.length,this[Fe]._maxPayload<1||this[$]<=this[Fe]._maxPayload){this[W].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 Oi(e){if(this[Fe]._inflate=null,this[re]){this[te](this[re]);return}e[xr]=1007,this[te](e)}});var ie=T((Uo,We)=>{"use strict";var{isUtf8:Cr}=require("buffer"),{hasBlob:Ai}=M(),Pi=[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 Ii(e){return Ai&&typeof e=="object"&&typeof e.arrayBuffer=="function"&&typeof e.type=="string"&&typeof e.stream=="function"&&(e[Symbol.toStringTag]==="Blob"||e[Symbol.toStringTag]==="File")}We.exports={isBlob:Ii,isValidStatusCode:Ni,isValidUTF8:Ot,tokenChars:Pi};if(Cr)We.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");We.exports.isValidUTF8=function(t){return t.length<32?Ot(t):e(t)}}catch{}});var Rt=T((jo,Dr)=>{"use strict";var{Writable:Ri}=require("stream"),Or=ne(),{BINARY_TYPES:Di,EMPTY_BUFFER:Ar,kStatusCode:Li,kWebSocket:Mi}=M(),{concat:At,toArrayBuffer:$i,unmask:Bi}=pe(),{isValidStatusCode:Ui,isValidUTF8:Pr}=ie(),qe=Buffer[Symbol.species],A=0,Nr=1,Ir=2,Rr=3,Pt=4,Nt=5,Ge=6,It=class extends Ri{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[Mi]=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 qe(n.buffer,n.byteOffset+t,n.length-t),new qe(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 qe(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 Nr:this.getPayloadLength16(t);break;case Ir:this.getPayloadLength64(t);break;case Rr:this.getMask();break;case Pt:this.getData(t);break;case Nt:case Ge: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=Nr: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=Rr:this._state=Pt}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=Pt}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]&&Bi(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=Nt,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=Ge,setImmediate(()=>{this.emit("message",i,!0),this._state=A,this.startLoop(t)}))}else{let i=At(n,r);if(!this._skipUTF8Validation&&!Pr(i)){let s=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");t(s);return}this._state===Nt||this._allowSynchronousEvents?(this.emit("message",i,!1),this._state=A):(this._state=Ge,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(!Ui(n)){let s=this.createError(RangeError,`invalid status code ${n}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");r(s);return}let i=new qe(t.buffer,t.byteOffset+2,t.length-2);if(!this._skipUTF8Validation&&!Pr(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=Ge,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}};Dr.exports=It});var Mt=T((Wo,$r)=>{"use strict";var{Duplex:Fo}=require("stream"),{randomFillSync:ji}=require("crypto"),{types:{isUint8Array:Fi}}=require("util"),Lr=ne(),{EMPTY_BUFFER:Wi,kWebSocket:qi,NOOP:Gi}=M(),{isBlob:se,isValidStatusCode:Vi}=ie(),{mask:Mr,toBuffer:H}=pe(),P=Symbol("kByteLength"),Hi=Buffer.alloc(4),Ve=8*1024,z,oe=Ve,N=0,zi=1,Ji=2,Dt=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=Gi,this[qi]=void 0}static frame(t,r){let n,i=!1,s=2,o=!1;r.mask&&(n=r.maskBuffer||Hi,r.generateMask?r.generateMask(n):(oe===Ve&&(z===void 0&&(z=Buffer.alloc(Ve)),ji(z,0,Ve),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[P]!==void 0?a=r[P]:(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?(Mr(t,n,c,s,a),[c]):(Mr(t,n,t,0,a),[c,t])):[c,t]}close(t,r,n,i){let s;if(t===void 0)s=Wi;else{if(typeof t!="number"||!Vi(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(Fi(r))s.set(r,2);else throw new TypeError("Second argument must be a string or a Uint8Array")}}let o={[P]: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):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={[P]:i,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:9,readOnly:s,rsv1:!1};se(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):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={[P]:i,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:10,readOnly:s,rsv1:!1};se(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[Lr.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={[P]:a,fin:r.fin,generateMask:this._generateMask,mask:r.mask,maskBuffer:this._maskBuffer,opcode:s,readOnly:l,rsv1:o};se(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[P],this._state=Ji,t.arrayBuffer().then(s=>{if(this._socket.destroyed){let a=new Error("The socket was closed while the blob was being read");process.nextTick(Lt,this,a,i);return}this._bufferedBytes-=n[P];let o=H(s);r?this.dispatch(o,r,n,i):(this._state=N,this.sendFrame(e.frame(o,n),i),this.dequeue())}).catch(s=>{process.nextTick(Ki,this,s,i)})}dispatch(t,r,n,i){if(!r){this.sendFrame(e.frame(t,n),i);return}let s=this._extensions[Lr.extensionName];this._bufferedBytes+=n[P],this._state=zi,s.compress(t,n.fin,(o,a)=>{if(this._socket.destroyed){let l=new Error("The socket was closed while data was being compressed");Lt(this,l,i);return}this._bufferedBytes-=n[P],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][P],Reflect.apply(t[0],this,t.slice(1))}}enqueue(t){this._bufferedBytes+=t[3][P],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)}};$r.exports=Dt;function Lt(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 Ki(e,t,r){Lt(e,t,r),e.onerror(t)}});var Hr=T((qo,Vr)=>{"use strict";var{kForOnEventAttribute:ge,kListener:$t}=M(),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 _e=class extends B{constructor(t,r={}){super(t),this[Ur]=r.data===void 0?null:r.data}get data(){return this[Ur]}};Object.defineProperty(_e.prototype,"data",{enumerable:!0});var Yi={addEventListener(e,t,r={}){for(let i of this.listeners(e))if(!r[ge]&&i[$t]===t&&!i[ge])return;let n;if(e==="message")n=function(s,o){let a=new _e("message",{data:o?s:s.toString()});a[ae]=this,He(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,He(t,this,a)};else if(e==="error")n=function(s){let o=new le("error",{error:s,message:s.message});o[ae]=this,He(t,this,o)};else if(e==="open")n=function(){let s=new B("open");s[ae]=this,He(t,this,s)};else return;n[ge]=!!r[ge],n[$t]=t,r.once?this.once(e,n):this.on(e,n)},removeEventListener(e,t){for(let r of this.listeners(e))if(r[$t]===t&&!r[ge]){this.removeListener(e,r);break}}};Vr.exports={CloseEvent:J,ErrorEvent:le,Event:B,EventTarget:Yi,MessageEvent:_e};function He(e,t,r){typeof e=="object"&&e.handleEvent?e.handleEvent.call(e,r):e.call(t,r)}});var ze=T((Go,zr)=>{"use strict";var{tokenChars:ye}=ie();function L(e,t,r){e[t]===void 0?e[t]=[r]:e[t].push(r)}function Zi(e){let t=Object.create(null),r=Object.create(null),n=!1,i=!1,s=!1,o,a,l=-1,c=-1,d=-1,u=0;for(;u<e.length;u++)if(c=e.charCodeAt(u),o===void 0)if(d===-1&&ye[c]===1)l===-1&&(l=u);else if(u!==0&&(c===32||c===9))d===-1&&l!==-1&&(d=u);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${u}`);d===-1&&(d=u);let h=e.slice(l,d);c===44?(L(t,h,r),r=Object.create(null)):o=h,l=d=-1}else throw new SyntaxError(`Unexpected character at index ${u}`);else if(a===void 0)if(d===-1&&ye[c]===1)l===-1&&(l=u);else if(c===32||c===9)d===-1&&l!==-1&&(d=u);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${u}`);d===-1&&(d=u),L(r,e.slice(l,d),!0),c===44&&(L(t,o,r),r=Object.create(null),o=void 0),l=d=-1}else if(c===61&&l!==-1&&d===-1)a=e.slice(l,u),l=d=-1;else throw new SyntaxError(`Unexpected character at index ${u}`);else if(i){if(ye[c]!==1)throw new SyntaxError(`Unexpected character at index ${u}`);l===-1?l=u:n||(n=!0),i=!1}else if(s)if(ye[c]===1)l===-1&&(l=u);else if(c===34&&l!==-1)s=!1,d=u;else if(c===92)i=!0;else throw new SyntaxError(`Unexpected character at index ${u}`);else if(c===34&&e.charCodeAt(u-1)===61)s=!0;else if(d===-1&&ye[c]===1)l===-1&&(l=u);else if(l!==-1&&(c===32||c===9))d===-1&&(d=u);else if(c===59||c===44){if(l===-1)throw new SyntaxError(`Unexpected character at index ${u}`);d===-1&&(d=u);let h=e.slice(l,d);n&&(h=h.replace(/\\/g,""),n=!1),L(r,a,h),c===44&&(L(t,o,r),r=Object.create(null),o=void 0),a=void 0,l=d=-1}else throw new SyntaxError(`Unexpected character at index ${u}`);if(l===-1||s||c===32||c===9)throw new SyntaxError("Unexpected end of input");d===-1&&(d=u);let f=e.slice(l,d);return o===void 0?L(t,f,r):(a===void 0?L(r,f,!0):n?L(r,a,f.replace(/\\/g,"")):L(r,a,f),L(t,o,r)),t}function Xi(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:Xi,parse:Zi}});var Ze=T((zo,on)=>{"use strict";var Qi=require("events"),es=require("https"),ts=require("http"),Yr=require("net"),rs=require("tls"),{randomBytes:ns,createHash:is}=require("crypto"),{Duplex:Vo,Readable:Ho}=require("stream"),{URL:Bt}=require("url"),q=ne(),ss=Rt(),os=Mt(),{isBlob:as}=ie(),{BINARY_TYPES:Jr,CLOSE_TIMEOUT:ls,EMPTY_BUFFER:Je,GUID:cs,kForOnEventAttribute:Ut,kListener:fs,kStatusCode:ds,kWebSocket:E,NOOP:Zr}=M(),{EventTarget:{addEventListener:us,removeEventListener:hs}}=Hr(),{format:ps,parse:ms}=ze(),{toBuffer:gs}=pe(),Xr=Symbol("kAborted"),jt=[8,13],U=["CONNECTING","OPEN","CLOSING","CLOSED"],_s=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,v=class e extends Qi{constructor(t,r,n){super(),this._binaryType=Jr[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=Je,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 ss({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 os(t,this._extensions,n.generateMask);this._receiver=i,this._sender=s,this._socket=t,i[E]=this,s[E]=this,t[E]=this,i.on("conclude",vs),i.on("drain",Ss),i.on("error",ws),i.on("message",Es),i.on("ping",xs),i.on("pong",Ts),s.onerror=ks,t.setTimeout&&t.setTimeout(0),t.setNoDelay&&t.setNoDelay(),r.length>0&&t.unshift(r),t.on("close",rn),t.on("data",Ye),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[q.extensionName]&&this._extensions[q.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||Je,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||Je,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[q.extensionName]||(i.compress=!1),this._sender.send(t||Je,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(v,"CONNECTING",{enumerable:!0,value:U.indexOf("CONNECTING")});Object.defineProperty(v.prototype,"CONNECTING",{enumerable:!0,value:U.indexOf("CONNECTING")});Object.defineProperty(v,"OPEN",{enumerable:!0,value:U.indexOf("OPEN")});Object.defineProperty(v.prototype,"OPEN",{enumerable:!0,value:U.indexOf("OPEN")});Object.defineProperty(v,"CLOSING",{enumerable:!0,value:U.indexOf("CLOSING")});Object.defineProperty(v.prototype,"CLOSING",{enumerable:!0,value:U.indexOf("CLOSING")});Object.defineProperty(v,"CLOSED",{enumerable:!0,value:U.indexOf("CLOSED")});Object.defineProperty(v.prototype,"CLOSED",{enumerable:!0,value:U.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(e=>{Object.defineProperty(v.prototype,e,{enumerable:!0})});["open","error","close","message"].forEach(e=>{Object.defineProperty(v.prototype,`on${e}`,{enumerable:!0,get(){for(let t of this.listeners(e))if(t[Ut])return t[fs];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})}})});v.prototype.addEventListener=us;v.prototype.removeEventListener=hs;on.exports=v;function Qr(e,t,r,n){let i={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:ls,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;Ke(e,m);return}let c=o?443:80,d=ns(16).toString("base64"),u=o?es.request:ts.request,f=new Set,h;if(i.createConnection=i.createConnection||(o?bs:ys),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":d,Connection:"Upgrade",Upgrade:"websocket"},i.path=s.pathname+s.search,i.timeout=i.handshakeTimeout,i.perMessageDeflate&&(h=new q({...i.perMessageDeflate,isServer:!1,maxPayload:i.maxPayload}),i.headers["Sec-WebSocket-Extensions"]=ps({[q.extensionName]:h.offer()})),r.length){for(let m of r){if(typeof m!="string"||!_s.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[_,w]of Object.entries(m))n.headers[_.toLowerCase()]=w}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=u(i),e._redirects&&e.emit("redirect",e.url,g)}else g=e._req=u(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,Ke(e,m))}),g.on("response",m=>{let _=m.headers.location,w=m.statusCode;if(_&&i.followRedirects&&w>=300&&w<400){if(++e._redirects>i.maxRedirects){k(e,g,"Maximum redirects exceeded");return}g.abort();let O;try{O=new Bt(_,t)}catch{let ee=new SyntaxError(`Invalid URL: ${_}`);Ke(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,_,w)=>{if(e.emit("upgrade",m),e.readyState!==v.CONNECTING)return;g=e._req=null;let O=m.headers.upgrade;if(O===void 0||O.toLowerCase()!=="websocket"){k(e,_,"Invalid Upgrade header");return}let V=is("sha1").update(d+cs).digest("base64");if(m.headers["sec-websocket-accept"]!==V){k(e,_,"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,_,fe);return}ee&&(e._protocol=ee);let ur=m.headers["sec-websocket-extensions"];if(ur!==void 0){if(!h){k(e,_,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let vt;try{vt=ms(ur)}catch{k(e,_,"Invalid Sec-WebSocket-Extensions header");return}let hr=Object.keys(vt);if(hr.length!==1||hr[0]!==q.extensionName){k(e,_,"Server indicated an extension that was not requested");return}try{h.accept(vt[q.extensionName])}catch{k(e,_,"Invalid Sec-WebSocket-Extensions header");return}e._extensions[q.extensionName]=h}e.setSocket(_,w,{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 Ke(e,t){e._readyState=v.CLOSING,e._errorEmitted=!0,e.emit("error",t),e.emitClose()}function ys(e){return e.path=e.socketPath,Yr.connect(e)}function bs(e){return e.path=void 0,!e.servername&&e.servername!==""&&(e.servername=Yr.isIP(e.host)?"":e.host),rs.connect(e)}function k(e,t,r){e._readyState=v.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(Ke,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=as(t)?t.size:gs(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 vs(e,t){let r=this[E];r._closeFrameReceived=!0,r._closeMessage=t,r._closeCode=e,r._socket[E]!==void 0&&(r._socket.removeListener("data",Ye),process.nextTick(en,r._socket),e===1005?r.close():r.close(e,t))}function Ss(){let e=this[E];e.isPaused||e._socket.resume()}function ws(e){let t=this[E];t._socket[E]!==void 0&&(t._socket.removeListener("data",Ye),process.nextTick(en,t._socket),t.close(e[ds])),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e))}function Kr(){this[E].emitClose()}function Es(e,t){this[E].emit("message",e,t)}function xs(e){let t=this[E];t._autoPong&&t.pong(e,!this._isServer,Zr),t.emit("ping",e)}function Ts(e){this[E].emit("pong",e)}function en(e){e.resume()}function ks(e){let t=this[E];t.readyState!==v.CLOSED&&(t.readyState===v.OPEN&&(t._readyState=v.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[E];if(this.removeListener("close",rn),this.removeListener("data",Ye),this.removeListener("end",nn),e._readyState=v.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[E]=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 Ye(e){this[E]._receiver.write(e)||this.pause()}function nn(){let e=this[E];e._readyState=v.CLOSING,e._receiver.end(),this.end()}function sn(){let e=this[E];this.removeListener("error",sn),this.on("error",Zr),e&&(e._readyState=v.CLOSING,this.destroy())}});var fn=T((Ko,cn)=>{"use strict";var Jo=Ze(),{Duplex:Cs}=require("stream");function an(e){e.emit("close")}function Os(){!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 As(e,t){let r=!0,n=new Cs({...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",Os),n.on("error",ln),n}cn.exports=As});var Wt=T((Yo,dn)=>{"use strict";var{tokenChars:Ps}=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&&Ps[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}dn.exports={parse:Ns}});var yn=T((Xo,_n)=>{"use strict";var Is=require("events"),Xe=require("http"),{Duplex:Zo}=require("stream"),{createHash:Rs}=require("crypto"),un=ze(),K=ne(),Ds=Wt(),Ls=Ze(),{CLOSE_TIMEOUT:Ms,GUID:$s,kWebSocket:Bs}=M(),Us=/^[+/0-9A-Za-z]{22}==$/,hn=0,pn=1,gn=2,qt=class extends Is{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:Ms,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=Xe.createServer((n,i)=>{let s=Xe.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=js(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(be,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(be,this):process.nextTick(be,this);else{let r=this._server;this._removeListeners(),this._removeListeners=this._server=null,r.close(()=>{be(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||!Us.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)){ve(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 d=t.headers["sec-websocket-extensions"],u={};if(this.options.perMessageDeflate&&d!==void 0){let f=new K({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let h=un.parse(d);h[K.extensionName]&&(f.accept(h[K.extensionName]),u[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,_)=>{if(!h)return ve(r,g||401,m,_);this.completeUpgrade(u,s,c,t,r,n,i)});return}if(!this.options.verifyClient(f))return ve(r,401)}this.completeUpgrade(u,s,c,t,r,n,i)}completeUpgrade(t,r,n,i,s,o,a){if(!s.readable||!s.writable)return s.destroy();if(s[Bs])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>hn)return ve(s,503);let c=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${Rs("sha1").update(r+$s).digest("base64")}`],d=new this.options.WebSocket(null,void 0,this.options);if(n.size){let u=this.options.handleProtocols?this.options.handleProtocols(n,i):n.values().next().value;u&&(c.push(`Sec-WebSocket-Protocol: ${u}`),d._protocol=u)}if(t[K.extensionName]){let u=t[K.extensionName].params,f=un.format({[K.extensionName]:[u]});c.push(`Sec-WebSocket-Extensions: ${f}`),d._extensions=t}this.emit("headers",c,i),s.write(c.concat(`\r
|
|
3
3
|
`).join(`\r
|
|
4
|
-
`)),s.removeListener("error",mn),
|
|
4
|
+
`)),s.removeListener("error",mn),d.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(d),d.on("close",()=>{this.clients.delete(d),this._shouldEmitClose&&!this.clients.size&&process.nextTick(be,this)})),a(d,i)}};_n.exports=qt;function js(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 be(e){e._state=gn,e.emit("close")}function mn(){this.destroy()}function ve(e,t,r,n){r=r||Xe.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} ${Xe.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 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
|
|
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 ve(r,n,i,s)}});var Fs,Ws,qs,Gs,Vs,Hs,zs,Gt,bn=y(()=>{Fs=j(fn(),1),Ws=j(ze(),1),qs=j(ne(),1),Gs=j(Rt(),1),Vs=j(Mt(),1),Hs=j(Wt(),1),zs=j(Ze(),1),Gt=j(yn(),1)});function vn(){return`m_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}function Qe(e,t,r){return{id:e,kind:"response",error:{code:t,message:r}}}var ce=y(()=>{"use strict"});function wn(e){return String(e?Math.floor(1e5+e()*9e5):(0,tt.randomInt)(1e5,1e6))}var tt,G,En,et,xn=y(()=>{"use strict";tt=require("node:crypto"),G=require("node:fs"),En=require("node:path");ce();et=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,G.existsSync)(this.persistPath))try{let r=JSON.parse((0,G.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,G.mkdirSync)((0,En.dirname)(this.persistPath),{recursive:!0}),(0,G.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=wn(s),c=0;for(;this.sessions.has(l)&&c++<100;)l=wn(s);if(this.sessions.has(l))throw Object.assign(new Error("RATE_LIMITED: code space exhausted"),{code:"RATE_LIMITED"});let d=String(r??"agent").slice(0,64)||"agent",u=(Array.isArray(n)?n:[]).map(String).slice(0,8),f={code:l,deviceId:t,clientName:d,scopes:u,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,tt.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);if(!n||n.expiresAt<=r)return{status:"expired"};if(n.approved&&n.token){let i=n.token;return this.sessions.delete(t),{status:"approved",token:i}}return{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 rt,Tn=y(()=>{"use strict";ce();rt=class{onTiming;now;constructor(t,r=()=>performance.now()){this.onTiming=t,this.now=r}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=vn(),l={id:a,kind:"request",method:r,params:n,agentName:s?.agentName},c=this.now(),d=0,u="error";return new Promise((f,h)=>{let g=setTimeout(()=>{this.pending.delete(a),h(Object.assign(new Error(`TIMEOUT waiting for device ${t}`),{code:"TIMEOUT"}))},i);this.pending.set(a,{deviceId:t,resolve:f,reject:h,timer:g});let m=this.now();try{o(JSON.stringify(l))}catch(_){this.pending.delete(a),clearTimeout(g),h(_ instanceof Error?_:new Error(String(_)))}finally{d=Math.max(0,this.now()-m)}}).then(f=>(u="response",f)).finally(()=>{try{this.onTiming?.({method:/^browser_[a-z_]{1,40}$/.test(r)?r:"other",outcome:u,sendMs:d,roundTripMs:Math.max(0,this.now()-c)})}catch{}})}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}}});var nt,Vt=y(()=>{"use strict";nt=["Babtab is a pull-mode browser runtime: observe digests, find refs, act with verification.","SOP:","1) Start with browser_observe level=page_digest (~100 tokens). Avoid level=full unless explicitly required.","2) Prefer browser_find (role/name/region/nth) over interactive dumps; act with returned refs.","3) If a flow needs \u22653 consecutive fill/click/select steps, MUST call browser_plan (one decision, many verified steps).","4) Always pass expect postconditions: URL conditions for navigate; relevant URL/element/value conditions for actions. Success without expect is dispatch_only \u2014 not business success.","5) On AMBIGUOUS_TARGET: pick a ranked candidate by ref, or refine with region/nth/near. Do not guess.","6) After an action error (including STALE_TARGET), observe the current URL and expected state before retrying: the action may already have succeeded. If still needed, re-find the target; do not click lookalike candidates.","7) Virtualized lists (Gmail/Slack/feeds): scroll, re-find, then act. Canvas sites (Docs/Figma): prefer menus/dialogs/press \u2014 never canvas tiles.","Gmail: verify the submitted search URL and loaded results before interpreting count:0. is:unread means current unread state, not never opened. Re-find row checkboxes after list changes; use expect checked=true to confirm selection. For delete, require a relevant new confirmation or disappearance of a unique previously present row; an inbox badge alone is not proof. Never retry a dispatched destructive click without checking its outcome.","8) Navigate verifies URL conditions only. Use browser_wait/browser_assert for content readiness, then browser_extract. Empty paragraphs do not prove an empty article; inspect page state. Check truncated before summarizing extracted text.","Pairing: if tools report pairing is needed, ask the user to open Babtab in Chrome and approve the connection."].join(" ")});function Qs(e){let t=new URL(e.url??"/","http://localhost");return e.method==="POST"&&t.pathname==="/mcp"}async function kn(e,t,r){if(!Qs(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 de(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:Xs,capabilities:{tools:{}},serverInfo:{name:"babtab-relay",version:"0.3.0"},instructions:nt}});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:ue.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:it("Tool arguments must be an object")});let l=Le(o);if(!l)return I(t,e,s.id??null,{result:it(`Unknown tool: ${o}`)});if(!$e(n,l.scope))return I(t,e,s.id??null,{result:it(`Token lacks scope ${l.scope} for ${o}`)});try{let c=await r.registry.routeToDevice(n.deviceId,o,a,13e4,{agentName:n.clientName}),d=[];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&&d.push({type:"image",mimeType:h[1],data:h[2]})}let u=Ht(c),f=JSON.stringify(u)??"null";return d.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:d,...x(c)&&c.ok===!1?{isError:!0}:{}}})}catch(c){let d=c;return I(t,e,s.id??null,{result:it(`${d.code??"DISCONNECTED"}: ${d.message}`,!0)})}}return I(t,e,s.id??null,{error:{code:-32601,message:`Method not found: ${s.method}`}},404)}function it(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
9
|
data: ${s}
|
|
10
10
|
|
|
11
|
-
`),!0):(e.writeHead(i,{"content-type":"application/json","access-control-allow-origin":"*"}),e.end(s),!0)}function
|
|
12
|
-
`)),i=setInterval(()=>{n.
|
|
13
|
-
`),
|
|
14
|
-
`)
|
|
11
|
+
`),!0):(e.writeHead(i,{"content-type":"application/json","access-control-allow-origin":"*"}),e.end(s),!0)}function Ht(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(Ht);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]=Ht(n)}return t}var Xs,Cn=y(()=>{"use strict";Re();Be();Me();Vt();ce();Xs="2024-11-05"});function ot(e={}){let t=new et({persistPath:e.tokenFile??process.env.BABTAB_TOKEN_FILE??"./data/relay-tokens.json"}),r=new rt(process.env.BABTAB_PERF==="1"?f=>process.stderr.write(`${JSON.stringify({type:"babtab:relay-timing",...f})}
|
|
12
|
+
`):void 0),n,i=!1,s=new Map,o=new Map,a=(0,On.createServer)((f,h)=>{if(i){h.writeHead(503).end();return}to(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")??"",_=setTimeout(()=>f.close(1008,"device authentication required"),5e3);_.unref(),f.once("close",()=>clearTimeout(_)),f.once("message",w=>{clearTimeout(_);let O;try{O=JSON.parse(String(w))}catch{f.close(1008,"invalid authentication");return}if(!x(O)||O.kind!=="authenticate"||!io(m,O.token)){f.close(1008,"invalid device credential");return}let V=s.get(m);s.set(m,f),ro(f,m,t,r),V?.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)),no(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 d=e.port??0;t.onRevoke(f=>{for(let[h,g]of o)g===f&&h.close(1008,"token revoked")}),a.listen(d,e.host??"127.0.0.1");let u;return n={server:a,pairings:t,registry:r,close:()=>u??=new Promise((f,h)=>{i=!0,clearInterval(c);for(let w of r.onlineDevices())r.failPendingForDevice(w);for(let w of l.clients)w.close(1001,"relay shutting down");let g=setTimeout(()=>{for(let w of l.clients)w.terminate();a.closeAllConnections()},1e3),m=new Promise((w,O)=>a.close(V=>V?O(V):w())),_=new Promise(w=>l.close(()=>w()));Promise.all([m,_]).then(()=>{clearTimeout(g),f()},w=>{clearTimeout(g),h(w)})})},n}async function to(e,t,r){let n=new URL(e.url??"/","http://localhost"),i=e.headers.origin??"",s=/^chrome-extension:\/\/[a-z]{32}$/.test(i)?i:null;if(e.method==="OPTIONS"){let a={"access-control-allow-methods":"GET, POST, OPTIONS","access-control-allow-headers":"content-type, authorization"};s&&(a["access-control-allow-origin"]=s),t.writeHead(204,a),t.end();return}let o=(a,l)=>{let c={"content-type":"application/json"};s&&(c["access-control-allow-origin"]=s),t.writeHead(a,c),t.end(JSON.stringify(l))};if(e.method==="GET"&&n.pathname==="/health"){o(200,{ok:!0,service:"babtab-relay",bridgeVersion:1,devices:r.registry.onlineDevices().length});return}if(e.method==="GET"&&n.pathname==="/client/status"){let a=r.pairings.verifyToken(he(e.headers.authorization)??"");if(!a){o(401,{error:"Unauthorized"});return}o(200,{deviceOnline:r.registry.isDeviceOnline(a.deviceId)});return}if(e.method==="POST"&&n.pathname==="/pairing/request"){let a=await de(e),l=String(a.deviceId??"").slice(0,128);if(!l){o(400,{error:"deviceId required"});return}let c=Array.isArray(a.scopes)?a.scopes.map(String).slice(0,8):["browser:read","browser:act"];try{let d=r.pairings.requestPairing(l,String(a.clientName??"agent"),c);o(200,{code:d.code,expiresAt:d.expiresAt,deviceOnline:r.registry.isDeviceOnline(l)})}catch(d){if(d.code==="RATE_LIMITED"){o(429,{error:d.message});return}throw d}return}if(e.method==="POST"&&n.pathname==="/pairing/claim"){let a=await de(e);o(200,r.pairings.claimPairing(String(a.code??"")));return}if(e.method==="POST"&&n.pathname==="/pairing/revoke"){let a=he(e.headers.authorization)??"",l=a?r.pairings.revokeToken(a):!1;o(200,{ok:l});return}await kn(e,t,r)||o(404,{error:"not found"})}function ro(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(Qe(a.id,"UNSUPPORTED_OPERATION",`Unknown device method ${a.method}`)))}}}),e.on("close",()=>n.unregisterDevice(t,i))}function no(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=Le(o.method);if(!l||!$e(a,l.scope)){e.send(JSON.stringify(Qe(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(Qe(o.id,c.code??"DISCONNECTED",c.message)))})})}function io(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,st.createHash)("sha256").update(t).digest();return(0,st.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 st,On,zt=y(()=>{"use strict";st=require("node:crypto");Re();Me();Be();On=require("node:http");bn();ce();xn();Tn();Be();Cn()});var In={};pr(In,{LocalBridge:()=>lt,parseBridgeArgs:()=>so,runStdio:()=>oo});function so(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 oo(e,t=process.stdin,r=process.stdout){let n=new lt(e,u=>process.stderr.write(`[babtab] ${u}
|
|
13
|
+
`)),i=setInterval(()=>{n.tick()},2e3);n.tick();let s=(u,f)=>r.write(`${JSON.stringify({jsonrpc:"2.0",id:u,...f})}
|
|
14
|
+
`),o=!1,a=()=>{},l=async u=>{let f;try{f=JSON.parse(u)}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.3.0"},instructions:nt}});else if(f.method==="ping")s(f.id,{result:{}});else if(f.method==="tools/list")s(f.id,{result:{tools:ue.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 d=u=>{c+=u;let f;for(;(f=c.indexOf(`
|
|
15
|
+
`))!==-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(u=>{a=()=>u(),t.on("data",d),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",d),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 Pn,R,Nn,at,lt,Rn=y(()=>{"use strict";Pn=require("node:crypto"),R=require("node:fs"),Nn=require("node:os"),at=require("node:path");zt();Re();Me();Vt();ce();lt=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,at.join)((0,Nn.homedir)(),".babtab");let n=(0,Pn.createHash)("sha256").update(`${this.base}/${t.deviceId}/${t.clientName}`).digest("hex");this.credentialPath=(0,at.join)(this.dataDir,`client-${n}.json`);try{let i=JSON.parse((0,R.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,R.mkdirSync)(this.dataDir,{recursive:!0,mode:448});let t=ot({port:this.opts.port,tokenFile:(0,at.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,R.mkdirSync)(this.dataDir,{recursive:!0,mode:448});let s=`${this.credentialPath}.${process.pid}.tmp`;(0,R.writeFileSync)(s,JSON.stringify({token:this.token}),{mode:384}),(0,R.chmodSync)(s,384),(0,R.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 ct(){let e=(0,Ln.homedir)();return{platform:process.platform,home:e,appData:process.env.APPDATA??(0,S.join)(e,"AppData","Roaming"),localAppData:process.env.LOCALAPPDATA??(0,S.join)(e,"AppData","Local")}}function Dn(e,t){let r=t?"Code - Insiders":"Code";return e.platform==="win32"?(0,S.join)(e.appData,r,"User"):e.platform==="darwin"?(0,S.join)(e.home,"Library","Application Support",r,"User"):(0,S.join)(e.home,".config",r,"User")}function ao(e){return e.platform==="win32"?(0,S.join)(e.appData,"Claude","claude_desktop_config.json"):e.platform==="darwin"?(0,S.join)(e.home,"Library","Application Support","Claude","claude_desktop_config.json"):(0,S.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 ft(e,t){return{url:`${e}/mcp`,headers:{Authorization:`Bearer ${t}`}}}function Jt(e,t){return{type:"http",...ft(e,t)}}function Kt(e,t){return{command:"npx",args:["-y","mcp-remote",`${e}/mcp`,"--allow-http","--header",`Authorization:Bearer ${t}`]}}function $n(e,t,r){switch(e){case"copilot-http":return Jt(t,r);case"stdio-remote":return Kt(t,r);case"http":default:return ft(t,r)}}function Bn(e,t){return`url = ${JSON.stringify(`${e}/mcp`)}
|
|
15
16
|
http_headers = { "Authorization" = ${JSON.stringify(`Bearer ${t}`)} }`}function Un(e,t){return`mcp_servers:
|
|
16
17
|
babtab:
|
|
17
18
|
url: "${e}/mcp"
|
|
18
19
|
headers:
|
|
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
|
|
20
|
+
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 Ln,S,Se,Yt=y(()=>{"use strict";Ln=require("node:os"),S=require("node:path");Se=[{id:"cursor",label:"Cursor",aliases:[],paths:e=>[(0,S.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,S.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,S.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,S.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,S.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=>[ao(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,S.join)(e.home,".gemini","antigravity","mcp_config.json"),(0,S.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,S.join)(e.appData,"devin","mcp_config.json")]:[(0,S.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,S.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,S.join)(e.home,".hermes","config.yaml"),(0,S.join)(e.localAppData,"hermes","config.yaml")]:[(0,S.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 lo(e,t){let r=e.slice(0,t).split(/\r?\n/);return[r.length,r.pop().length+1]}function co(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+=`
|
|
20
21
|
`,o===t&&(i+=" ".repeat(s+r+2),i+=`^
|
|
21
|
-
`))}return i}var p,X=y(()=>{p=class e extends Error{line;column;codeblock;constructor(t,r){let[n,i]=
|
|
22
|
+
`))}return i}var p,X=y(()=>{p=class e extends Error{line;column;codeblock;constructor(t,r){let[n,i]=lo(r.toml,r.ptr),s=co(r.toml,n,i);super(`Invalid TOML document: ${t}
|
|
22
23
|
|
|
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
|
|
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&&`
|
|
24
|
+
${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 dt(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,d=0,u=r===120?2:r===117?4:8;for(let f=0;f<u;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),d=d<<4|g}(d<0||d>1114111||d>=55296&&d<=57343)&&p.x("invalid unicode escape",e,c),o+=String.fromCodePoint(d),a=e.p--,l=0}else s&&(r===32||r===9)?l=2:(r===98?o+="\b":r===116?o+=" ":r===110?o+=`
|
|
25
|
+
`: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 Zt=y(()=>{X();});var fo,we,Xt=y(()=>{fo=/^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i,we=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(fo);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 er(e,t){return e===32||e===9||e===10||e===13||t&&(e===t||e===44)||e===35}function xe(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?dt(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?ut(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?uo(e,n,t):e.s.charCodeAt(e.p+2)===58?ho(e,n,t):ut(e,e.p,n,0,t)}function ut(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||er(s=e.s.charCodeAt(e.p),i))return e.bi===!0?0n:0;if(!n){if(s===120)return Qt(e,t,16,i);if(s===98)return Qt(e,t,2,i);if(s===111)return Qt(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),!er(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 Qt(e,t,r,n){let i,s=1;for(;++e.p<e.s.length&&(i=e.s.charCodeAt(e.p),!er(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 uo(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 ut(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 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(;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 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 ho(e,t,r){let n=e.p;if(!C(t)||!C(e.s.charCodeAt(++e.p)))return ut(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 Ee(e,i,4,!1,n)}function Ee(e,t,r,n,i,s){if(e.ld){let o=new we(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 tr=y(()=>{Zt();rr();X();Xt();});function po(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 D(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;po(e)}}var nr=y(()=>{X();});function ht(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(dt(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(D(e),(i=e.s.charCodeAt(e.p))===125)return e.p++,r;let s,o=r,a=!1,l=e.p,c=ht(e);for(let u=0;u<c.length;u++){u&&(o=a?o[s]:o[s]=Object.create(null)),s=c[u],(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),D(e,!0,!0);let d=xe(e,125);if(o&&typeof(o[s]=d)=="object"&&n.add(d),D(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(D(e),(n=e.s.charCodeAt(e.p))===93)return e.p++,r;if(r.push(xe(e,93)),D(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 rr=y(()=>{Zt();tr();nr();X();});function Gn(e,t,r,n,i){let s=r,o=n,a,l=!1,c;for(let d=0;d<t.length;d++){if(d){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 u=s.length-1;s=s[u],o=o[u].c}}if(a=t[d],(l=Object.hasOwn(s,a))&&o[a]?.t===0&&o[a]?.d)return null;if(!l){let u=a==="__proto__";if(e.uk&&(u||a==="constructor"))return!1;u&&(Object.defineProperty(s,a,{enumerable:!0,configurable:!0,writable:!0}),Object.defineProperty(o,a,{enumerable:!0,configurable:!0,writable:!0})),o[a]={t:d<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 Te(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++,D(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 d=ht(r,93);c&&(e.charCodeAt(r.p)!==93&&p.x("expected end of table array declaration",r),r.p++);let u=Gn(r,d,n,i,c?2:1);u?(l=u[2],a=u[1]):(Vn(r,u,s),o=!0)}else{s=r.p;let c=ht(r),d=Gn(r,c,a,l,0);!d&&!o&&Vn(r,d,s),D(r,!0,!0);let u=xe(r,void 0);d&&!o&&(d[1][d[0]]=u)}D(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),D(r)}return n}var Hn=y(()=>{rr();tr();nr();X();});function ke(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 go(e){for(let t=0;t<e.length;t++)if(ke(e[t])!=="object")return!1;return e.length!=0}function Jn(e){return JSON.stringify(e).replaceAll("\x7F","\\u007f")}function _o(e){return Jn(zn?e.toWellFormed():e)}function Kn(e){if(mo.test(e))return e;if(zn&&!e.isWellFormed())throw new RangeError("key contains illegal lone surrogates");return Jn(e)}function ir(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 _o(e);case"date":if(isNaN(e.getTime()))throw new TypeError("cannot serialize invalid date");return e.toISOString();case"object":return yo(e,r,n,i);case"array":return bo(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 yo(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)+" = "+ir(e[a],ke(e[a]),t-1,r,n)}return s+" }"}function bo(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+=ir(e[s],ke(e[s]),t-1,r,n)}return i+" ]"}function vo(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&&`
|
|
25
26
|
`}[[${t}]]
|
|
26
|
-
`,s+=
|
|
27
|
-
`)+
|
|
28
|
-
`)+
|
|
27
|
+
`,s+=sr(0,e[o],t,r,n,i);return s}function sr(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 d=l[c];if(t[d]!==null&&t[d]!==void 0){let u=ke(t[d]);if(u==="symbol"||u==="function")throw new TypeError(`cannot serialize values of type '${u}'`);let f=Kn(d);if(u==="array"&&go(t[d]))a+=(a&&`
|
|
28
|
+
`)+vo(t[d],r?`${r}.${f}`:f,n-1,i,s);else if(u==="object"){let h=r?`${r}.${f}`:f;a+=(a&&`
|
|
29
|
+
`)+sr(h,t[d],h,n-1,i,s)}else o+=f,o+=" = ",o+=ir(t[d],u,n,i,s),o+=`
|
|
29
30
|
`}}return e&&(o||!a)&&(o=o?`[${e}]
|
|
30
31
|
${o}`:`[${e}]`),o&&a?`${o}
|
|
31
|
-
${a}`:o||a}function
|
|
32
|
+
${a}`:o||a}function or(e,{maxDepth:t=1e3,numbersAsFloat:r=!1,strictTemporal:n=!1}={}){if(ke(e)!=="object")throw new TypeError("stringify can only be called with an object");let i=sr(0,e,"",t,r,n);return i[i.length-1]!==`
|
|
32
33
|
`?i+`
|
|
33
|
-
`:i}var
|
|
34
|
+
`:i}var mo,zn,Yn=y(()=>{mo=/^[a-z0-9-_]+$/i,zn=!!"".isWellFormed});var Zn=y(()=>{Hn();Yn();Xt();X();});function mt(e,t){let r=e.paths(t);if(r.length===0)return null;for(let n of r)try{if((0,b.statSync)((0,Ce.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]!==`
|
|
34
35
|
`;)r++;continue}if(s==="/"&&o==="*"){for(r+=2;r<e.length&&!(e[r]==="*"&&e[r+1]==="/");)e[r]===`
|
|
35
36
|
`&&(t+=`
|
|
36
|
-
`),r++;r+=2;continue}t+=s,r++}return t}function
|
|
37
|
-
Fix or rename it first (setup left it untouched).`)}if(!
|
|
38
|
-
`,{mode:384}),{path:t,created:!s,backedUp:l}}function
|
|
37
|
+
`),r++;r+=2;continue}t+=s,r++}return t}function pt(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Oe(e){try{return(0,b.existsSync)(e)?((0,b.writeFileSync)(`${e}.bak`,(0,b.readFileSync)(e)),!0):!1}catch{return!1}}function gt(e){let{path:t,rootKey:r,serverName:n,entry:i}=e,s=(0,b.existsSync)(t),o={};if(s){let c=(0,b.readFileSync)(t,"utf8"),d;try{d=JSON.parse(c.trim()===""?"{}":So(c))}catch{throw new Error(`Existing config is not valid JSON: ${t}
|
|
38
|
+
Fix or rename it first (setup left it untouched).`)}if(!pt(d))throw new Error(`Existing config root must be an object: ${t} (left untouched).`);o=d;let u=o[r];if(u!==void 0&&!pt(u))throw new Error(`Existing "${r}" is not an object: ${t} (left untouched).`)}let a=pt(o[r])?o[r]:{};a[n]=i,o[r]=a,(0,b.mkdirSync)((0,Ce.dirname)(t),{recursive:!0});let l=s?Oe(t):!1;return(0,b.writeFileSync)(t,`${JSON.stringify(o,null,2)}
|
|
39
|
+
`,{mode:384}),{path:t,created:!s,backedUp:l}}function _t(e,t){let r=(0,b.existsSync)(e),n=r?Te((0,b.readFileSync)(e,"utf8")):{},i=Te(`${wo}
|
|
39
40
|
${t}
|
|
40
|
-
`);if(n.mcp_servers!==void 0&&!
|
|
41
|
-
`;else{let s=(0,
|
|
41
|
+
`);if(n.mcp_servers!==void 0&&!pt(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=or(n);Te(o),(0,b.mkdirSync)((0,Ce.dirname)(e),{recursive:!0});let a=r?Oe(e):!1;if(r&&!a)throw new Error(`Cannot back up ${e}; left untouched`);let l=`${e}.${(0,Xn.randomUUID)()}.tmp`;try{(0,b.writeFileSync)(l,o,{mode:384,flag:"wx"}),(0,b.renameSync)(l,e)}finally{(0,b.rmSync)(l,{force:!0})}return{path:e,created:!r,backedUp:a}}function yt(e,t){let r=(0,b.existsSync)(e),n;if(!r)n=`${t}
|
|
42
|
+
`;else{let s=(0,b.readFileSync)(e,"utf8").split(`
|
|
42
43
|
`),o=s.findIndex(a=>/^mcp_servers\s*:\s*(#.*)?$/.test(a));if(o===-1){let a=s.length>0&&s[s.length-1].trim()!==""?`
|
|
43
44
|
`:"";n=`${s.join(`
|
|
44
45
|
`)}${a}
|
|
45
46
|
${t}
|
|
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)),
|
|
47
|
+
`}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)),d=t.split(`
|
|
47
48
|
`).slice(1).join(`
|
|
48
|
-
`),
|
|
49
|
+
`),u;if(c===-1)u=[...l,d];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++;u=[...l.slice(0,c),d,...l.slice(h)]}n=[...s.slice(0,o+1),...u,...s.slice(a)].join(`
|
|
49
50
|
`),n.endsWith(`
|
|
50
51
|
`)||(n+=`
|
|
51
|
-
`)}}(0,
|
|
52
|
-
args = ${JSON.stringify(i.args)}`):s.kind==="yaml-hermes"&&
|
|
52
|
+
`)}}(0,b.mkdirSync)((0,Ce.dirname)(e),{recursive:!0});let i=r?Oe(e):!1;return(0,b.writeFileSync)(e,n,{mode:384}),{path:e,created:!r,backedUp:i}}var Xn,b,Ce,wo,ar=y(()=>{"use strict";Zn();Xn=require("node:crypto"),b=require("node:fs"),Ce=require("node:path");wo="[mcp_servers.babtab]"});function xo(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=ct()){let i=xo(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=mt(e,n);if(!o)throw new Error(`Automatic setup is unavailable for ${e.label}`);s.kind==="json"?gt({path:o,rootKey:s.rootKey,serverName:"babtab",entry:{...i,...s.entry==="copilot-http"?{type:"stdio"}:{}}}):s.kind==="toml-codex"?_t(o,`command = ${JSON.stringify(i.command)}
|
|
53
|
+
args = ${JSON.stringify(i.args)}`):s.kind==="yaml-hermes"&&yt(o,`mcp_servers:
|
|
53
54
|
babtab:
|
|
54
55
|
command: ${JSON.stringify(i.command)}
|
|
55
56
|
args: ${JSON.stringify(i.args)}`),console.log(`Configured ${o} (existing settings preserved; backup created when replacing a file).`)}return console.log(`
|
|
56
57
|
${e.nextStep.replace(" (via mcp-remote bridge)","")}
|
|
57
58
|
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");
|
|
59
|
-
`),"","Options:"," --target, -t <id> Harness to configure (required, see list above)",` --port, -p <n> Relay port (default ${
|
|
60
|
-
`)}function ci(){return
|
|
61
|
-
${
|
|
59
|
+
Then ask: "Use babtab to observe the current tab".`),0}var Qn,Eo,ti=y(()=>{"use strict";Qn=require("node:child_process");Yt();ar();Eo="@babtab/relay@0.3.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 lr(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 Ae(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 Pe("Pairing code expired \u2014 run the setup command again.");if(Date.now()>=s)throw new Ne("Timed out waiting for approval \u2014 run the setup command again.");await new Promise(l=>setTimeout(l,n))}}var Q,Ae,Pe,Ne,si=y(()=>{"use strict";Q=class extends Error{},Ae=class extends Error{},Pe=class extends Error{},Ne=class extends Error{}});var fr={};pr(fr,{DEFAULT_PORT:()=>Ie,SERVER_NAME:()=>ai,VERIFY_SENTENCE:()=>bt,backupFile:()=>Oe,copilotJsonEntry:()=>Jt,httpJsonEntry:()=>ft,listTargetCommands:()=>ci,parseSetupArgs:()=>li,runSetup:()=>ko,setupHelp:()=>cr,stdioRemoteJsonEntry:()=>Kt});function li(e){let t={target:"",port:Number(process.env.PORT??Ie),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 ${Ie}${t}`}function cr(){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:",Se.map(t=>` ${t.id.padEnd(17)} ${t.label}`).join(`
|
|
60
|
+
`),"","Options:"," --target, -t <id> Harness to configure (required, see list above)",` --port, -p <n> Relay port (default ${Ie}, 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: "${bt}".`," Remote --relay-url connections still require an already-running relay and pairing.",""].join(`
|
|
61
|
+
`)}function ci(){return Se.map(e=>`# ${e.label}
|
|
62
|
+
${To(e)}`).join(`
|
|
62
63
|
|
|
63
64
|
`)+`
|
|
64
|
-
`}function fi(e){return e===
|
|
65
|
-
`),console.error(
|
|
66
|
-
`),console.error(
|
|
67
|
-
`)),1;let n=t.relayUrl??`http://127.0.0.1:${t.port}`;if(r.action.kind==="print")return
|
|
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
|
|
65
|
+
`}function fi(e){return e===Ie?"npx -y @babtab/relay":`PORT=${e} npx -y @babtab/relay`}async function ko(e){let t;try{t=li(e)}catch(o){return console.error(`Error: ${o.message}
|
|
66
|
+
`),console.error(cr()),1}if(t.help)return console.log(cr()),0;if(t.listTargets)return console.log(ci()),0;let r=Mn(t.target);if(!r)return console.error(`Error: unknown --target "${t.target}". Pick one of:
|
|
67
|
+
`),console.error(Se.map(o=>` ${o.id}`).join(`
|
|
68
|
+
`)),1;let n=t.relayUrl??`http://127.0.0.1:${t.port}`;if(r.action.kind==="print")return Co(r,n,t);if(!t.deviceId)return console.error(`Error: --device is required.
|
|
69
|
+
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 lr(n)}catch(o){if(o instanceof Q)return console.error(`Error: relay is not reachable at ${n}.
|
|
69
70
|
Start it first in another terminal:
|
|
70
71
|
|
|
71
72
|
${fi(t.port)}
|
|
72
73
|
`),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
|
|
74
|
+
Open Advanced connection settings and use Save & Connect first, then re-run this command.`),3;i=o.code}catch(o){return o instanceof Ae?(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 Pe||o instanceof Ne?(console.error(`Error: ${o.message}`),3):(console.error(`Error: claim failed: ${o.message}`),3)}console.log("Approved \u2713");try{return Oo(r,n,s)}catch(o){return console.error(`Error: ${o.message}`),4}}async function Co(e,t,r){if(e.action.kind!=="print")return 1;try{await lr(t)}catch{console.log(`Note: relay is not reachable at ${t} yet \u2014 start it with:
|
|
74
75
|
|
|
75
76
|
${fi(r.port)}
|
|
76
77
|
`)}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
78
|
`),console.log(` ${jn(t,"<token>")}
|
|
78
79
|
`)):(console.log("Standard MCP (Streamable HTTP):"),console.log(` Endpoint: ${t}/mcp`),console.log(` Header: Authorization: Bearer <token>
|
|
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
|
|
80
|
+
`),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 Oo(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 d=c.error.code==="ENOENT";return console.error(d?`The "${l[0]}" CLI was not found. Install it, then run:
|
|
80
81
|
|
|
81
82
|
${l.join(" ")}
|
|
82
83
|
`:`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(`
|
|
83
|
-
Configured ${e.label} \u2713`),console.log(e.nextStep),console.log(`Then ask: "${
|
|
84
|
-
Wrote ${s} ${o?"(created)":"(updated, babtab entry replaced)"} \u2713`),a&&console.log(`Backup: ${s}.bak`),console.log(e.nextStep),console.log(`Then ask: "${
|
|
84
|
+
Configured ${e.label} \u2713`),console.log(e.nextStep),console.log(`Then ask: "${bt}".`),0)}let i=ct(),s=mt(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=$n(n.entry,t,r);({created:o,backedUp:a}=gt({path:s,rootKey:n.rootKey,serverName:ai,entry:l}))}else if(n.kind==="toml-codex")({created:o,backedUp:a}=_t(s,Bn(t,r)));else if(n.kind==="yaml-hermes")({created:o,backedUp:a}=yt(s,Un(t,r)));else return console.error(`Error: unsupported action for target "${e.id}".`),4;return console.log(`
|
|
85
|
+
Wrote ${s} ${o?"(created)":"(updated, babtab entry replaced)"} \u2713`),a&&console.log(`Backup: ${s}.bak`),console.log(e.nextStep),console.log(`Then ask: "${bt}".`),0}var oi,Ie,ai,bt,dr=y(()=>{"use strict";oi=require("node:child_process");ti();Yt();ar();si();Ie=3e3,ai="babtab",bt="Use babtab to observe the current tab"});zt();async function Ao(){let e=process.argv[2];if(e==="stdio"){let{runStdio:t,parseBridgeArgs:r}=await Promise.resolve().then(()=>(Rn(),In));await t(r(process.argv.slice(3)))}else if(e==="setup"){let{runSetup:t}=await Promise.resolve().then(()=>(dr(),fr));process.exitCode=await t(process.argv.slice(3))}else if(e==="help"||e==="--help"||e==="-h"){let{setupHelp:t}=await Promise.resolve().then(()=>(dr(),fr));console.log(`babtab-relay \u2014 local bridge between your AI agent and Chrome
|
|
85
86
|
|
|
86
87
|
Start the relay:
|
|
87
88
|
npx -y @babtab/relay (env: PORT=3000 BABTAB_TOKEN_FILE=./data/relay-tokens.json)
|
|
88
89
|
|
|
89
90
|
`+t())}else e!==void 0?(console.error(`Unknown command: ${e}
|
|
90
|
-
Run \`npx -y @babtab/relay help\` for usage.`),process.exitCode=1):
|
|
91
|
+
Run \`npx -y @babtab/relay help\` for usage.`),process.exitCode=1):Po()}Ao().catch(e=>{console.error(`[babtab] ${e.message}`),process.exitCode=1});function Po(){let e=Number(process.env.PORT??3e3),t=ot({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)}
|
|
91
92
|
/*! Bundled license information:
|
|
92
93
|
|
|
93
94
|
smol-toml/dist/error.js:
|
package/package.json
CHANGED