@ait-co/devtools 0.1.22 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +114 -4
- package/README.md +124 -4
- package/dist/in-app/index.d.ts +136 -0
- package/dist/in-app/index.d.ts.map +1 -0
- package/dist/in-app/index.js +163 -0
- package/dist/in-app/index.js.map +1 -0
- package/dist/mcp/cli.d.ts +20 -0
- package/dist/mcp/cli.d.ts.map +1 -0
- package/dist/mcp/cli.js +930 -0
- package/dist/mcp/cli.js.map +1 -0
- package/dist/mcp/server.d.ts +79 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +285 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/panel/index.d.ts.map +1 -1
- package/dist/panel/index.js +20 -4
- package/dist/panel/index.js.map +1 -1
- package/dist/unplugin/index.cjs +64 -20
- package/dist/unplugin/index.cjs.map +1 -1
- package/dist/unplugin/index.d.cts +11 -0
- package/dist/unplugin/index.d.cts.map +1 -1
- package/dist/unplugin/index.d.ts +11 -0
- package/dist/unplugin/index.d.ts.map +1 -1
- package/dist/unplugin/index.js +64 -20
- package/dist/unplugin/index.js.map +1 -1
- package/package.json +22 -2
package/README.en.md
CHANGED
|
@@ -13,7 +13,7 @@ Lets you develop and test Apps in Toss mini-apps in a **regular browser** — wi
|
|
|
13
13
|
- **60+ SDK API mocks** — auth, payments, IAP, location, camera, storage, and more
|
|
14
14
|
- **Device API mode system** — switch between mock / web / prompt modes for device APIs
|
|
15
15
|
- **Device simulation** — iPhone/Galaxy presets + orientation toggle to simulate a mobile viewport in your desktop browser
|
|
16
|
-
- **Floating DevTools Panel** — control SDK state in real time from the browser (
|
|
16
|
+
- **Floating DevTools Panel** — control SDK state in real time from the browser (12 tabs, mock state preset library included)
|
|
17
17
|
- **All bundlers supported** — [unplugin](https://github.com/unjs/unplugin)-based Vite, Webpack, Rspack, esbuild, and Rollup integration
|
|
18
18
|
|
|
19
19
|
Live demo: <https://devtools.aitc.dev/> (the `e2e/fixture/` from this repo deployed to GitHub Pages as a self-contained demo).
|
|
@@ -170,12 +170,14 @@ module.exports = {
|
|
|
170
170
|
| `panel` | `boolean` | `true` | Auto-inject the DevTools Panel |
|
|
171
171
|
| `forceEnable` | `boolean` | `false` | Enable devtools even in production |
|
|
172
172
|
| `mock` | `boolean` | `true` (dev) / `false` (prod+forceEnable) | Enable mock alias |
|
|
173
|
+
| `mcp` | `boolean` | `false` | Add an MCP state endpoint to the Vite dev server (Vite only — see [MCP Server](#mcp-server)) |
|
|
173
174
|
| `tunnel` | `boolean \| { port?: number; qr?: boolean }` | `false` | Expose the Vite dev server via a Cloudflare quick tunnel for real-device preview (see [below](#run-on-a-real-phone)). **Vite dev mode only** |
|
|
174
175
|
|
|
175
176
|
```ts
|
|
176
177
|
aitDevtools.vite({ panel: false }); // mock only, no panel
|
|
177
178
|
aitDevtools.vite({ forceEnable: true }); // enable in production (mock OFF by default, panel ON)
|
|
178
179
|
aitDevtools.vite({ forceEnable: true, mock: true }); // enable mock in production too
|
|
180
|
+
aitDevtools.vite({ mcp: true }); // enable MCP endpoint for AI agents
|
|
179
181
|
aitDevtools.vite({ tunnel: true }); // expose dev server at *.trycloudflare.com
|
|
180
182
|
```
|
|
181
183
|
|
|
@@ -336,7 +338,7 @@ Camera and album APIs return dummy images in mock mode.
|
|
|
336
338
|
|
|
337
339
|
When using the plugin, the panel is auto-injected into your entry point file. Click the **'AIT' button** in the bottom-right corner of the screen to toggle it.
|
|
338
340
|
|
|
339
|
-
###
|
|
341
|
+
### 12 tabs
|
|
340
342
|
|
|
341
343
|
| Tab | Description |
|
|
342
344
|
|---|---|
|
|
@@ -344,9 +346,11 @@ When using the plugin, the panel is auto-injected into your entry point file. Cl
|
|
|
344
346
|
| **Presets** | Apply/remove common QA scenarios (permission denied, offline, logged out, etc.) with one click. Save and delete user presets |
|
|
345
347
|
| **Viewport** | Simulate a mobile viewport using device presets (iPhone/Galaxy) + orientation toggle |
|
|
346
348
|
| **Permissions** | Control camera, photos, geolocation, clipboard, contacts, and microphone permission states (allowed/denied/notDetermined) |
|
|
349
|
+
| **Notifications** | Choose the next result of the notification-consent flow (new agreement / already agreed / rejected) |
|
|
347
350
|
| **Location** | Set latitude, longitude, and accuracy |
|
|
348
351
|
| **Device** | Switch API modes (mock/web/prompt), manage dummy images (add/remove/reset to defaults) |
|
|
349
352
|
| **IAP** | Choose the next purchase result (success/cancel/error, etc.), TossPay payment result, completed order history (last 5) |
|
|
353
|
+
| **Ads** | Trigger full-screen ad load/show and view the last ad event log |
|
|
350
354
|
| **Events** | Trigger Back/Home navigation events, toggle login state |
|
|
351
355
|
| **Analytics** | Real-time log viewer for recorded analytics events (last 30 entries, with timestamp/type/parameters) |
|
|
352
356
|
| **Storage** | View and clear items stored via the `Storage` API |
|
|
@@ -493,7 +497,7 @@ The bottom of the Viewport tab shows the currently applied values in real time:
|
|
|
493
497
|
### Known limitations
|
|
494
498
|
|
|
495
499
|
- **Body becomes the scroll container** — while the viewport is active, scrolling happens on `document.body` rather than `window`. `window.addEventListener('scroll', ...)` or `IntersectionObserver` attached to the root may behave differently from a real device. If your mini-app handles scrolling, verify it against `body` as well.
|
|
496
|
-
- **Estimated
|
|
500
|
+
- **Estimated safe area** — Galaxy S26 series is based on published spec (phone-simulator.com measurements), but safe area values are temporarily from S25 — pixel-accurate QA should be verified on a real device.
|
|
497
501
|
|
|
498
502
|
## `window.__ait` console API
|
|
499
503
|
|
|
@@ -780,7 +784,7 @@ Please file an issue: https://github.com/apps-in-toss-community/devtools/issues
|
|
|
780
784
|
5. Write tests in `src/__tests__/`
|
|
781
785
|
|
|
782
786
|
```bash
|
|
783
|
-
pnpm build # build with
|
|
787
|
+
pnpm build # build with tsdown
|
|
784
788
|
pnpm typecheck # verify type compatibility
|
|
785
789
|
pnpm test # run all tests
|
|
786
790
|
```
|
|
@@ -823,6 +827,109 @@ Since Turbopack doesn't support unplugin, use `resolveAlias` in `next.config.js`
|
|
|
823
827
|
import '@ait-co/devtools/panel';
|
|
824
828
|
```
|
|
825
829
|
|
|
830
|
+
## MCP Server
|
|
831
|
+
|
|
832
|
+
AI coding agents (Claude Code, Cursor, etc.) can observe a running mini-app directly via [MCP (Model Context Protocol)](https://modelcontextprotocol.io/). A single `devtools-mcp` binary provides two modes.
|
|
833
|
+
|
|
834
|
+
| Mode | Invocation | Target | Tools |
|
|
835
|
+
|---|---|---|---|
|
|
836
|
+
| **debug** (default) | `devtools-mcp` | Production bundle on a phone or dev browser (CDP/Chii) | console/network/page + DOM/snapshot/screenshot + `AIT.*` |
|
|
837
|
+
| **dev** | `devtools-mcp --mode=dev` | Mock state from a running Vite dev server | `AIT.*` (+ `devtools_get_mock_state` alias) |
|
|
838
|
+
|
|
839
|
+
Both modes expose the same `AIT.*` tool surface — debug mode backed by the Chii channel, dev mode by the dev server's mock-state HTTP endpoint — so an agent sees the same tools whether attached to a phone (debug) or a dev browser (dev).
|
|
840
|
+
|
|
841
|
+
### Debug mode (CDP via Chii)
|
|
842
|
+
|
|
843
|
+
> Read-only tools only. The phone attach roundtrip requires a real-device dog-food step and is deferred to a later phase; the tool layer is CI-verified via mockable injectable CDP connection / AIT source.
|
|
844
|
+
|
|
845
|
+
Running `devtools-mcp` as a stdio server starts a local Chii relay on `:9100` and opens a cloudflared quick tunnel, printing a public `wss://*.trycloudflare.com` URL, a QR code, and a secret token in the terminal. When the phone enters the dogfood entry point, the in-app attach UI connects to the relay with that URL and token, and the agent reads console/network/page state via `chrome-devtools-mcp`-compatible tools — diagnosing regressions without anyone watching the phone.
|
|
846
|
+
|
|
847
|
+
```json
|
|
848
|
+
{
|
|
849
|
+
"mcpServers": {
|
|
850
|
+
"ait-debug": {
|
|
851
|
+
"command": "pnpm",
|
|
852
|
+
"args": ["exec", "devtools-mcp"]
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
| Tool | CDP / AIT backing | Description |
|
|
859
|
+
|---|---|---|
|
|
860
|
+
| `list_console_messages` | `Runtime.consoleAPICalled` | Recent console.log/warn/error messages (level, text, timestamp, args) |
|
|
861
|
+
| `list_network_requests` | `Network.requestWillBeSent` + `responseReceived` | Recent XHR/fetch requests (url, method, status, timing) |
|
|
862
|
+
| `list_pages` | Chii relay target list | Attached pages + tunnel status + wss URL |
|
|
863
|
+
| `get_dom_document` | `DOM.getDocument` | DOM tree read (structural/layout regression diagnosis) |
|
|
864
|
+
| `take_snapshot` | `DOMSnapshot.captureSnapshot` | Page snapshot (documents + interned strings, visual regression) |
|
|
865
|
+
| `take_screenshot` | `Page.captureScreenshot` | Page PNG screenshot (returned as an MCP image content block) |
|
|
866
|
+
| `AIT.getSdkCallHistory` | AIT domain | SDK call trace (method, args, result/error, timestamp) |
|
|
867
|
+
| `AIT.getMockState` | AIT domain | Mock state snapshot (`window.__ait`) |
|
|
868
|
+
| `AIT.getOperationalEnvironment` | AIT domain | `getOperationalEnvironment()` + SDK version |
|
|
869
|
+
|
|
870
|
+
`AIT.*` covers what raw CDP cannot; the same MCP server forwards it alongside CDP. In debug mode the in-app side answers over the Chii channel (phone integration is a later phase).
|
|
871
|
+
|
|
872
|
+
### Dev mode (mock state)
|
|
873
|
+
|
|
874
|
+
`devtools-mcp --mode=dev` reads the mock state from a running browser. Phase 3 aligned it on the same `AIT.*` tool surface as debug mode.
|
|
875
|
+
|
|
876
|
+
#### Architecture
|
|
877
|
+
|
|
878
|
+
```
|
|
879
|
+
Browser (aitState)
|
|
880
|
+
└─ POST /api/ait-devtools/state (auto-pushed by the panel on every state change)
|
|
881
|
+
└─ Vite dev server (unplugin with mcp: true)
|
|
882
|
+
└─ GET /api/ait-devtools/state
|
|
883
|
+
└─ MCP stdio server (dist/mcp/server.js)
|
|
884
|
+
└─ AI agent (AIT.getMockState tool)
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
#### Setup
|
|
888
|
+
|
|
889
|
+
**1. Add `mcp: true` to the Vite plugin**
|
|
890
|
+
|
|
891
|
+
```ts
|
|
892
|
+
// vite.config.ts
|
|
893
|
+
import aitDevtools from '@ait-co/devtools/unplugin';
|
|
894
|
+
|
|
895
|
+
export default {
|
|
896
|
+
plugins: [aitDevtools.vite({ mcp: true })],
|
|
897
|
+
};
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
**2. Configure your MCP client (e.g. Claude Code `.claude/settings.json`)**
|
|
901
|
+
|
|
902
|
+
```json
|
|
903
|
+
{
|
|
904
|
+
"mcpServers": {
|
|
905
|
+
"ait-devtools": {
|
|
906
|
+
"command": "pnpm",
|
|
907
|
+
"args": ["exec", "devtools-mcp", "--mode=dev"],
|
|
908
|
+
"env": {
|
|
909
|
+
"AIT_DEVTOOLS_URL": "http://localhost:5173"
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
`AIT_DEVTOOLS_URL` defaults to `http://localhost:5173` — you can omit it if you're using the default port.
|
|
917
|
+
|
|
918
|
+
**3. Open the app in your browser, then call the tool from your AI agent**
|
|
919
|
+
|
|
920
|
+
```
|
|
921
|
+
> AIT.getMockState
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
Returns the full current mock state (permissions, location, auth, network, IAP, etc.) as JSON.
|
|
925
|
+
|
|
926
|
+
| Tool | Description |
|
|
927
|
+
|---|---|
|
|
928
|
+
| `AIT.getMockState` | Returns the current `AitDevtoolsState` snapshot (read-only) |
|
|
929
|
+
| `AIT.getOperationalEnvironment` | Environment + version derived from the mock state's `environment` + `appVersion` |
|
|
930
|
+
| `AIT.getSdkCallHistory` | Empty in dev mode (the HTTP endpoint records no trace) |
|
|
931
|
+
| `devtools_get_mock_state` | Backward-compatible alias of `AIT.getMockState` (prefer `AIT.getMockState` in new configs) |
|
|
932
|
+
|
|
826
933
|
## Package export structure
|
|
827
934
|
|
|
828
935
|
| Import path | Purpose |
|
|
@@ -830,6 +937,9 @@ import '@ait-co/devtools/panel';
|
|
|
830
937
|
| `@ait-co/devtools` or `@ait-co/devtools/mock` | All mock exports (bundler alias target) |
|
|
831
938
|
| `@ait-co/devtools/panel` | Floating DevTools Panel (auto-mounts on import) |
|
|
832
939
|
| `@ait-co/devtools/unplugin` | Bundler plugin (.vite, .webpack, .rspack, .esbuild, .rollup) |
|
|
940
|
+
| `@ait-co/devtools/mcp/server` | Dev-mode MCP stdio server function (Node.js) |
|
|
941
|
+
| `@ait-co/devtools/mcp/cli` | `devtools-mcp` bin entry point (debug / dev mode, Node.js) |
|
|
942
|
+
| `@ait-co/devtools/in-app` | In-app debug attach — 3-layer gate + Chii target.js injection (dogfood builds only; active when `__DEBUG_BUILD__=true`) |
|
|
833
943
|
|
|
834
944
|
## Telemetry
|
|
835
945
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- **60+ SDK API mock** — 인증, 결제, IAP, 위치, 카메라, 스토리지 등
|
|
14
14
|
- **Device API 모드 시스템** — mock / web / prompt 세 가지 모드로 디바이스 API 동작 전환
|
|
15
15
|
- **Device simulation** — iPhone/Galaxy 프리셋 + orientation 토글로 데스크탑 브라우저에서 모바일 뷰포트 시뮬레이션
|
|
16
|
-
- **Floating DevTools Panel** — 브라우저에서 SDK 상태를 실시간으로 제어 (
|
|
16
|
+
- **Floating DevTools Panel** — 브라우저에서 SDK 상태를 실시간으로 제어 (12개 탭, mock state preset library 포함)
|
|
17
17
|
- **모든 번들러 지원** — [unplugin](https://github.com/unjs/unplugin) 기반 Vite, Webpack, Rspack, esbuild, Rollup 통합
|
|
18
18
|
|
|
19
19
|
라이브 데모: <https://devtools.aitc.dev/> (이 repo의 `e2e/fixture/`를 GitHub Pages에 그대로 배포한 self-contained 데모).
|
|
@@ -170,12 +170,14 @@ module.exports = {
|
|
|
170
170
|
| `panel` | `boolean` | `true` | DevTools Panel 자동 주입 여부 |
|
|
171
171
|
| `forceEnable` | `boolean` | `false` | production에서도 devtools 활성화 |
|
|
172
172
|
| `mock` | `boolean` | `true` (dev) / `false` (prod+forceEnable) | mock alias 활성화 여부 |
|
|
173
|
+
| `mcp` | `boolean` | `false` | Vite dev server에 MCP state endpoint 추가 (Vite 전용, [MCP 섹션](#mcp-server) 참조) |
|
|
173
174
|
| `tunnel` | `boolean \| { port?: number; qr?: boolean }` | `false` | Vite dev 서버를 Cloudflare quick tunnel로 노출 (실기기 미리보기, [아래](#run-on-a-real-phone-실기기-미리보기) 참고). **Vite dev 모드 전용** |
|
|
174
175
|
|
|
175
176
|
```ts
|
|
176
177
|
aitDevtools.vite({ panel: false }); // Panel 없이 mock만 사용
|
|
177
178
|
aitDevtools.vite({ forceEnable: true }); // production에서도 활성화 (mock 기본 OFF, panel ON)
|
|
178
179
|
aitDevtools.vite({ forceEnable: true, mock: true }); // production에서 mock도 활성화
|
|
180
|
+
aitDevtools.vite({ mcp: true }); // AI 에이전트용 MCP endpoint 활성화
|
|
179
181
|
aitDevtools.vite({ tunnel: true }); // dev 서버를 *.trycloudflare.com으로 노출
|
|
180
182
|
```
|
|
181
183
|
|
|
@@ -336,7 +338,7 @@ mock 모드에서 카메라/앨범 API는 더미 이미지를 반환합니다.
|
|
|
336
338
|
|
|
337
339
|
플러그인 사용 시 진입점 파일에 패널이 자동 주입됩니다. 화면 우하단의 **'AIT' 버튼**을 클릭하면 토글됩니다.
|
|
338
340
|
|
|
339
|
-
###
|
|
341
|
+
### 12개 탭
|
|
340
342
|
|
|
341
343
|
| 탭 | 설명 |
|
|
342
344
|
|---|---|
|
|
@@ -344,9 +346,11 @@ mock 모드에서 카메라/앨범 API는 더미 이미지를 반환합니다.
|
|
|
344
346
|
| **Presets** | 자주 쓰는 QA 시나리오(권한 거부, offline, 미로그인 등)를 한 클릭으로 적용/해제. 사용자 preset 저장/삭제 가능 |
|
|
345
347
|
| **Viewport** | 디바이스 프리셋(iPhone/Galaxy) + orientation 토글로 모바일 뷰포트 시뮬레이션 |
|
|
346
348
|
| **Permissions** | camera, photos, geolocation, clipboard, contacts, microphone 권한 상태 제어 (allowed/denied/notDetermined) |
|
|
349
|
+
| **Notifications** | 알림 동의 흐름의 다음 결과 선택 (신규 동의 / 이미 동의함 / 거부) |
|
|
347
350
|
| **Location** | 위도, 경도, 정확도 설정 |
|
|
348
351
|
| **Device** | API 모드 전환 (mock/web/prompt), 더미 이미지 관리 (추가/제거/기본값/초기화) |
|
|
349
352
|
| **IAP** | 다음 구매 결과 선택 (success/취소/에러 등), TossPay 결제 결과, 완료된 주문 내역 (최근 5건) |
|
|
353
|
+
| **Ads** | 전면 광고 load/show 트리거 및 마지막 광고 이벤트 로그 |
|
|
350
354
|
| **Events** | Back/Home 네비게이션 이벤트 트리거, 로그인 상태 토글 |
|
|
351
355
|
| **Analytics** | 기록된 분석 이벤트 실시간 로그 뷰어 (최근 30건, 타임스탬프/타입/파라미터) |
|
|
352
356
|
| **Storage** | `Storage` API로 저장된 항목 조회 및 초기화 |
|
|
@@ -493,7 +497,7 @@ Viewport 탭 하단에 현재 적용된 값을 실시간으로 보여줍니다:
|
|
|
493
497
|
### Known limitations
|
|
494
498
|
|
|
495
499
|
- **Body가 스크롤 컨테이너가 됩니다** — 뷰포트 활성화 중에는 스크롤이 `window`가 아닌 `document.body`에서 발생합니다. `window.addEventListener('scroll', ...)`나 root에 붙은 `IntersectionObserver`는 실 디바이스와 다른 동작을 보일 수 있습니다. 미니앱 코드에서 스크롤을 다룬다면 `body`도 함께 검증하세요.
|
|
496
|
-
- **추정
|
|
500
|
+
- **추정 safe area** — Galaxy S26 시리즈는 출시 spec(phone-simulator.com 측정치) 기반이지만 safe area는 S25 값을 잠정 사용합니다 — 픽셀 단위 정확도가 필요한 QA는 실 기기 확인을 권장합니다.
|
|
497
501
|
|
|
498
502
|
## `window.__ait` 콘솔 API
|
|
499
503
|
|
|
@@ -780,7 +784,7 @@ Please file an issue: https://github.com/apps-in-toss-community/devtools/issues
|
|
|
780
784
|
5. `src/__tests/`에 테스트 작성
|
|
781
785
|
|
|
782
786
|
```bash
|
|
783
|
-
pnpm build #
|
|
787
|
+
pnpm build # tsdown으로 빌드
|
|
784
788
|
pnpm typecheck # 타입 호환성 검증
|
|
785
789
|
pnpm test # 전체 테스트 실행
|
|
786
790
|
```
|
|
@@ -823,6 +827,119 @@ Turbopack은 unplugin을 지원하지 않으므로, `next.config.js`에서 `reso
|
|
|
823
827
|
import '@ait-co/devtools/panel';
|
|
824
828
|
```
|
|
825
829
|
|
|
830
|
+
## MCP Server
|
|
831
|
+
|
|
832
|
+
AI 코딩 에이전트(Claude Code, Cursor 등)가 [MCP(Model Context Protocol)](https://modelcontextprotocol.io/)를
|
|
833
|
+
통해 실행 중인 미니앱을 직접 관측할 수 있습니다. 단일 `devtools-mcp` bin이 두 모드를 제공합니다.
|
|
834
|
+
|
|
835
|
+
| 모드 | 호출 | 대상 | tool |
|
|
836
|
+
|---|---|---|---|
|
|
837
|
+
| **debug** (기본값) | `devtools-mcp` | 폰 안 production 번들 또는 dev 브라우저 (CDP/Chii) | console/network/page + DOM/snapshot/screenshot + `AIT.*` |
|
|
838
|
+
| **dev** | `devtools-mcp --mode=dev` | 실행 중인 Vite dev server의 mock state | `AIT.*` (+ `devtools_get_mock_state` alias) |
|
|
839
|
+
|
|
840
|
+
두 모드는 같은 `AIT.*` tool surface를 노출합니다 — debug 모드는 Chii 채널로, dev 모드는 dev server의
|
|
841
|
+
mock-state HTTP endpoint로 백킹되어, 에이전트가 폰(debug)에 붙든 dev 브라우저(dev)에 붙든 동일한
|
|
842
|
+
tool을 봅니다.
|
|
843
|
+
|
|
844
|
+
### Debug 모드 (CDP via Chii)
|
|
845
|
+
|
|
846
|
+
> read-only tool만 노출합니다. 폰 attach 라운드트립은 실기기 dog-food가 필요해 후속 phase로 분리되어
|
|
847
|
+
> 있고, tool 계층은 주입 가능한 CDP 연결 / AIT 소스를 mock해 CI에서 검증됩니다.
|
|
848
|
+
|
|
849
|
+
`devtools-mcp`를 stdio로 실행하면 로컬 Chii 릴레이(:9100)를 띄우고 cloudflared quick tunnel로
|
|
850
|
+
공개 `wss://*.trycloudflare.com` URL을 발급한 뒤 QR + secret token을 터미널에 출력합니다.
|
|
851
|
+
폰이 dogfood 진입 시 in-app attach UI가 그 URL + token으로 릴레이에 붙으면, 에이전트가
|
|
852
|
+
`chrome-devtools-mcp` 호환 tool로 console/network/page 상태를 read합니다. 사람이 폰을 지켜볼
|
|
853
|
+
필요 없이 회귀를 단독 진단하는 것이 목표입니다.
|
|
854
|
+
|
|
855
|
+
```json
|
|
856
|
+
{
|
|
857
|
+
"mcpServers": {
|
|
858
|
+
"ait-debug": {
|
|
859
|
+
"command": "pnpm",
|
|
860
|
+
"args": ["exec", "devtools-mcp"]
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
| Tool | CDP / AIT 백킹 | 설명 |
|
|
867
|
+
|---|---|---|
|
|
868
|
+
| `list_console_messages` | `Runtime.consoleAPICalled` | 최근 console.log/warn/error 메시지 (level, text, timestamp, args) |
|
|
869
|
+
| `list_network_requests` | `Network.requestWillBeSent` + `responseReceived` | 최근 XHR/fetch 요청 (url, method, status, timing) |
|
|
870
|
+
| `list_pages` | Chii 릴레이 target 목록 | attach된 페이지 + tunnel 상태 + wss URL |
|
|
871
|
+
| `get_dom_document` | `DOM.getDocument` | DOM 트리 read (구조/레이아웃 회귀 진단) |
|
|
872
|
+
| `take_snapshot` | `DOMSnapshot.captureSnapshot` | 페이지 스냅샷 (documents + interned strings, 시각 회귀 진단) |
|
|
873
|
+
| `take_screenshot` | `Page.captureScreenshot` | 페이지 PNG 스크린샷 (MCP image content block 반환) |
|
|
874
|
+
| `AIT.getSdkCallHistory` | AIT 도메인 | SDK 호출 trace (method, args, result/error, timestamp) |
|
|
875
|
+
| `AIT.getMockState` | AIT 도메인 | mock state 스냅샷 (`window.__ait`) |
|
|
876
|
+
| `AIT.getOperationalEnvironment` | AIT 도메인 | `getOperationalEnvironment()` + SDK 버전 |
|
|
877
|
+
|
|
878
|
+
`AIT.*`는 raw CDP가 못 잡는 영역으로, 같은 MCP server가 CDP와 함께 forward합니다. debug 모드에서는
|
|
879
|
+
in-app 측이 Chii 채널로 응답합니다(폰 통합은 후속 phase).
|
|
880
|
+
|
|
881
|
+
### Dev 모드 (mock state)
|
|
882
|
+
|
|
883
|
+
`devtools-mcp --mode=dev`는 실행 중인 브라우저의 mock state를 읽습니다. Phase 3에서 debug 모드와
|
|
884
|
+
같은 `AIT.*` tool surface로 정렬되었습니다.
|
|
885
|
+
|
|
886
|
+
#### 구조
|
|
887
|
+
|
|
888
|
+
```
|
|
889
|
+
브라우저 (aitState)
|
|
890
|
+
└─ POST /api/ait-devtools/state (panel이 state 변경 시 자동 push)
|
|
891
|
+
└─ Vite dev server (unplugin mcp: true 로 등록)
|
|
892
|
+
└─ GET /api/ait-devtools/state
|
|
893
|
+
└─ MCP stdio server (dist/mcp/server.js)
|
|
894
|
+
└─ AI 에이전트 (AIT.getMockState tool)
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
#### 설정
|
|
898
|
+
|
|
899
|
+
**1. Vite 플러그인에 `mcp: true` 추가**
|
|
900
|
+
|
|
901
|
+
```ts
|
|
902
|
+
// vite.config.ts
|
|
903
|
+
import aitDevtools from '@ait-co/devtools/unplugin';
|
|
904
|
+
|
|
905
|
+
export default {
|
|
906
|
+
plugins: [aitDevtools.vite({ mcp: true })],
|
|
907
|
+
};
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
**2. MCP 클라이언트 설정 (예: Claude Code `.claude/settings.json`)**
|
|
911
|
+
|
|
912
|
+
```json
|
|
913
|
+
{
|
|
914
|
+
"mcpServers": {
|
|
915
|
+
"ait-devtools": {
|
|
916
|
+
"command": "pnpm",
|
|
917
|
+
"args": ["exec", "devtools-mcp", "--mode=dev"],
|
|
918
|
+
"env": {
|
|
919
|
+
"AIT_DEVTOOLS_URL": "http://localhost:5173"
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
`AIT_DEVTOOLS_URL`은 기본값이 `http://localhost:5173`이므로 기본 포트를 쓰면 생략 가능합니다.
|
|
927
|
+
|
|
928
|
+
**3. 앱을 브라우저에서 열고, AI 에이전트에서 tool 호출**
|
|
929
|
+
|
|
930
|
+
```
|
|
931
|
+
> AIT.getMockState
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
현재 mock state 전체(권한, 위치, 인증, 네트워크, IAP 등)를 JSON으로 반환합니다.
|
|
935
|
+
|
|
936
|
+
| Tool | 설명 |
|
|
937
|
+
|---|---|
|
|
938
|
+
| `AIT.getMockState` | 현재 `AitDevtoolsState` 스냅샷 반환 (read-only) |
|
|
939
|
+
| `AIT.getOperationalEnvironment` | mock state의 `environment` + `appVersion` 기반 환경/버전 |
|
|
940
|
+
| `AIT.getSdkCallHistory` | dev 모드에서는 빈 목록 (HTTP endpoint가 trace를 기록하지 않음) |
|
|
941
|
+
| `devtools_get_mock_state` | `AIT.getMockState`의 하위호환 alias (신규 설정은 `AIT.getMockState` 권장) |
|
|
942
|
+
|
|
826
943
|
## 패키지 Export 구조
|
|
827
944
|
|
|
828
945
|
| Import path | 용도 |
|
|
@@ -830,6 +947,9 @@ import '@ait-co/devtools/panel';
|
|
|
830
947
|
| `@ait-co/devtools` 또는 `@ait-co/devtools/mock` | 모든 mock export (번들러 alias 대상) |
|
|
831
948
|
| `@ait-co/devtools/panel` | Floating DevTools Panel (import 시 자동 마운트) |
|
|
832
949
|
| `@ait-co/devtools/unplugin` | 번들러 플러그인 (.vite, .webpack, .rspack, .esbuild, .rollup) |
|
|
950
|
+
| `@ait-co/devtools/mcp/server` | dev-mode MCP stdio server 함수 (Node.js) |
|
|
951
|
+
| `@ait-co/devtools/mcp/cli` | `devtools-mcp` bin 진입점 (debug / dev 모드, Node.js) |
|
|
952
|
+
| `@ait-co/devtools/in-app` | In-app debug attach — 3-layer gate + Chii target.js 주입 (dogfood 빌드 전용, `__DEBUG_BUILD__=true` 시에만 활성) |
|
|
833
953
|
|
|
834
954
|
## 텔레메트리
|
|
835
955
|
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
//#region src/in-app/gate.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* 3-layer activation gate for the in-app debug surface.
|
|
4
|
+
*
|
|
5
|
+
* Spec: docs/superpowers/specs/2026-05-18-in-app-debug-mcp.md
|
|
6
|
+
* "3-layer activation gate" — Phase 1 implementation (gate logic only).
|
|
7
|
+
* Chii client, WebSocket transport, and QR UI are later phases.
|
|
8
|
+
*
|
|
9
|
+
* Decision matrix:
|
|
10
|
+
*
|
|
11
|
+
* build channel | _deploymentId | debug=1 | result
|
|
12
|
+
* release | (any) | (any) | BLOCKED (Layer A — code absent via DCE)
|
|
13
|
+
* dogfood | absent | (any) | BLOCKED (Layer B — entry gate)
|
|
14
|
+
* dogfood | present | absent | BLOCKED (Layer C — opt-in gate)
|
|
15
|
+
* dogfood | present | present | ATTACH
|
|
16
|
+
*/
|
|
17
|
+
/** Shape returned when the gate allows attachment. */
|
|
18
|
+
interface GateResultAttach {
|
|
19
|
+
readonly attach: true;
|
|
20
|
+
/** The validated `wss:` relay URL from the `relay` query param. */
|
|
21
|
+
readonly relayUrl: string;
|
|
22
|
+
/** The deployment ID extracted from the `_deploymentId` query param. */
|
|
23
|
+
readonly deploymentId: string;
|
|
24
|
+
}
|
|
25
|
+
/** Shape returned when the gate blocks attachment, with a reason code. */
|
|
26
|
+
interface GateResultBlocked {
|
|
27
|
+
readonly attach: false;
|
|
28
|
+
/**
|
|
29
|
+
* - `'build'` Layer A: `__DEBUG_BUILD__` is false (release build).
|
|
30
|
+
* - `'entry'` Layer B: `_deploymentId` param is absent or empty.
|
|
31
|
+
* - `'opt-in'` Layer C: `debug=1` param is absent.
|
|
32
|
+
* - `'invalid-relay'` Layer C: `relay` param is absent, empty, or not a `wss:` URL.
|
|
33
|
+
*/
|
|
34
|
+
readonly reason: 'build' | 'entry' | 'opt-in' | 'invalid-relay';
|
|
35
|
+
}
|
|
36
|
+
type GateResult = GateResultAttach | GateResultBlocked;
|
|
37
|
+
/**
|
|
38
|
+
* Input for {@link evaluateDebugGate}.
|
|
39
|
+
*
|
|
40
|
+
* Keeping each field explicit makes the function trivially testable without
|
|
41
|
+
* needing to manipulate `window.location`.
|
|
42
|
+
*/
|
|
43
|
+
interface GateInput {
|
|
44
|
+
/**
|
|
45
|
+
* Whether this is a debug build. Corresponds to the `__DEBUG_BUILD__`
|
|
46
|
+
* compile-time constant injected by tsdown.
|
|
47
|
+
*
|
|
48
|
+
* In source code consumed via `@ait-co/devtools/in-app`, the thin
|
|
49
|
+
* `src/in-app/index.ts` entry reads `__DEBUG_BUILD__` and passes it here.
|
|
50
|
+
* Tests supply it directly.
|
|
51
|
+
*/
|
|
52
|
+
readonly isDebugBuild: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* The URL search params to inspect for gate signals.
|
|
55
|
+
*
|
|
56
|
+
* Prefer `URLSearchParams` so callers can pass `new URLSearchParams(location.search)`
|
|
57
|
+
* without coupling the pure function to `window`.
|
|
58
|
+
*
|
|
59
|
+
* Layer B open seam (spec open question 2): if the Toss SDK ever exposes
|
|
60
|
+
* `getEntryScheme()` or a similar API that reliably signals a dogfood entry,
|
|
61
|
+
* that signal should be checked before `_deploymentId` here. For now only the
|
|
62
|
+
* `_deploymentId` query param fallback is implemented. Pass a custom
|
|
63
|
+
* `URLSearchParams` to inject the SDK signal at the call site without
|
|
64
|
+
* modifying this function.
|
|
65
|
+
*/
|
|
66
|
+
readonly searchParams: URLSearchParams;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Pure function that evaluates the 3-layer debug activation gate.
|
|
70
|
+
*
|
|
71
|
+
* Has no side effects. All inputs are explicit. Returns a discriminated union
|
|
72
|
+
* so callers can pattern-match on `result.attach`.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const result = evaluateDebugGate({
|
|
77
|
+
* isDebugBuild: __DEBUG_BUILD__,
|
|
78
|
+
* searchParams: new URLSearchParams(window.location.search),
|
|
79
|
+
* });
|
|
80
|
+
* if (result.attach) {
|
|
81
|
+
* // Proceed to load Chii client
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
declare function evaluateDebugGate(input: GateInput): GateResult;
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/in-app/attach.d.ts
|
|
88
|
+
/**
|
|
89
|
+
* Converts a validated `wss:` relay URL into the Chii `target.js` script URL.
|
|
90
|
+
*
|
|
91
|
+
* Scheme is mapped `wss:` → `https:`. Host and port are preserved.
|
|
92
|
+
* Pathname is set to `/target.js` regardless of the relay path.
|
|
93
|
+
* Query params and hash from the relay URL are dropped — the target script
|
|
94
|
+
* URL is a static asset path on the same host.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* deriveTargetScriptUrl('wss://abc.trycloudflare.com/relay')
|
|
98
|
+
* // → 'https://abc.trycloudflare.com/target.js'
|
|
99
|
+
*
|
|
100
|
+
* deriveTargetScriptUrl('wss://h.example.com:9100/')
|
|
101
|
+
* // → 'https://h.example.com:9100/target.js'
|
|
102
|
+
*/
|
|
103
|
+
declare function deriveTargetScriptUrl(relayUrl: string): string;
|
|
104
|
+
/**
|
|
105
|
+
* Evaluates the 3-layer debug gate and, if the gate passes, injects the Chii
|
|
106
|
+
* `target.js` script into `document.head`.
|
|
107
|
+
*
|
|
108
|
+
* Idempotent — calling more than once is safe. The second call is a no-op if
|
|
109
|
+
* a script with the same `src` is already present in the document, and the
|
|
110
|
+
* module-level `attached` flag prevents redundant DOM queries after the first
|
|
111
|
+
* successful injection.
|
|
112
|
+
*
|
|
113
|
+
* Safe to call even if `document` is somehow unavailable (defensive boundary
|
|
114
|
+
* guard — in practice this always runs in a real WebView).
|
|
115
|
+
*
|
|
116
|
+
* @param gateResult - Optional pre-evaluated gate result for testability.
|
|
117
|
+
* Defaults to `checkDebugGate()` which reads the current page URL and the
|
|
118
|
+
* `__DEBUG_BUILD__` compile-time constant. Passing a custom value avoids
|
|
119
|
+
* the need to manipulate `window.location` in tests.
|
|
120
|
+
*/
|
|
121
|
+
declare function maybeAttach(gateResult?: GateResult): void;
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/in-app/index.d.ts
|
|
124
|
+
/**
|
|
125
|
+
* Evaluates the 3-layer debug activation gate against the current page URL.
|
|
126
|
+
*
|
|
127
|
+
* Returns the gate result. Callers can check `result.attach` to decide whether
|
|
128
|
+
* to proceed with debug surface attachment.
|
|
129
|
+
*
|
|
130
|
+
* This function reads `window.location` and the `__DEBUG_BUILD__` compile-time
|
|
131
|
+
* constant. It has no other side effects.
|
|
132
|
+
*/
|
|
133
|
+
declare function checkDebugGate(): GateResult;
|
|
134
|
+
//#endregion
|
|
135
|
+
export { type GateInput, type GateResult, type GateResultAttach, type GateResultBlocked, checkDebugGate, deriveTargetScriptUrl, evaluateDebugGate, maybeAttach };
|
|
136
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/in-app/gate.ts","../../src/in-app/attach.ts","../../src/in-app/index.ts"],"mappings":";;AAiBA;;;;;;;;;AASA;;;;;AAWA;AAAA,UApBiB,gBAAA;EAAA,SACN,MAAA;EAmBc;EAAA,SAjBd,QAAA;EAyBM;EAAA,SAvBN,YAAA;AAAA;;UAIM,iBAAA;EAAA,SACN,MAAA;EA0Cc;;;AAoBzB;;;EApByB,SAnCd,MAAA;AAAA;AAAA,KAGC,UAAA,GAAa,gBAAA,GAAmB,iBAAA;;;;;;;UAQ3B,SAAA;EChBoB;;;;AA6BrC;;;;EA7BqC,SDyB1B,YAAA;;;;AEzBX;;;;;;;;;;WFwCW,YAAA,EAAc,eAAA;AAAA;;;;;;;;;;;;;;;;;;iBAoBT,iBAAA,CAAkB,KAAA,EAAO,SAAA,GAAY,UAAA;;;;;;AApDrD;;;;;AAQA;;;;;;;iBChBgB,qBAAA,CAAsB,QAAA;;AD4DtC;;;;;;;;;;;;AC5DA;;;;iBA6BgB,WAAA,CAAY,UAAA,GAAY,UAAA;;;;;;ADbxC;;;;;;iBEhBgB,cAAA,CAAA,GAAkB,UAAA"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
//#region src/in-app/gate.ts
|
|
2
|
+
/**
|
|
3
|
+
* Pure function that evaluates the 3-layer debug activation gate.
|
|
4
|
+
*
|
|
5
|
+
* Has no side effects. All inputs are explicit. Returns a discriminated union
|
|
6
|
+
* so callers can pattern-match on `result.attach`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const result = evaluateDebugGate({
|
|
11
|
+
* isDebugBuild: __DEBUG_BUILD__,
|
|
12
|
+
* searchParams: new URLSearchParams(window.location.search),
|
|
13
|
+
* });
|
|
14
|
+
* if (result.attach) {
|
|
15
|
+
* // Proceed to load Chii client
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
function evaluateDebugGate(input) {
|
|
20
|
+
if (!input.isDebugBuild) return {
|
|
21
|
+
attach: false,
|
|
22
|
+
reason: "build"
|
|
23
|
+
};
|
|
24
|
+
const deploymentId = input.searchParams.get("_deploymentId") ?? "";
|
|
25
|
+
if (deploymentId === "") return {
|
|
26
|
+
attach: false,
|
|
27
|
+
reason: "entry"
|
|
28
|
+
};
|
|
29
|
+
if (input.searchParams.get("debug") !== "1") return {
|
|
30
|
+
attach: false,
|
|
31
|
+
reason: "opt-in"
|
|
32
|
+
};
|
|
33
|
+
const relayRaw = input.searchParams.get("relay") ?? "";
|
|
34
|
+
if (relayRaw === "") return {
|
|
35
|
+
attach: false,
|
|
36
|
+
reason: "invalid-relay"
|
|
37
|
+
};
|
|
38
|
+
let relayUrl;
|
|
39
|
+
try {
|
|
40
|
+
relayUrl = new URL(relayRaw);
|
|
41
|
+
} catch {
|
|
42
|
+
return {
|
|
43
|
+
attach: false,
|
|
44
|
+
reason: "invalid-relay"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (relayUrl.protocol !== "wss:") return {
|
|
48
|
+
attach: false,
|
|
49
|
+
reason: "invalid-relay"
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
attach: true,
|
|
53
|
+
relayUrl: relayUrl.href,
|
|
54
|
+
deploymentId
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/in-app/attach.ts
|
|
59
|
+
/**
|
|
60
|
+
* In-app Chii target injection for the debug attach flow.
|
|
61
|
+
*
|
|
62
|
+
* Spec: docs/superpowers/specs/2026-05-18-in-app-debug-mcp.md
|
|
63
|
+
* "MCP attach" topology section — Phase 1 browser-side implementation.
|
|
64
|
+
*
|
|
65
|
+
* This module bridges the 3-layer gate result to a Chii `target.js` script
|
|
66
|
+
* injection. The Chii npm package is the relay SERVER — the in-app side is
|
|
67
|
+
* a plain `<script src="…/target.js">` pointing at the relay host. No chii
|
|
68
|
+
* npm dependency is needed here.
|
|
69
|
+
*/
|
|
70
|
+
/**
|
|
71
|
+
* Converts a validated `wss:` relay URL into the Chii `target.js` script URL.
|
|
72
|
+
*
|
|
73
|
+
* Scheme is mapped `wss:` → `https:`. Host and port are preserved.
|
|
74
|
+
* Pathname is set to `/target.js` regardless of the relay path.
|
|
75
|
+
* Query params and hash from the relay URL are dropped — the target script
|
|
76
|
+
* URL is a static asset path on the same host.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* deriveTargetScriptUrl('wss://abc.trycloudflare.com/relay')
|
|
80
|
+
* // → 'https://abc.trycloudflare.com/target.js'
|
|
81
|
+
*
|
|
82
|
+
* deriveTargetScriptUrl('wss://h.example.com:9100/')
|
|
83
|
+
* // → 'https://h.example.com:9100/target.js'
|
|
84
|
+
*/
|
|
85
|
+
function deriveTargetScriptUrl(relayUrl) {
|
|
86
|
+
const u = new URL(relayUrl);
|
|
87
|
+
u.protocol = "https:";
|
|
88
|
+
u.pathname = "/target.js";
|
|
89
|
+
u.search = "";
|
|
90
|
+
u.hash = "";
|
|
91
|
+
return u.toString();
|
|
92
|
+
}
|
|
93
|
+
/** Module-level guard against double-injection within a page lifecycle. */
|
|
94
|
+
let attached = false;
|
|
95
|
+
/**
|
|
96
|
+
* Evaluates the 3-layer debug gate and, if the gate passes, injects the Chii
|
|
97
|
+
* `target.js` script into `document.head`.
|
|
98
|
+
*
|
|
99
|
+
* Idempotent — calling more than once is safe. The second call is a no-op if
|
|
100
|
+
* a script with the same `src` is already present in the document, and the
|
|
101
|
+
* module-level `attached` flag prevents redundant DOM queries after the first
|
|
102
|
+
* successful injection.
|
|
103
|
+
*
|
|
104
|
+
* Safe to call even if `document` is somehow unavailable (defensive boundary
|
|
105
|
+
* guard — in practice this always runs in a real WebView).
|
|
106
|
+
*
|
|
107
|
+
* @param gateResult - Optional pre-evaluated gate result for testability.
|
|
108
|
+
* Defaults to `checkDebugGate()` which reads the current page URL and the
|
|
109
|
+
* `__DEBUG_BUILD__` compile-time constant. Passing a custom value avoids
|
|
110
|
+
* the need to manipulate `window.location` in tests.
|
|
111
|
+
*/
|
|
112
|
+
function maybeAttach(gateResult = checkDebugGate()) {
|
|
113
|
+
if (!gateResult.attach) {
|
|
114
|
+
console.debug(`[@ait-co/devtools] debug attach skipped — gate blocked (reason: ${gateResult.reason})`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (attached) return;
|
|
118
|
+
if (typeof document === "undefined") return;
|
|
119
|
+
const src = deriveTargetScriptUrl(gateResult.relayUrl);
|
|
120
|
+
if (document.querySelector(`script[src="${src}"]`) !== null) {
|
|
121
|
+
attached = true;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const script = document.createElement("script");
|
|
125
|
+
script.src = src;
|
|
126
|
+
script.async = true;
|
|
127
|
+
(document.head ?? document.documentElement).appendChild(script);
|
|
128
|
+
attached = true;
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/in-app/index.ts
|
|
132
|
+
/**
|
|
133
|
+
* @ait-co/devtools/in-app entry point.
|
|
134
|
+
*
|
|
135
|
+
* Spec: docs/superpowers/specs/2026-05-18-in-app-debug-mcp.md
|
|
136
|
+
*
|
|
137
|
+
* Phase 1 — gate + browser-side Chii target injection.
|
|
138
|
+
* WebSocket relay, QR/paste UI, and AI-host MCP bin are later phases that
|
|
139
|
+
* require real-device validation and are not included here.
|
|
140
|
+
*
|
|
141
|
+
* This thin entry reads `__DEBUG_BUILD__` and `window.location`, then calls
|
|
142
|
+
* the pure {@link evaluateDebugGate} function. All testable logic lives in
|
|
143
|
+
* `./gate.ts` and `./attach.ts`, not here.
|
|
144
|
+
*/
|
|
145
|
+
/**
|
|
146
|
+
* Evaluates the 3-layer debug activation gate against the current page URL.
|
|
147
|
+
*
|
|
148
|
+
* Returns the gate result. Callers can check `result.attach` to decide whether
|
|
149
|
+
* to proceed with debug surface attachment.
|
|
150
|
+
*
|
|
151
|
+
* This function reads `window.location` and the `__DEBUG_BUILD__` compile-time
|
|
152
|
+
* constant. It has no other side effects.
|
|
153
|
+
*/
|
|
154
|
+
function checkDebugGate() {
|
|
155
|
+
return evaluateDebugGate({
|
|
156
|
+
isDebugBuild: false,
|
|
157
|
+
searchParams: new URLSearchParams(window.location.search)
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
161
|
+
export { checkDebugGate, deriveTargetScriptUrl, evaluateDebugGate, maybeAttach };
|
|
162
|
+
|
|
163
|
+
//# sourceMappingURL=index.js.map
|