@ait-co/devtools 0.1.144 → 0.2.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.
Files changed (182) hide show
  1. package/README.en.md +47 -218
  2. package/README.md +36 -246
  3. package/dist/in-app/auto.d.ts +1 -138
  4. package/dist/in-app/auto.js +28 -1102
  5. package/dist/in-app/auto.js.map +1 -1
  6. package/dist/in-app/index.d.ts +38 -547
  7. package/dist/in-app/index.d.ts.map +1 -1
  8. package/dist/in-app/index.js +62 -939
  9. package/dist/in-app/index.js.map +1 -1
  10. package/dist/mcp/cli.d.ts +1 -54
  11. package/dist/mcp/cli.js +33 -9720
  12. package/dist/mcp/cli.js.map +1 -1
  13. package/dist/mcp/server.d.ts +1 -88
  14. package/dist/mcp/server.js +36 -1076
  15. package/dist/mcp/server.js.map +1 -1
  16. package/dist/mock/index.d.ts +35 -21
  17. package/dist/mock/index.d.ts.map +1 -1
  18. package/dist/mock/index.js +81 -2
  19. package/dist/mock/index.js.map +1 -1
  20. package/dist/panel/index.js +80 -104
  21. package/dist/panel/index.js.map +1 -1
  22. package/dist/relay-url-store-CkVSQZMq.cjs +110 -0
  23. package/dist/relay-url-store-CkVSQZMq.cjs.map +1 -0
  24. package/dist/relay-url-store-dkII-DHD.js +109 -0
  25. package/dist/relay-url-store-dkII-DHD.js.map +1 -0
  26. package/dist/stubs/bin-devtools-mcp.js +58 -0
  27. package/dist/stubs/bin-devtools-mcp.js.map +1 -0
  28. package/dist/stubs/bin-devtools-test.d.ts +2 -0
  29. package/dist/stubs/bin-devtools-test.js +55 -0
  30. package/dist/stubs/bin-devtools-test.js.map +1 -0
  31. package/dist/test-runner/config.d.ts +1 -231
  32. package/dist/test-runner/config.js +41 -45
  33. package/dist/test-runner/config.js.map +1 -1
  34. package/dist/{tunnel-BGT9Curk.cjs → tunnel-BKZkOyQp.cjs} +1 -1
  35. package/dist/{tunnel-BGT9Curk.cjs.map → tunnel-BKZkOyQp.cjs.map} +1 -1
  36. package/dist/{tunnel-BOKmLzBO.js → tunnel-CqSCIrdU.js} +1 -1
  37. package/dist/{tunnel-BOKmLzBO.js.map → tunnel-CqSCIrdU.js.map} +1 -1
  38. package/dist/unplugin/index.cjs +9 -18
  39. package/dist/unplugin/index.cjs.map +1 -1
  40. package/dist/unplugin/index.d.cts +26 -5
  41. package/dist/unplugin/index.d.cts.map +1 -1
  42. package/dist/unplugin/index.d.ts +27 -6
  43. package/dist/unplugin/index.d.ts.map +1 -1
  44. package/dist/unplugin/index.js +10 -19
  45. package/dist/unplugin/index.js.map +1 -1
  46. package/package.json +10 -25
  47. package/dist/attach-orchestrator-0F0m_UqQ.js +0 -1845
  48. package/dist/attach-orchestrator-0F0m_UqQ.js.map +0 -1
  49. package/dist/attach-orchestrator-D65KxFy_.js +0 -1831
  50. package/dist/attach-orchestrator-D65KxFy_.js.map +0 -1
  51. package/dist/attach-orchestrator-DL3NQ9ca.js +0 -1846
  52. package/dist/attach-orchestrator-DL3NQ9ca.js.map +0 -1
  53. package/dist/bundle-C796JIwG.d.ts +0 -159
  54. package/dist/bundle-C796JIwG.d.ts.map +0 -1
  55. package/dist/capture-DsP525OZ.d.ts +0 -58
  56. package/dist/capture-DsP525OZ.d.ts.map +0 -1
  57. package/dist/cdp-connection-rP1WdnH5.d.ts +0 -287
  58. package/dist/cdp-connection-rP1WdnH5.d.ts.map +0 -1
  59. package/dist/cell-BaLvusOl.js +0 -68
  60. package/dist/cell-BaLvusOl.js.map +0 -1
  61. package/dist/cell-CBUS3-nT.js +0 -274
  62. package/dist/cell-CBUS3-nT.js.map +0 -1
  63. package/dist/cell-EBKKpAAT.js +0 -307
  64. package/dist/cell-EBKKpAAT.js.map +0 -1
  65. package/dist/chii-relay-B3ZhjGMi.js +0 -304
  66. package/dist/chii-relay-B3ZhjGMi.js.map +0 -1
  67. package/dist/chii-relay-CGMlePMd.cjs +0 -304
  68. package/dist/chii-relay-CGMlePMd.cjs.map +0 -1
  69. package/dist/debug-server-B3ABDrRI.js +0 -456
  70. package/dist/debug-server-B3ABDrRI.js.map +0 -1
  71. package/dist/debug-server-BWhwrVXa.js +0 -1158
  72. package/dist/debug-server-BWhwrVXa.js.map +0 -1
  73. package/dist/debug-server-CfQNxxGW.js +0 -600
  74. package/dist/debug-server-CfQNxxGW.js.map +0 -1
  75. package/dist/devtools-opener-3Drge_RJ.js +0 -75
  76. package/dist/devtools-opener-3Drge_RJ.js.map +0 -1
  77. package/dist/devtools-opener-CJpEsXXQ.js +0 -76
  78. package/dist/devtools-opener-CJpEsXXQ.js.map +0 -1
  79. package/dist/devtools-opener-CxtryS8c.js +0 -75
  80. package/dist/devtools-opener-CxtryS8c.js.map +0 -1
  81. package/dist/in-app/auto.d.ts.map +0 -1
  82. package/dist/mcp/cli.d.ts.map +0 -1
  83. package/dist/mcp/server.d.ts.map +0 -1
  84. package/dist/pool-DcaaOwUq.d.ts +0 -14761
  85. package/dist/pool-DcaaOwUq.d.ts.map +0 -1
  86. package/dist/qr-http-server-C_lqOrgc.js +0 -1644
  87. package/dist/qr-http-server-C_lqOrgc.js.map +0 -1
  88. package/dist/qr-http-server-CopuMbub.js +0 -1644
  89. package/dist/qr-http-server-CopuMbub.js.map +0 -1
  90. package/dist/qr-http-server-DrbIVDjO.js +0 -1645
  91. package/dist/qr-http-server-DrbIVDjO.js.map +0 -1
  92. package/dist/relay-factory-N9QobQxG.js +0 -206
  93. package/dist/relay-factory-N9QobQxG.js.map +0 -1
  94. package/dist/relay-secret-store-BR0YIkNv.cjs +0 -241
  95. package/dist/relay-secret-store-BR0YIkNv.cjs.map +0 -1
  96. package/dist/relay-secret-store-Bmyleu0A.js +0 -154
  97. package/dist/relay-secret-store-Bmyleu0A.js.map +0 -1
  98. package/dist/relay-secret-store-CQenfcSL.js +0 -154
  99. package/dist/relay-secret-store-CQenfcSL.js.map +0 -1
  100. package/dist/relay-secret-store-CYM8CBIF.js +0 -240
  101. package/dist/relay-secret-store-CYM8CBIF.js.map +0 -1
  102. package/dist/relay-secret-store-DKxs7zwq.js +0 -153
  103. package/dist/relay-secret-store-DKxs7zwq.js.map +0 -1
  104. package/dist/relay-secret-store-WJ8EGkIl.js +0 -153
  105. package/dist/relay-secret-store-WJ8EGkIl.js.map +0 -1
  106. package/dist/relay-url-store-BR2XodiO.js +0 -123
  107. package/dist/relay-url-store-BR2XodiO.js.map +0 -1
  108. package/dist/relay-url-store-C1as_m5G.cjs +0 -115
  109. package/dist/relay-url-store-C1as_m5G.cjs.map +0 -1
  110. package/dist/relay-url-store-CH63fVCm.js +0 -122
  111. package/dist/relay-url-store-CH63fVCm.js.map +0 -1
  112. package/dist/relay-url-store-CzFo_84F.js +0 -114
  113. package/dist/relay-url-store-CzFo_84F.js.map +0 -1
  114. package/dist/relay-url-store-DaY1QPes.js +0 -123
  115. package/dist/relay-url-store-DaY1QPes.js.map +0 -1
  116. package/dist/relay-url-store-xmUuTjXA.js +0 -122
  117. package/dist/relay-url-store-xmUuTjXA.js.map +0 -1
  118. package/dist/relay-worker-B5HKkGUY.js +0 -832
  119. package/dist/relay-worker-B5HKkGUY.js.map +0 -1
  120. package/dist/relay-worker-YdlpZQl9.d.ts +0 -214
  121. package/dist/relay-worker-YdlpZQl9.d.ts.map +0 -1
  122. package/dist/rolldown-runtime-DGkTqVfb.js +0 -15
  123. package/dist/rolldown-runtime-DUslC3ob.js +0 -14
  124. package/dist/runtime-kn9DxOeg.d.ts +0 -249
  125. package/dist/runtime-kn9DxOeg.d.ts.map +0 -1
  126. package/dist/test-runner/bin.js +0 -2584
  127. package/dist/test-runner/bin.js.map +0 -1
  128. package/dist/test-runner/bridge-stub.d.ts +0 -125
  129. package/dist/test-runner/bridge-stub.d.ts.map +0 -1
  130. package/dist/test-runner/bridge-stub.js +0 -92
  131. package/dist/test-runner/bridge-stub.js.map +0 -1
  132. package/dist/test-runner/bundle.d.ts +0 -2
  133. package/dist/test-runner/bundle.js +0 -439
  134. package/dist/test-runner/bundle.js.map +0 -1
  135. package/dist/test-runner/capture.d.ts +0 -2
  136. package/dist/test-runner/capture.js +0 -44
  137. package/dist/test-runner/capture.js.map +0 -1
  138. package/dist/test-runner/config.d.ts.map +0 -1
  139. package/dist/test-runner/method-pace.d.ts +0 -82
  140. package/dist/test-runner/method-pace.d.ts.map +0 -1
  141. package/dist/test-runner/method-pace.js +0 -120
  142. package/dist/test-runner/method-pace.js.map +0 -1
  143. package/dist/test-runner/pool.d.ts +0 -2
  144. package/dist/test-runner/pool.js +0 -136
  145. package/dist/test-runner/pool.js.map +0 -1
  146. package/dist/test-runner/relay-factory.d.ts +0 -11245
  147. package/dist/test-runner/relay-factory.d.ts.map +0 -1
  148. package/dist/test-runner/relay-factory.js +0 -206
  149. package/dist/test-runner/relay-factory.js.map +0 -1
  150. package/dist/test-runner/relay-worker.d.ts +0 -2
  151. package/dist/test-runner/relay-worker.js +0 -2
  152. package/dist/test-runner/report.d.ts +0 -163
  153. package/dist/test-runner/report.d.ts.map +0 -1
  154. package/dist/test-runner/report.js +0 -198
  155. package/dist/test-runner/report.js.map +0 -1
  156. package/dist/test-runner/rpc.d.ts +0 -56
  157. package/dist/test-runner/rpc.d.ts.map +0 -1
  158. package/dist/test-runner/rpc.js +0 -98
  159. package/dist/test-runner/rpc.js.map +0 -1
  160. package/dist/test-runner/runtime.d.ts +0 -2
  161. package/dist/test-runner/runtime.js +0 -659
  162. package/dist/test-runner/runtime.js.map +0 -1
  163. package/dist/test-runner/task-graph.d.ts +0 -38
  164. package/dist/test-runner/task-graph.d.ts.map +0 -1
  165. package/dist/test-runner/task-graph.js +0 -182
  166. package/dist/test-runner/task-graph.js.map +0 -1
  167. package/dist/throttle-DKKzX1qC.js +0 -59
  168. package/dist/throttle-DKKzX1qC.js.map +0 -1
  169. package/dist/totp-BqmCLSNA.js +0 -189
  170. package/dist/totp-BqmCLSNA.js.map +0 -1
  171. package/dist/totp-CMHR5lsW.cjs +0 -191
  172. package/dist/totp-CMHR5lsW.cjs.map +0 -1
  173. package/dist/totp-CZLLKfOC.js +0 -200
  174. package/dist/totp-CZLLKfOC.js.map +0 -1
  175. package/dist/totp-DAxys-r0.js +0 -199
  176. package/dist/totp-DAxys-r0.js.map +0 -1
  177. package/dist/totp-DfekTBk3.js +0 -211
  178. package/dist/totp-DfekTBk3.js.map +0 -1
  179. package/dist/totp-Dwft0Kz7.js +0 -3
  180. package/dist/totp-WY6l0ysP.js +0 -190
  181. package/dist/totp-WY6l0ysP.js.map +0 -1
  182. /package/dist/{test-runner/bin.d.ts → stubs/bin-devtools-mcp.d.ts} +0 -0
package/README.md CHANGED
@@ -55,10 +55,10 @@ pnpm dev:phone # AIT_TUNNEL=1 pnpm dev 와 동일
55
55
 
56
56
  **환경 3 — intoss-private** (토스 WebView, HMR X, debug 전용)
57
57
 
58
- 실기기 토스 앱 WebView에서 dog-food 번들을 로드하고 MCP relay로 디버깅합니다.
58
+ 실기기 토스 앱 WebView에서 dog-food 번들을 로드하고 MCP relay로 디버깅합니다. `@ait-co/debugger` 설치가 필요합니다 — 아래 [디버깅 패키지](#디버깅-패키지-환경-23) 참고.
59
59
 
60
60
  ```bash
61
- devtools-mcp # MCP 서버 시작 → QR 출력
61
+ npx -y -p @ait-co/debugger debugger # MCP 서버 시작 → QR 출력 (devDep이면 pnpm exec debugger)
62
62
  # ait build && ait deploy --scheme-only
63
63
  # start_attach(scheme_url) 호출 한 번으로 QR 생성 + 폰 attach까지 — QR 스캔하면 토스 앱 로드 + relay attach
64
64
  ```
@@ -73,7 +73,7 @@ HMR 없음(토스 WebView cold-load만). 상세: [`docs/scenarios/env-3.md`](./d
73
73
 
74
74
  ```ts
75
75
  // main.tsx (또는 미니앱 entry 최상단)
76
- import '@ait-co/devtools/in-app/auto';
76
+ import '@ait-co/debug-console/auto';
77
77
  ```
78
78
 
79
79
  이 한 줄이 하는 일:
@@ -85,7 +85,9 @@ import '@ait-co/devtools/in-app/auto';
85
85
 
86
86
  환경 3(intoss-private relay) 빌드는 relay QR deep-link가 `?debug=1&relay=<wss>` 파라미터를 실어 보내므로, 이 한 줄만 있으면 별도 게이트 코드가 필요 없습니다. 환경 2(PWA, `tunnel: { cdp: true }`)도 동일하게 동작합니다.
87
87
 
88
- > TOTP 인증이 필요한 dog-food 빌드는 빌드 define으로 `__DEBUG_TOTP_SECRET__`을 주입하고 `@ait-co/devtools/in-app`을 직접 import해 `evaluateDebugGate({ verifyTotpCode })` + `maybeAttach()`를 사용하세요. `in-app/auto`는 TOTP verifier주입하지 않으므로 C3 레이어가 비활성화됩니다.
88
+ 경로 `@ait-co/devtools/in-app/auto`는 0.2.x에서도 계속 resolve되지만 inert한 no-op 스텁이며 1.0.0에서 제거됩니다 import 경로로 옮기세요.
89
+
90
+ > TOTP 인증이 필요한 dog-food 빌드는 빌드 define으로 `__DEBUG_TOTP_SECRET__`을 주입하고 `@ait-co/debug-console`을 직접 import해 `evaluateDebugGate({ verifyTotpCode })` + `maybeAttach()`를 사용하세요. `in-app/auto`는 TOTP verifier를 주입하지 않으므로 C3 레이어가 비활성화됩니다.
89
91
 
90
92
  ## 자주 겪는 문제 5가지
91
93
 
@@ -99,7 +101,7 @@ relay에 붙은 페이지가 없는 상태입니다. `start_attach` → QR 스
99
101
 
100
102
  **"tunnel down" — 터널 응답 없음 또는 timeout**
101
103
 
102
- cloudflared quick tunnel은 수 시간 후 drop될 수 있습니다. `devtools-mcp` 프로세스를 재시작하면 새 tunnel URL이 발급됩니다. 재발급 후 QR을 다시 스캔하세요. (관련: [#290](https://github.com/apps-in-toss-community/devtools/issues/290))
104
+ cloudflared quick tunnel은 수 시간 후 drop될 수 있습니다. `debugger` 프로세스를 재시작하면 새 tunnel URL이 발급됩니다. 재발급 후 QR을 다시 스캔하세요. (관련: [#290](https://github.com/apps-in-toss-community/devtools/issues/290))
103
105
 
104
106
  **"page crash" — list_pages에 crashDetectedAt이 찍힘**
105
107
 
@@ -107,7 +109,7 @@ cloudflared quick tunnel은 수 시간 후 drop될 수 있습니다. `devtools-m
107
109
 
108
110
  **"SDK 부재" — window.__sdkCall 미주입**
109
111
 
110
- `call_sdk` 호출 시 `ok: false, error: "window.__sdkCall is not available"` 에러가 뜨면 SDK 브리지가 아직 설치되지 않은 상태입니다. 아래 "on-device 디버깅 한 줄 설정" 섹션을 참고해 `import '@ait-co/devtools/in-app/auto'`가 미니앱 entry에 추가돼 있는지 확인하세요. 환경 2(PWA)에서는 이 에러가 예상 결과입니다. (관련: [#285](https://github.com/apps-in-toss-community/devtools/issues/285))
112
+ `call_sdk` 호출 시 `ok: false, error: "window.__sdkCall is not available"` 에러가 뜨면 SDK 브리지가 아직 설치되지 않은 상태입니다. 아래 "on-device 디버깅 한 줄 설정" 섹션을 참고해 `import '@ait-co/debug-console/auto'`가 미니앱 entry에 추가돼 있는지 확인하세요. 환경 2(PWA)에서는 이 에러가 예상 결과입니다. (관련: [#285](https://github.com/apps-in-toss-community/devtools/issues/285))
111
113
 
112
114
  **"QR 스캔했는데 인증 실패" — TOTP 만료**
113
115
 
@@ -300,7 +302,7 @@ aitDevtools.vite({ tunnel: { cdp: true } }); // 실기기 미리보기 + on-devi
300
302
 
301
303
  ## Production 빌드
302
304
 
303
- 기본적으로 devtools 플러그인은 **production 빌드에서 자동 비활성화**됩니다 (`NODE_ENV === 'production'`이면 alias 변환과 Panel 주입이 모두 스킵). 별도의 조건부 설정 없이도 안전합니다.
305
+ 기본적으로 devtools 플러그인은 **production 빌드에서 자동 비활성화**됩니다 (`NODE_ENV === 'production'`이면 alias 변환과 Panel 주입이 모두 스킵). 별도의 조건부 설정 없이도 안전합니다. `@ait-co/devtools`는 devDependency이고 production 번들에 기여하는 바이트 수는 0입니다. CI가 실제 소비자 fixture를 빌드해 결과물을 grep하는 방식으로 이를 강제합니다.
304
306
 
305
307
  스테이징 환경 등에서 production 빌드에서도 devtools를 사용하려면 `forceEnable` 옵션을 사용하세요:
306
308
 
@@ -411,9 +413,9 @@ launcher는 **PWA(홈 화면 앱)로 실행할 때만 동작**합니다. 일반
411
413
  >
412
414
  > `tunnel` 옵션은 Vite dev 모드에서만 동작합니다 — production 빌드는 `forceEnable`이어도 터널을 띄우지 않습니다. 다른 번들러(Webpack/Rspack 등)에서는 무시됩니다. 이 옵션을 켜면 `cloudflared` / `qrcode-terminal`가 동적 import로만 로드되므로, 끄면 번들 그래프에 들어오지 않습니다.
413
415
 
414
- ### 한 줄 셋업 (예정)
416
+ ### 한 줄 셋업
415
417
 
416
- 위 "프로젝트당 1회" 단계(vite.config 패치 + `onlyBuiltDependencies` + `dev:phone` 스크립트)는 향후 [`agent-plugin`](https://github.com/apps-in-toss-community/agent-plugin) `/ait setup phone` 같은 단일 명령으로 흡수할 예정입니다 (명령 이름은 잠정). 이 README가 그 자동화의 명세서 역할을 하므로, 수동 셋업 단계가 줄어들어도 동작 모델 자체는 동일합니다.
418
+ 위 "프로젝트당 1회" 단계(vite.config 패치 + `onlyBuiltDependencies` + `dev:phone` 스크립트)는 [`agent-plugin`](https://github.com/apps-in-toss-community/agent-plugin) `/ait:setup-phone-preview` 명령으로 자동화돼 있습니다. 이 README가 그 자동화의 명세서 역할을 하므로, 수동 셋업 단계가 줄어들어도 동작 모델 자체는 동일합니다.
417
419
 
418
420
  ## Device API 모드 시스템
419
421
 
@@ -653,6 +655,9 @@ __ait.patch('permissions', { camera: 'denied' });
653
655
  __ait.patch('deviceModes', { location: 'web' });
654
656
  __ait.patch('iap', { nextResult: 'USER_CANCELED' });
655
657
  __ait.patch('failureModes', { loadAdMob: 'PLACEMENT_ID_FETCH_FAILED' }); // 실기기 광고 지면 조회 실패 재현
658
+ // 네이티브 브리지의 per-method rate limit 재현 — 아래 메서드를 1초 안에 재호출하면 APP_BRIDGE_THROTTLED로 거부된다.
659
+ // 훅이 삽입된 메서드: getClipboardText · setClipboardText · getCurrentLocation · loadAppsInTossAdMob · loadFullScreenAd
660
+ __ait.patch('failureModes', { throttled: { methods: ['getCurrentLocation'], intervalMs: 1000 } });
656
661
 
657
662
  // 이벤트 트리거
658
663
  __ait.trigger('backEvent');
@@ -876,68 +881,18 @@ it('Storage에 값을 저장하고 읽을 수 있다', async () => {
876
881
  });
877
882
  ```
878
883
 
879
- ## 실기기 테스트 러너 (`devtools-test`)
884
+ ## 실기기 테스트 러너 (`debugger-test`)
880
885
 
881
- 위 "테스트에서의 활용"이 데스크톱 jsdom에서 mock을 검증하는 경로라면, `devtools-test`는 같은 스타일의 테스트를 **실기기 토스 앱 WebView(환경 3)에서 실 SDK로** 돌리는 별도 실행 파일입니다. 패키지를 설치하면 `devtools-test` bin이 함께 들어옵니다.
886
+ 위 "테스트에서의 활용"이 데스크톱 jsdom에서 mock을 검증하는 경로라면, 같은 스타일의 테스트를 **실기기 토스 앱 WebView(환경 3)에서 실 SDK로** 돌리는 러너는 `@ait-co/debugger`로 이동했습니다(#818) bin도 `devtools-test`에서 `debugger-test`로 바뀌었습니다.
882
887
 
883
888
  ```bash
884
- # 형태
885
- devtools-test <glob> --scheme-url <intoss-private URL> [--manual-blocking] \
886
- --cell-sdk-line <2.x|3.x> --cell-platform <ios|android> [--report-dir <dir>]
887
-
888
- # 예시
889
- pnpm exec devtools-test 'src/**/*.ait.test.ts' \
889
+ pnpm add -D @ait-co/debugger
890
+ pnpm exec debugger-test 'src/**/*.ait.test.ts' \
890
891
  --scheme-url "intoss-private://my-mini-app?_deploymentId=<uuid>" \
891
892
  --cell-sdk-line 3.x --cell-platform ios --report-dir .ait-report
892
893
  ```
893
894
 
894
- | 플래그 | 의미 |
895
- |---|---|
896
- | `<glob>` | 테스트 파일 glob (여러 개 지정 가능) |
897
- | `--scheme-url` | `ait deploy --scheme-only`가 출력한 `intoss-private://` URL. 환경 3 attach에 필수 |
898
- | `--cell-sdk-line` | 리포트에 박히는 SDK 라인 축 (`2.x` / `3.x`, 생략 시 `2.x`) |
899
- | `--cell-platform` | 플랫폼 축 (`mock` / `ios` / `android` / `ios-pwa`). 해석 순서: 플래그 → `AIT_CELL_PLATFORM` env → `mock` |
900
- | `--manual-blocking` | `*.manual.ait.test.ts`를 사람이 조작하며 맨 마지막에 실행 |
901
- | `--report-dir` | 리포트·capture 저장 디렉토리. 생략하면 아무것도 저장하지 않습니다 |
902
-
903
- 준비물은 네 가지입니다:
904
-
905
- | 항목 | 내용 |
906
- |---|---|
907
- | relay TOTP 시크릿 | 러너가 relay를 띄우기 전에 필수로 검사하며, 없으면 QR이 뜨기도 전에 exit 1 합니다. `pnpm dev:phone:cdp`(unplugin `tunnel.cdp` 옵션)를 한 번 띄우면 프로젝트 루트에 `.ait_relay`가 자동 생성되고, 없으면 `AIT_DEBUG_TOTP_SECRET`을 직접 설정하세요 (`openssl rand -hex 32`). `.ait_relay`를 찾는 디렉토리는 `--project-root`(생략 시 cwd)가 정합니다 |
908
- | dog-food 번들 | `ait build && ait deploy --scheme-only` → 출력된 `intoss-private://…?_deploymentId=…` URL이 `--scheme-url` 값 |
909
- | 미니앱 entry 한 줄 | `import '@ait-co/devtools/in-app/auto'` — attach + `window.__sdk` 브리지 설치 ([위 섹션](#on-device-디버깅-한-줄-설정)) |
910
- | 테스트 파일 | `*.ait.test.ts`. `describe`/`it`/`test`/`expect`는 러너가 글로벌로 주입하므로 import가 필요 없고, `@apps-in-toss/web-framework` import는 번들 시 `window.__sdk`로 리다이렉트됩니다 |
911
-
912
- ### 스캔할 QR은 대시보드 QR입니다
913
-
914
- 실행하면 러너가 자체적으로 Chii relay + cloudflared 터널 + 로컬 QR 대시보드를 띄우고 그 주소를 stderr에 출력합니다 (기본 `http://127.0.0.1:8317/` — 포트가 점유돼 있으면 +1씩 최대 20개 포트를 훑고 그래도 안 되면 임의 포트. `--dashboard-port` 또는 `AIT_DEBUG_HTTP_PORT`로 변경).
915
-
916
- **폰으로 스캔할 QR은 이 대시보드의 QR입니다.** 이 QR만 scheme URL + relay wss + 항상 실리는 회전 코드 `at=`을 한 캡슐에 담고 있어서, 한 번 스캔하면 토스 앱이 번들을 cold-load하면서 동시에 CDP가 attach됩니다. attach에 성공하면 폰 화면 좌하단에 `Debugger Connected` 배지가 뜨고 러너가 곧바로 테스트를 실행합니다.
917
-
918
- > `ait deploy --scheme-only`가 출력한 맨 `intoss-private://` URL을 그대로 QR로 만들어 스캔하면 앱은 열리지만 **디버거는 붙지 않습니다** — `debug=1`·`relay=`가 없어 in-app gate가 attach를 막습니다. 러너는 스캔이 올 때까지 무한 대기하며(`--attach-timeout`으로 상한을 줄 수 있습니다) 그 사이 테스트는 한 줄도 실행되지 않습니다.
919
-
920
- ### 끝나면 "디버거 연결 끊김"이 뜹니다 (정상)
921
-
922
- run-then-exit 모델입니다. 마지막 테스트 파일이 끝나면 러너는 요약을 출력하고 relay·터널·대시보드를 정리한 뒤 종료하며(실패한 테스트가 있으면 exit code 1), 그 순간 폰의 배지가 "디버거 연결 끊김"으로 바뀌었다가 잠시 후 사라집니다. 디버그 세션이 닫힌 것이지 앱이 죽은 게 아니라서 미니앱 자체는 계속 떠 있습니다. 다시 돌리려면 러너를 재실행하고 새 대시보드 QR을 스캔하세요.
923
-
924
- ### 네이티브 시트가 뜨는 테스트 (`--manual-blocking`)
925
-
926
- 사진 선택기·권한 다이얼로그·전면 광고처럼 사람이 직접 눌러야 넘어가는 테스트는 파일명을 `*.manual.ait.test.ts`로 둡니다. 이 파일들은 기본 실행에서 **제외**되고 `--manual-blocking`을 줄 때만 포함되며, 일반 파일이 전부 끝난 뒤 **맨 마지막에** 실행됩니다. 각 수동 파일 직전에 대시보드와 stdout에 파일명 + 진행도(k/n) 안내가 뜨고, 파일당 타임아웃도 5분으로 늘어납니다.
927
-
928
- ### 산출물 (`--report-dir`)
929
-
930
- | 경로 | 내용 |
931
- |---|---|
932
- | `<dir>/<sdkLine>.<platform>.json` | 러너 중립 리포트. 파일 경로는 프로젝트 루트 기준 상대 경로이고 relay·scheme·TOTP 값은 담기지 않습니다 |
933
- | `<dir>/<sdkLine>.<platform>.manual.json` | `--manual-blocking` 실행에 포함된 수동 파일들 — 표준 리포트를 대체하지 않고 나란히 기록됩니다 |
934
- | `<dir>/.ait-capture/<category>.<sdkLine>.<platform>.json` | 테스트가 남긴 `__AIT_CAPTURE__` 라인 (2.x↔3.0 오프라인 비교용) |
935
-
936
- `<sdkLine>`·`<platform>`은 `--cell-sdk-line`·`--cell-platform` 값이 그대로 들어갑니다. `--report-dir`을 생략하면 리포트도 capture도 수집하지 않습니다.
937
-
938
- ### 나머지 플래그
939
-
940
- 전체 플래그 레퍼런스는 `devtools-test --help`가 정본입니다. attach/실행 타임아웃, 브리지 호출 pacing, 환경 2(launcher PWA)에 붙는 `--attach-launcher --app-url` 모드처럼 위에 없는 것은 그쪽에서 확인하세요.
895
+ 전체 플래그·QR 스캔 절차·산출물 레퍼런스는 이제 `@ait-co/debugger` 패키지가 정본입니다 — `debugger-test --help`를 참고하세요. 미니앱 entry에 필요한 한 줄만 이 패키지 쪽에 남아 있습니다: `import '@ait-co/debug-console/auto'` ([위 섹션](#on-device-디버깅-한-줄-설정)).
941
896
 
942
897
  ## SDK 업데이트 대응
943
898
 
@@ -1051,207 +1006,42 @@ Turbopack은 unplugin을 지원하지 않으므로, `next.config.js`에서 `reso
1051
1006
  import '@ait-co/devtools/panel';
1052
1007
  ```
1053
1008
 
1054
- ### `devtools-mcp` — 이미 실행 중인 세션이 있을 때
1055
-
1056
- 두 번째 `devtools-mcp` 실행 시 "기존 debug-mode 세션이 이미 실행 중" 메시지가 stderr에 출력됩니다. 기존 PID와 wssUrl이 함께 표시됩니다.
1057
-
1058
- 회복 방법:
1059
-
1060
- ```bash
1061
- # 기존 세션을 직접 종료
1062
- kill <PID>
1063
-
1064
- # 또는 --force 플래그로 기존 세션을 종료하고 takeover
1065
- npx @ait-co/devtools devtools-mcp --force
1066
- # local 모드라면:
1067
- npx @ait-co/devtools devtools-mcp --target=local --force
1068
- ```
1069
-
1070
- `--takeover`도 `--force`의 alias로 동일하게 동작합니다.
1071
-
1072
1009
  ## MCP Server
1073
1010
 
1074
- AI 코딩 에이전트(Claude Code, Cursor ) [MCP(Model Context Protocol)](https://modelcontextprotocol.io/)
1075
- 통해 실행 중인 미니앱을 직접 관측할 수 있습니다. 단일 `devtools-mcp` bin이 두 모드를 제공합니다.
1076
-
1077
- 로컬 브라우저(환경 1)와 폰 토스 앱 WebView(환경 2·3)는 둘 다 CDP를 말하므로 모든 tool이 두 환경에서 동일하게 동작합니다 — 갈라지는 건 attach 전략(`--target=relay` vs `--target=local`)뿐입니다.
1078
-
1079
- | 모드 + 타깃 | 호출 | 환경 변수 | 대상 | tool |
1080
- |---|---|---|---|---|
1081
- | `--target=mobile` (env 2) | `devtools-mcp` → `start_debug({mode:'relay-sandbox'})` | `AIT_RELAY_BASE_URL`, `AIT_TUNNEL_BASE_URL` | 실기기 Safari/WebKit PWA (외부 Chii relay + cloudflared 터널, 환경 2) | console/network/page + DOM/snapshot/screenshot |
1082
- | `--mode=debug --target=relay` (기본값, env 3) | `devtools-mcp` → `start_debug({mode: 'relay-staging'})` | — | 폰 안 dog-food 번들 (CDP/Chii relay + cloudflared 터널, 환경 3) | 동일 + `AIT.*` |
1083
- | `--mode=debug --target=local` (env 1) | `devtools-mcp --target=local` | `MCP_ENV=mock` (자동) | MCP가 직접 기동한 로컬 Chromium (CDP direct-attach, relay 불필요, 환경 1) | 동일 |
1084
- | `--mode=dev` | `devtools-mcp --mode=dev` | `MCP_ENV=mock` (자동) | 실행 중인 Vite dev server의 mock state (AIT.* 전용, CDP 없음) | `AIT.*` (+ `devtools_get_mock_state` alias) |
1085
-
1086
- `--target=local`은 `AIT_DEVTOOLS_URL`(기본 `http://localhost:5173`)을 열고 로컬 Chromium에 CDP direct-attach합니다 — relay나 터널이 필요하지 않습니다. `--mode=dev`는 Vite dev server의 mock-state HTTP endpoint를 읽으며 CDP tool은 제공하지 않습니다. 세션 내 환경 전환은 `start_debug(mode)` 한 번으로 처리됩니다: `relay-sandbox`(env 2 PWA), `relay-staging`(env 3 dogfood), `local-browser`(env 1).
1087
-
1088
- #### 환경 2 (실기기 PWA CDP) — `--target=mobile`
1089
-
1090
- 토스 검수 없이 실기기 WebKit 엔진에서 CDP 디버깅이 가능한 모드입니다. [`tunnel:{cdp:true}`](#tunnel-옵션)를 켠 Vite dev server가 앱 HTTP 터널과 Chii relay 터널을 두 개 띄우고, MCP는 그 relay에 붙어 `start_attach` → launcher QR을 제공합니다.
1091
-
1092
- **진입 절차:**
1093
-
1094
- 1. Vite dev server를 CDP 터널 모드로 기동:
1095
- ```bash
1096
- AIT_TUNNEL_CDP=1 pnpm exec vite --config e2e/fixture/vite.config.ts
1097
- ```
1098
- 터미널 배너에 두 URL이 출력됩니다:
1099
- - **앱 HTTP 터널** `https://<A>.trycloudflare.com` → `AIT_TUNNEL_BASE_URL`로 설정
1100
- - **relay wss 터널** `wss://<B>.trycloudflare.com` → `AIT_RELAY_BASE_URL`의 `https://` 형으로 설정
1101
-
1102
- 2. MCP server를 mobile 모드로 기동 (별도 터미널):
1103
- ```json
1104
- {
1105
- "mcpServers": {
1106
- "ait-debug": {
1107
- "command": "npx",
1108
- "args": ["-y", "@ait-co/devtools", "devtools-mcp"],
1109
- "env": {
1110
- "AIT_RELAY_BASE_URL": "https://<B>.trycloudflare.com",
1111
- "AIT_TUNNEL_BASE_URL": "https://<A>.trycloudflare.com"
1112
- }
1113
- }
1114
- }
1115
- }
1116
- ```
1117
-
1118
- 3. Claude Code 세션에서 진입:
1119
- ```
1120
- start_debug({mode: 'relay-sandbox'})
1121
- start_attach()
1122
- ```
1123
- QR을 폰 카메라로 스캔하면 launcher PWA가 앱을 프레임에 열고 Chii target.js를 주입합니다.
1124
-
1125
- 4. `list_pages()` → 페이지 1개 확인. `take_screenshot()` 등 CDP tool을 사용합니다.
1126
-
1127
- **env 2의 fidelity 경계**: SDK mock을 씁니다 (실 SDK 호출 불가) — `call_sdk`는 환경 2에서 mock을 칩니다. 실 SDK fidelity가 필요하면 환경 3으로 올라가세요. CDP는 실 WebKit 엔진 위에서 동작하므로 DOM·console·screenshot은 실기기 화면을 그대로 반영합니다.
1128
-
1129
- **로컬 PC 검증**: `e2e/launcher-cdp.test.ts`가 node-side relay 기동(`startChiiRelay({port:0})`)과 launcher 파라미터 포워딩(Playwright)을 자동 검증합니다. browser-side Chii target.js 주입은 localhost 호스트 게이트(Layer B1)와 ws:// vs wss:// 제약으로 CI에서 검증 불가 — 위 수동 절차(실기기 trycloudflare.com 호스트)에서 완성됩니다.
1130
-
1131
- ### Debug 모드 (CDP via Chii)
1132
-
1133
- 실기기 relay 디버깅 루프(dog-food 빌드 → QR 스캔 → relay attach)의 단계별 절차와 복구 방법은 **[`docs/dogfood-relay-loop.md`](./docs/dogfood-relay-loop.md)** 를 참고하세요. crash가 발생한 경우 — `list_pages.crashDetectedAt`, iOS Console.app `.ips` 분석, redact 절차를 포함한 원인 추적 절차는 **[`docs/crash-triage.md`](./docs/crash-triage.md)** 를 참고하세요.
1134
-
1135
- read-only tool만 노출합니다. 도구는 attach 상태에 따라 2단계로 등록됩니다 — attach 전에는 bootstrap
1136
- 도구(`start_attach`·`list_pages`)만 보이고, 릴레이/로컬 페이지가 attach되면 `notifications/tools/list_changed`로
1137
- attach 의존 도구가 같은 세션에서 동적 등록됩니다(세션 재시작 불필요). 폰 attach 라운드트립은 fully wired
1138
- 상태이며 남은 것은 실기기 acceptance 한 번뿐입니다. tool 계층은 주입 가능한 CDP 연결 / AIT 소스를 mock해
1139
- CI에서 검증됩니다.
1140
-
1141
- `devtools-mcp`를 stdio로 실행하면 로컬 Chii 릴레이를 OS가 할당한 포트에 띄우고 cloudflared quick
1142
- tunnel로 공개 `wss://*.trycloudflare.com` URL을 발급한 뒤 QR을 터미널에 출력합니다(시크릿/인증
1143
- 코드는 출력하지 않습니다). 폰이 dog-food 진입 시 in-app attach UI가 그 URL로 릴레이에 붙으면,
1144
- 에이전트가 `chrome-devtools-mcp` 호환 tool로 console/network/page 상태를 read합니다. 사람이 폰을
1145
- 지켜볼 필요 없이 회귀를 단독 진단하는 것이 목표입니다.
1146
-
1147
- 환경 3 (intoss-private relay) — `devtools-mcp`를 그대로 기동한 뒤 `start_debug(mode)`로 진입합니다:
1011
+ MCP 표면(데몬 · attach · CDP tool) `@ait-co/debugger`로 이동했습니다(#818). 에이전트 등록도 이제 devtools가 아니라 debugger 가리킵니다:
1148
1012
 
1149
1013
  ```json
1150
1014
  {
1151
1015
  "mcpServers": {
1152
1016
  "ait-debug": {
1153
- "command": "pnpm",
1154
- "args": ["exec", "devtools-mcp"]
1155
- }
1156
- }
1157
- }
1158
- ```
1159
-
1160
- - 환경 3 (dog-food relay): `start_debug({mode: 'relay-staging'})`
1161
- **세션 내 환경 전환은 `start_debug(mode)`가 단일 진입 경로**입니다.
1162
-
1163
- | Tool | CDP / AIT 백킹 | 설명 |
1164
- |---|---|---|
1165
- | `list_console_messages` | `Runtime.consoleAPICalled` | 최근 console.log/warn/error 메시지 (level, text, timestamp, args) |
1166
- | `list_network_requests` | `Network.requestWillBeSent` + `responseReceived` | 최근 XHR/fetch 요청 (url, method, status, timing) |
1167
- | `list_pages` | Chii 릴레이 target 목록 | attach된 페이지 + tunnel 상태 + wss URL |
1168
- | `start_attach` | (순수 합성 + attach 대기) | `ait deploy --scheme-only` URL에 `debug=1`+릴레이 URL을 끼워 self-attach deep-link를 합성하고 QR을 출력한 뒤, 폰이 attach될 때까지 같은 호출 안에서 대기한다(QR 생성·attach가 한 호출). `mode`로 세션 환경을 함께 전환할 수 있고, 대기 중 TOTP 코드를 자동 재발행한다. 환경 2·3 진입 도구(bootstrap) — `list_pages` 선행 불필요 |
1169
- | `get_dom_document` | `DOM.getDocument` | DOM 트리 read (구조/레이아웃 회귀 진단) |
1170
- | `take_snapshot` | `DOMSnapshot.captureSnapshot` | 페이지 스냅샷 (documents + interned strings, 시각 회귀 진단) |
1171
- | `take_screenshot` | `Page.captureScreenshot` | 페이지 PNG 스크린샷 (MCP image content block 반환) |
1172
- | `measure_safe_area` | `Runtime.evaluate` | attach된 페이지에서 safe-area 프로브 실행 → 정규화된 safe-area inset·뷰포트 geometry·DPR·User-Agent 반환. read-only. relay 세션(폰 attach)에서 viewport preset을 extrapolated/placeholder→measured로 승급할 ground truth 수집용. attach 필요 (`list_pages` 먼저) |
1173
- | `evaluate` | `Runtime.evaluate` | attach된 페이지에서 임의 JS 표현식 평가(returnByValue) → 결과 반환. **read-only 아님** — 표현식이 부작용(DOM 변경·SDK 호출·상태 변경)을 일으킬 수 있음. attach 필요 |
1174
- | `call_sdk` | `window.__sdkCall` 브리지 (`Runtime.evaluate` 경유) | dog-food SDK 메서드를 `window.__sdkCall` 브리지로 호출 (`@apps-in-toss/web-framework`가 `__DEBUG_BUILD__` 번들에서만 export). **read-only 아님** — SDK 호출은 부작용(내비게이션·결제·권한 등). 환경 3(실기기 relay)에선 실 SDK, 환경 1(로컬 mock)에선 mock SDK. 환경 2(PWA)는 SDK 미주입으로 사용 불가. attach 필요. `{ok,value}` / `{ok,error}` 반환 |
1175
- | `AIT.getSdkCallHistory` | AIT 도메인 | SDK 호출 trace (method, args, result/error, timestamp) |
1176
- | `AIT.getMockState` | AIT 도메인 | mock state 스냅샷 (`window.__ait`) |
1177
- | `AIT.getOperationalEnvironment` | AIT 도메인 | `getOperationalEnvironment()` + SDK 버전 |
1178
-
1179
- `AIT.*`는 raw CDP가 못 잡는 영역으로, 같은 MCP server가 CDP와 함께 forward합니다. debug 모드에서는
1180
- in-app 측이 Chii 채널로 응답합니다.
1181
-
1182
- ### Dev 모드 (mock state)
1183
-
1184
- `devtools-mcp --mode=dev`는 실행 중인 브라우저의 mock state를 읽습니다. debug 모드와 같은 `AIT.*`
1185
- tool surface를 공유합니다.
1186
-
1187
- #### 구조
1188
-
1189
- ```
1190
- 브라우저 (aitState)
1191
- └─ POST /api/ait-devtools/state (panel이 state 변경 시 자동 push)
1192
- └─ Vite dev server (unplugin mcp: true 로 등록)
1193
- └─ GET /api/ait-devtools/state
1194
- └─ MCP stdio server (dist/mcp/server.js)
1195
- └─ AI 에이전트 (AIT.getMockState tool)
1196
- ```
1197
-
1198
- #### 설정
1199
-
1200
- **1. Vite 플러그인에 `mcp: true` 추가**
1201
-
1202
- ```ts
1203
- // vite.config.ts
1204
- import aitDevtools from '@ait-co/devtools/unplugin';
1205
-
1206
- export default {
1207
- plugins: [aitDevtools.vite({ mcp: true })],
1208
- };
1209
- ```
1210
-
1211
- **2. MCP 클라이언트 설정 (예: Claude Code `.claude/settings.json`)**
1212
-
1213
- ```json
1214
- {
1215
- "mcpServers": {
1216
- "ait-devtools": {
1217
- "command": "pnpm",
1218
- "args": ["exec", "devtools-mcp", "--mode=dev"],
1219
- "env": {
1220
- "AIT_DEVTOOLS_URL": "http://localhost:5173"
1221
- }
1017
+ "command": "npx",
1018
+ "args": ["-y", "-p", "@ait-co/debugger", "debugger"]
1222
1019
  }
1223
1020
  }
1224
1021
  }
1225
1022
  ```
1226
1023
 
1227
- `AIT_DEVTOOLS_URL`은 기본값이 `http://localhost:5173`이므로 기본 포트를 쓰면 생략 가능합니다.
1228
-
1229
- **3. 앱을 브라우저에서 열고, AI 에이전트에서 tool 호출**
1230
-
1231
- ```
1232
- > AIT.getMockState
1233
- ```
1234
-
1235
- 현재 mock state 전체(권한, 위치, 인증, 네트워크, IAP 등)를 JSON으로 반환합니다.
1236
-
1237
- | Tool | 설명 |
1238
- |---|---|
1239
- | `AIT.getMockState` | 현재 `AitDevtoolsState` 스냅샷 반환 (read-only) |
1240
- | `AIT.getOperationalEnvironment` | mock state의 `environment` + `appVersion` 기반 환경/버전 |
1241
- | `AIT.getSdkCallHistory` | dev 모드에서는 빈 목록 (HTTP endpoint가 trace를 기록하지 않음) |
1242
- | `devtools_get_mock_state` | `AIT.getMockState`의 하위호환 alias (신규 설정은 `AIT.getMockState` 권장) |
1024
+ 이 서버가 주는 것: 로컬 브라우저(환경 1)·PWA(환경 2)·intoss-private WebView(환경 3)에서 실행 중인 미니앱을 CDP로 관측 — console, network, DOM, snapshot, screenshot — 그리고 환경 2·3 on-device 진입용 `start_attach`. 전체 tool 목록·모드/타깃 매트릭스·환경별 설정은 [`@ait-co/debugger`](https://www.npmjs.com/package/@ait-co/debugger) 패키지 문서가 정본입니다.
1243
1025
 
1244
1026
  ## 패키지 Export 구조
1245
1027
 
1028
+ 이 패키지가 실제로 출하하는 진입점입니다:
1029
+
1246
1030
  | Import path | 용도 |
1247
1031
  |---|---|
1248
- | `@ait-co/devtools` 또는 `@ait-co/devtools/mock` | 모든 mock export (번들러 alias 대상) |
1032
+ | `@ait-co/devtools` (= `/mock`) | 번들러 alias 대상, 모든 mock export |
1249
1033
  | `@ait-co/devtools/panel` | Floating DevTools Panel (import 시 자동 마운트) |
1250
1034
  | `@ait-co/devtools/unplugin` | 번들러 플러그인 (.vite, .webpack, .rspack, .esbuild, .rollup) |
1251
- | `@ait-co/devtools/mcp/server` | dev-mode MCP stdio server 함수 (Node.js) |
1252
- | `@ait-co/devtools/mcp/cli` | `devtools-mcp` bin 진입점 (debug / dev 모드, Node.js) |
1253
- | `@ait-co/devtools/in-app` | In-app debug attach — 런타임 gate(layer B·C) + Chii target.js 주입. 소비자가 `if (__DEBUG_BUILD__)`로 import를 감싸 release 빌드에서 DCE — dog-food 빌드 전용 |
1254
- | `@ait-co/devtools/in-app/auto` | Self-gating side-effect entry — `import '@ait-co/devtools/in-app/auto'` 한 줄로 attach + SDK 브리지 설치. URL 파라미터(`?debug=1` / `?relay=`) 또는 DEV 빌드에서만 활성화, 일반 프로덕션 로드는 dormant. [위 섹션](#on-device-디버깅-한-줄-설정) 참고 |
1035
+
1036
+ 아래는 **전환 스텁**입니다 0.2.x에만 존재하고 1.0.0에서 제거됩니다(#818). 패키지로 마이그레이션하세요.
1037
+
1038
+ | Import path | 이동처 | import |
1039
+ |---|---|---|
1040
+ | `@ait-co/devtools/mcp/server` | `@ait-co/debugger/mcp/server` | throw |
1041
+ | `@ait-co/devtools/mcp/cli` | `@ait-co/debugger/mcp/cli` | throw |
1042
+ | `@ait-co/devtools/test-runner` | `@ait-co/debugger/test-runner` | throw |
1043
+ | `@ait-co/devtools/in-app` | `@ait-co/debug-console` | no-op + `console.error` 1회 |
1044
+ | `@ait-co/devtools/in-app/auto` | `@ait-co/debug-console/auto` | no-op + `console.error` 1회 |
1255
1045
 
1256
1046
  ## 라이센스
1257
1047
 
@@ -1,138 +1 @@
1
- //#region src/in-app/auto.d.ts
2
- /**
3
- * @ait-co/devtools/in-app/auto — self-gating side-effect entry.
4
- *
5
- * Consumers add a single line to their mini-app entry:
6
- *
7
- * import '@ait-co/devtools/in-app/auto';
8
- *
9
- * The entry self-gates: if none of the debug activation signals are present
10
- * (no `?debug=1`, no `?relay=`, and not a DEV build), it does nothing. The
11
- * imported chunk stays dormant and `window.__sdk` / `window.__sdkCall` are
12
- * never installed on a normal production load.
13
- *
14
- * DEPRECATED for builds that require debug code to be PHYSICALLY ABSENT from
15
- * the release bundle. This entry is a RUNTIME self-gate, not a build-time one:
16
- * the imported chunk (Chii target.js injection, the SDK bridge, and the eruda
17
- * console it pulls in via `maybeAttach()`) stays in the production bundle as a
18
- * dormant chunk and is only kept asleep at runtime. If your threat model needs
19
- * "zero bytes of debug surface in release" (no dormant chunk to extract or
20
- * re-enable), do NOT use this entry. Instead guard the call site yourself:
21
- *
22
- * if (__DEBUG_BUILD__) {
23
- * import('@ait-co/devtools/in-app').then((m) => m.maybeAttach());
24
- * }
25
- *
26
- * with `define: { __DEBUG_BUILD__: 'false' }` in your release build — the
27
- * bundler then dead-code-eliminates the whole `@ait-co/devtools/in-app` graph
28
- * (verified on Vite 8/rolldown). This entry stays for the convenience case
29
- * where a dormant chunk gated at runtime is acceptable.
30
- *
31
- * When the gate passes it:
32
- * 1. Calls `maybeAttach()` — runs the full Layer B/C gate (host allowlist,
33
- * opt-in params, relay URL, TOTP) and injects the Chii `target.js` script.
34
- * Gate semantics are NOT changed — this is a thin self-gate wrapper.
35
- * 2. Installs the SDK bridge (`window.__sdk` / `window.__sdkCall`) so an AI
36
- * agent can drive any SDK API over the CDP relay without hand-synthesising
37
- * the Granite/ReactNative bridge envelope. SDK access uses a dynamic
38
- * import of `@apps-in-toss/web-framework` — the peer is optional, so if
39
- * the SDK is not installed the bridge install is silently skipped
40
- * (fail-silent). The namespace mirror pattern (iterate `Object.keys`) is
41
- * SDK version-neutral: 2.x and 3.x are both covered without any static
42
- * import that would couple the entry to a specific SDK line.
43
- *
44
- * SECRET-HANDLING: no secret, TOTP code, relay URL, or host value is ever
45
- * logged or surfaced beyond the reason enum in `maybeAttach()`.
46
- *
47
- * Layer A (build-time DCE) is NOT enforced here — this entry IS the
48
- * consumer-facing alternative to `if (__DEBUG_BUILD__) { … }`. The self-gate
49
- * below performs the same dormancy guarantee via a URL param check, which is
50
- * safe in a side-effect import context (the gate runs at module evaluation
51
- * time, before any React tree mounts). Consumers who already manage their own
52
- * `__DEBUG_BUILD__` guard can keep using `@ait-co/devtools/in-app` directly.
53
- *
54
- * DEV detection uses two complementary signals:
55
- * 1. `import.meta.env.DEV` — resolved by the consumer's bundler at their
56
- * build time (Vite/Webpack/Rspack inject the value via top-level source
57
- * transforms). Works when the consumer's source code (not node_modules)
58
- * is processed — same pattern used by the polyfill's `auto` entry.
59
- * 2. `process.env.NODE_ENV === 'development'` — resolved by the consumer's
60
- * bundler via esbuild `define` (Vite dep-prebundle) or DefinePlugin
61
- * (webpack/Rspack). This token IS substituted in dep code inside
62
- * node_modules (how React's own dev/prod branching works), fixing the
63
- * env-1 regression where signal (1) was never injected into dep code
64
- * (sdk-example#180 / issue #520).
65
- * IMPORTANT: the `process.env.NODE_ENV` token must be written verbatim
66
- * — bundler define substitution is a textual token match. A `typeof
67
- * process` guard would survive substitution as-is and always evaluate to
68
- * `false` in a browser, killing the comparison. Instead we rely on
69
- * try/catch: if `process` is not defined (raw ESM in a browser without
70
- * bundler substitution) a ReferenceError is caught → fail-closed (dormant).
71
- */
72
- declare global {
73
- interface Window {
74
- /**
75
- * Entire `@apps-in-toss/web-framework` export namespace mirrored onto a
76
- * plain writable object. Installed by the auto entry when `?debug=1` /
77
- * `?relay=` is present in the URL, or in DEV builds.
78
- *
79
- * Lets an AI agent call any SDK API over a CDP relay without
80
- * hand-synthesising the Granite/ReactNative bridge envelope:
81
- * `window.__sdk.setDeviceOrientation({ type: 'landscape' })`
82
- */
83
- __sdk?: Record<string, unknown>;
84
- /**
85
- * Safe call wrapper for `window.__sdk`. Returns a JSON-serialisable
86
- * `{ ok: true, value }` or `{ ok: false, error }` tuple even for
87
- * throwing/async SDK functions — ideal for `Runtime.evaluate` results.
88
- *
89
- * @example
90
- * window.__sdkCall('setDeviceOrientation', { type: 'landscape' })
91
- */
92
- __sdkCall?: (name: string, ...args: unknown[]) => Promise<{
93
- ok: boolean;
94
- value?: unknown;
95
- error?: string;
96
- }>;
97
- }
98
- }
99
- /**
100
- * Detects whether the current build is a DEV build by consulting two signals.
101
- *
102
- * Signal A — `import.meta.env.DEV`:
103
- * Substituted by Vite/Webpack/Rspack in the consumer's own source files.
104
- * NOT substituted in node_modules dep code (esbuild prebundle does not
105
- * apply Vite's define pass to deps) — this was the root cause of #520.
106
- *
107
- * Signal B — `process.env.NODE_ENV === 'development'`:
108
- * Substituted by esbuild's dep-prebundle define pass (Vite) and by
109
- * DefinePlugin (webpack/Rspack) even inside node_modules. This is how
110
- * React itself gates its dev-only code paths. Writing the token verbatim
111
- * ensures textual substitution works; a `typeof process` guard would not
112
- * be substituted and would evaluate to `'undefined'` in the browser,
113
- * killing the comparison. A try/catch catches the ReferenceError when
114
- * `process` is genuinely absent (raw ESM without bundler, e.g. direct
115
- * browser import or test runners that leave identifiers in place) →
116
- * fail-closed (dormant).
117
- *
118
- * Exported for unit tests — pass an explicit `isDev` override to bypass
119
- * the environment detection in controlled test scenarios.
120
- */
121
- declare function detectDevSignal(): boolean;
122
- /**
123
- * Pure predicate for the self-gate. Exported for unit tests.
124
- *
125
- * @param isDev - Whether the consumer's bundler signals a DEV build.
126
- * Default: calls `detectDevSignal()` which consults both
127
- * `import.meta.env.DEV` (consumer source pass) and
128
- * `process.env.NODE_ENV === 'development'` (dep prebundle pass, fixing
129
- * the env-1 regression in issue #520).
130
- * Pass an explicit value in tests to control the DEV signal without
131
- * depending on the Vite/vitest build environment.
132
- * @param searchStr - URL search string to inspect. Defaults to
133
- * `window.location.search` when called in a browser context.
134
- */
135
- declare function shouldActivate(isDev?: boolean, searchStr?: string): boolean;
136
- //#endregion
137
- export { detectDevSignal, shouldActivate };
138
- //# sourceMappingURL=auto.d.ts.map
1
+ export { };