@ait-co/devtools 0.1.143 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/README.en.md +65 -163
  2. package/README.md +65 -192
  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 +19 -20
  17. package/dist/mock/index.d.ts.map +1 -1
  18. package/dist/mock/index.js.map +1 -1
  19. package/dist/optional-peers-CDEFhlhJ.cjs +131 -0
  20. package/dist/optional-peers-CDEFhlhJ.cjs.map +1 -0
  21. package/dist/optional-peers-FdVbUJst.js +96 -0
  22. package/dist/optional-peers-FdVbUJst.js.map +1 -0
  23. package/dist/panel/index.js +1 -103
  24. package/dist/panel/index.js.map +1 -1
  25. package/dist/relay-url-store-CPZAn-T5.js +107 -0
  26. package/dist/relay-url-store-CPZAn-T5.js.map +1 -0
  27. package/dist/relay-url-store-DLjlvMSA.cjs +108 -0
  28. package/dist/relay-url-store-DLjlvMSA.cjs.map +1 -0
  29. package/dist/stubs/bin-devtools-mcp.js +58 -0
  30. package/dist/stubs/bin-devtools-mcp.js.map +1 -0
  31. package/dist/stubs/bin-devtools-test.d.ts +2 -0
  32. package/dist/stubs/bin-devtools-test.js +55 -0
  33. package/dist/stubs/bin-devtools-test.js.map +1 -0
  34. package/dist/test-runner/config.d.ts +1 -231
  35. package/dist/test-runner/config.js +41 -45
  36. package/dist/test-runner/config.js.map +1 -1
  37. package/dist/{tunnel-BVSMXctM.cjs → tunnel-BKZkOyQp.cjs} +27 -75
  38. package/dist/tunnel-BKZkOyQp.cjs.map +1 -0
  39. package/dist/{tunnel-D7xkimBu.js → tunnel-CqSCIrdU.js} +27 -75
  40. package/dist/tunnel-CqSCIrdU.js.map +1 -0
  41. package/dist/unplugin/index.cjs +17 -30
  42. package/dist/unplugin/index.cjs.map +1 -1
  43. package/dist/unplugin/index.d.cts +34 -5
  44. package/dist/unplugin/index.d.cts.map +1 -1
  45. package/dist/unplugin/index.d.ts +35 -6
  46. package/dist/unplugin/index.d.ts.map +1 -1
  47. package/dist/unplugin/index.js +17 -30
  48. package/dist/unplugin/index.js.map +1 -1
  49. package/dist/unplugin/tunnel.cjs +61 -74
  50. package/dist/unplugin/tunnel.cjs.map +1 -1
  51. package/dist/unplugin/tunnel.d.cts +22 -16
  52. package/dist/unplugin/tunnel.d.cts.map +1 -1
  53. package/dist/unplugin/tunnel.d.ts +22 -16
  54. package/dist/unplugin/tunnel.d.ts.map +1 -1
  55. package/dist/unplugin/tunnel.js +61 -74
  56. package/dist/unplugin/tunnel.js.map +1 -1
  57. package/package.json +17 -22
  58. package/dist/attach-orchestrator-0F0m_UqQ.js +0 -1845
  59. package/dist/attach-orchestrator-0F0m_UqQ.js.map +0 -1
  60. package/dist/attach-orchestrator-D65KxFy_.js +0 -1831
  61. package/dist/attach-orchestrator-D65KxFy_.js.map +0 -1
  62. package/dist/attach-orchestrator-DL3NQ9ca.js +0 -1846
  63. package/dist/attach-orchestrator-DL3NQ9ca.js.map +0 -1
  64. package/dist/bundle-C796JIwG.d.ts +0 -159
  65. package/dist/bundle-C796JIwG.d.ts.map +0 -1
  66. package/dist/capture-DsP525OZ.d.ts +0 -58
  67. package/dist/capture-DsP525OZ.d.ts.map +0 -1
  68. package/dist/cdp-connection-rP1WdnH5.d.ts +0 -287
  69. package/dist/cdp-connection-rP1WdnH5.d.ts.map +0 -1
  70. package/dist/cell-BaLvusOl.js +0 -68
  71. package/dist/cell-BaLvusOl.js.map +0 -1
  72. package/dist/cell-CBUS3-nT.js +0 -274
  73. package/dist/cell-CBUS3-nT.js.map +0 -1
  74. package/dist/cell-EBKKpAAT.js +0 -307
  75. package/dist/cell-EBKKpAAT.js.map +0 -1
  76. package/dist/chii-relay-BZ3HqWL5.js +0 -304
  77. package/dist/chii-relay-BZ3HqWL5.js.map +0 -1
  78. package/dist/chii-relay-D7eK2acz.cjs +0 -304
  79. package/dist/chii-relay-D7eK2acz.cjs.map +0 -1
  80. package/dist/debug-server-B3ABDrRI.js +0 -456
  81. package/dist/debug-server-B3ABDrRI.js.map +0 -1
  82. package/dist/debug-server-BWhwrVXa.js +0 -1158
  83. package/dist/debug-server-BWhwrVXa.js.map +0 -1
  84. package/dist/debug-server-CfQNxxGW.js +0 -600
  85. package/dist/debug-server-CfQNxxGW.js.map +0 -1
  86. package/dist/deeplink-B5-Hxu0Q.js +0 -62
  87. package/dist/deeplink-B5-Hxu0Q.js.map +0 -1
  88. package/dist/deeplink-BpO9qc-D.js +0 -62
  89. package/dist/deeplink-BpO9qc-D.js.map +0 -1
  90. package/dist/deeplink-BzdbA1gV.cjs +0 -62
  91. package/dist/deeplink-BzdbA1gV.cjs.map +0 -1
  92. package/dist/deeplink-DCScMYcp.cjs +0 -62
  93. package/dist/deeplink-DCScMYcp.cjs.map +0 -1
  94. package/dist/devtools-opener-3Drge_RJ.js +0 -75
  95. package/dist/devtools-opener-3Drge_RJ.js.map +0 -1
  96. package/dist/devtools-opener-B8nxrxqu.js +0 -71
  97. package/dist/devtools-opener-B8nxrxqu.js.map +0 -1
  98. package/dist/devtools-opener-BDY0w3_0.cjs +0 -68
  99. package/dist/devtools-opener-BDY0w3_0.cjs.map +0 -1
  100. package/dist/devtools-opener-BTl5A6Cd.js +0 -71
  101. package/dist/devtools-opener-BTl5A6Cd.js.map +0 -1
  102. package/dist/devtools-opener-CJpEsXXQ.js +0 -76
  103. package/dist/devtools-opener-CJpEsXXQ.js.map +0 -1
  104. package/dist/devtools-opener-CxtryS8c.js +0 -75
  105. package/dist/devtools-opener-CxtryS8c.js.map +0 -1
  106. package/dist/devtools-opener-iv1OwfJN.cjs +0 -68
  107. package/dist/devtools-opener-iv1OwfJN.cjs.map +0 -1
  108. package/dist/in-app/auto.d.ts.map +0 -1
  109. package/dist/mcp/cli.d.ts.map +0 -1
  110. package/dist/mcp/server.d.ts.map +0 -1
  111. package/dist/pool-DcaaOwUq.d.ts +0 -14761
  112. package/dist/pool-DcaaOwUq.d.ts.map +0 -1
  113. package/dist/qr-http-server--gl2-WKc.cjs +0 -1644
  114. package/dist/qr-http-server--gl2-WKc.cjs.map +0 -1
  115. package/dist/qr-http-server-Bb7lMeqi.js +0 -1644
  116. package/dist/qr-http-server-Bb7lMeqi.js.map +0 -1
  117. package/dist/qr-http-server-C_lqOrgc.js +0 -1644
  118. package/dist/qr-http-server-C_lqOrgc.js.map +0 -1
  119. package/dist/qr-http-server-CopuMbub.js +0 -1644
  120. package/dist/qr-http-server-CopuMbub.js.map +0 -1
  121. package/dist/qr-http-server-D-Off6K1.cjs +0 -1644
  122. package/dist/qr-http-server-D-Off6K1.cjs.map +0 -1
  123. package/dist/qr-http-server-DrbIVDjO.js +0 -1645
  124. package/dist/qr-http-server-DrbIVDjO.js.map +0 -1
  125. package/dist/qr-http-server-n1twN18z.js +0 -1644
  126. package/dist/qr-http-server-n1twN18z.js.map +0 -1
  127. package/dist/relay-factory-N9QobQxG.js +0 -206
  128. package/dist/relay-factory-N9QobQxG.js.map +0 -1
  129. package/dist/relay-secret-store-BPhN1upr.js +0 -240
  130. package/dist/relay-secret-store-BPhN1upr.js.map +0 -1
  131. package/dist/relay-secret-store-Bmyleu0A.js +0 -154
  132. package/dist/relay-secret-store-Bmyleu0A.js.map +0 -1
  133. package/dist/relay-secret-store-CQenfcSL.js +0 -154
  134. package/dist/relay-secret-store-CQenfcSL.js.map +0 -1
  135. package/dist/relay-secret-store-DKxs7zwq.js +0 -153
  136. package/dist/relay-secret-store-DKxs7zwq.js.map +0 -1
  137. package/dist/relay-secret-store-DWKdV-eY.cjs +0 -241
  138. package/dist/relay-secret-store-DWKdV-eY.cjs.map +0 -1
  139. package/dist/relay-secret-store-WJ8EGkIl.js +0 -153
  140. package/dist/relay-secret-store-WJ8EGkIl.js.map +0 -1
  141. package/dist/relay-url-store-1FGuSYAn.cjs +0 -115
  142. package/dist/relay-url-store-1FGuSYAn.cjs.map +0 -1
  143. package/dist/relay-url-store-BR2XodiO.js +0 -123
  144. package/dist/relay-url-store-BR2XodiO.js.map +0 -1
  145. package/dist/relay-url-store-Bskcyeg8.js +0 -114
  146. package/dist/relay-url-store-Bskcyeg8.js.map +0 -1
  147. package/dist/relay-url-store-CH63fVCm.js +0 -122
  148. package/dist/relay-url-store-CH63fVCm.js.map +0 -1
  149. package/dist/relay-url-store-DaY1QPes.js +0 -123
  150. package/dist/relay-url-store-DaY1QPes.js.map +0 -1
  151. package/dist/relay-url-store-xmUuTjXA.js +0 -122
  152. package/dist/relay-url-store-xmUuTjXA.js.map +0 -1
  153. package/dist/relay-worker-B5HKkGUY.js +0 -832
  154. package/dist/relay-worker-B5HKkGUY.js.map +0 -1
  155. package/dist/relay-worker-YdlpZQl9.d.ts +0 -214
  156. package/dist/relay-worker-YdlpZQl9.d.ts.map +0 -1
  157. package/dist/rolldown-runtime-DGkTqVfb.js +0 -15
  158. package/dist/rolldown-runtime-DUslC3ob.js +0 -14
  159. package/dist/runtime-kn9DxOeg.d.ts +0 -249
  160. package/dist/runtime-kn9DxOeg.d.ts.map +0 -1
  161. package/dist/test-runner/bin.js +0 -2584
  162. package/dist/test-runner/bin.js.map +0 -1
  163. package/dist/test-runner/bridge-stub.d.ts +0 -125
  164. package/dist/test-runner/bridge-stub.d.ts.map +0 -1
  165. package/dist/test-runner/bridge-stub.js +0 -92
  166. package/dist/test-runner/bridge-stub.js.map +0 -1
  167. package/dist/test-runner/bundle.d.ts +0 -2
  168. package/dist/test-runner/bundle.js +0 -439
  169. package/dist/test-runner/bundle.js.map +0 -1
  170. package/dist/test-runner/capture.d.ts +0 -2
  171. package/dist/test-runner/capture.js +0 -44
  172. package/dist/test-runner/capture.js.map +0 -1
  173. package/dist/test-runner/config.d.ts.map +0 -1
  174. package/dist/test-runner/method-pace.d.ts +0 -82
  175. package/dist/test-runner/method-pace.d.ts.map +0 -1
  176. package/dist/test-runner/method-pace.js +0 -120
  177. package/dist/test-runner/method-pace.js.map +0 -1
  178. package/dist/test-runner/pool.d.ts +0 -2
  179. package/dist/test-runner/pool.js +0 -136
  180. package/dist/test-runner/pool.js.map +0 -1
  181. package/dist/test-runner/relay-factory.d.ts +0 -11245
  182. package/dist/test-runner/relay-factory.d.ts.map +0 -1
  183. package/dist/test-runner/relay-factory.js +0 -206
  184. package/dist/test-runner/relay-factory.js.map +0 -1
  185. package/dist/test-runner/relay-worker.d.ts +0 -2
  186. package/dist/test-runner/relay-worker.js +0 -2
  187. package/dist/test-runner/report.d.ts +0 -163
  188. package/dist/test-runner/report.d.ts.map +0 -1
  189. package/dist/test-runner/report.js +0 -198
  190. package/dist/test-runner/report.js.map +0 -1
  191. package/dist/test-runner/rpc.d.ts +0 -56
  192. package/dist/test-runner/rpc.d.ts.map +0 -1
  193. package/dist/test-runner/rpc.js +0 -98
  194. package/dist/test-runner/rpc.js.map +0 -1
  195. package/dist/test-runner/runtime.d.ts +0 -2
  196. package/dist/test-runner/runtime.js +0 -659
  197. package/dist/test-runner/runtime.js.map +0 -1
  198. package/dist/test-runner/task-graph.d.ts +0 -38
  199. package/dist/test-runner/task-graph.d.ts.map +0 -1
  200. package/dist/test-runner/task-graph.js +0 -182
  201. package/dist/test-runner/task-graph.js.map +0 -1
  202. package/dist/throttle-DKKzX1qC.js +0 -59
  203. package/dist/throttle-DKKzX1qC.js.map +0 -1
  204. package/dist/totp-95OAa20j.js +0 -64
  205. package/dist/totp-95OAa20j.js.map +0 -1
  206. package/dist/totp-BjtoQNfu.cjs +0 -64
  207. package/dist/totp-BjtoQNfu.cjs.map +0 -1
  208. package/dist/totp-CZLLKfOC.js +0 -200
  209. package/dist/totp-CZLLKfOC.js.map +0 -1
  210. package/dist/totp-DAxys-r0.js +0 -199
  211. package/dist/totp-DAxys-r0.js.map +0 -1
  212. package/dist/totp-DIbrZtI7.js +0 -189
  213. package/dist/totp-DIbrZtI7.js.map +0 -1
  214. package/dist/totp-Df252ZdA.cjs +0 -192
  215. package/dist/totp-Df252ZdA.cjs.map +0 -1
  216. package/dist/totp-DfekTBk3.js +0 -211
  217. package/dist/totp-DfekTBk3.js.map +0 -1
  218. package/dist/totp-Dwft0Kz7.js +0 -3
  219. package/dist/totp-WY6l0ysP.js +0 -190
  220. package/dist/totp-WY6l0ysP.js.map +0 -1
  221. package/dist/tunnel-BVSMXctM.cjs.map +0 -1
  222. package/dist/tunnel-D7xkimBu.js.map +0 -1
  223. /package/dist/{test-runner/bin.d.ts → stubs/bin-devtools-mcp.d.ts} +0 -0
package/README.en.md CHANGED
@@ -47,7 +47,7 @@ pnpm dev:phone # same as AIT_TUNNEL=1 pnpm dev
47
47
  # QR appears in the terminal → scan with your phone camera → opens in the launcher PWA
48
48
  ```
49
49
 
50
- With `tunnel: { cdp: true }`, a single QR scan opens both the screen preview and on-device CDP — inspect the real WebKit DOM, console, and exceptions from your MCP host (`call_sdk` still hits the mock on environment 2; the real SDK lives on environment 3).
50
+ With `tunnel: { cdp: true }`, a single QR scan opens both the screen preview and on-device CDP — inspect the real WebKit DOM, console, and exceptions from your MCP host (`call_sdk` still hits the mock on environment 2; the real SDK lives on environment 3). CDP needs two extra packages — see [Debugging packages](#debugging-packages-environments-2-and-3) below.
51
51
 
52
52
  One-time prerequisite: add `https://devtools.aitc.dev/launcher/` to your phone's home screen. Details: [`docs/scenarios/env-2.md`](./docs/scenarios/env-2.md)
53
53
 
@@ -55,10 +55,10 @@ One-time prerequisite: add `https://devtools.aitc.dev/launcher/` to your phone's
55
55
 
56
56
  **Environment 3 — intoss-private** (Toss WebView, HMR off, debug only)
57
57
 
58
- Load a dog-food bundle in the real Toss app WebView and debug it via the MCP relay.
58
+ Load a dog-food bundle in the real Toss app WebView and debug it via the MCP relay. Requires `@ait-co/debugger` — see [Debugging packages](#debugging-packages-environments-2-and-3) below.
59
59
 
60
60
  ```bash
61
- devtools-mcp # start MCP server → QR printed in terminal
61
+ npx -y -p @ait-co/debugger debugger # start MCP server → QR printed in terminal (or `pnpm exec debugger` if it's a devDependency)
62
62
  # ait build && ait deploy --scheme-only
63
63
  # one start_attach(scheme_url) call generates the QR and waits for the phone to attach — scan it and the Toss app loads the bundle + relay attaches
64
64
  ```
@@ -73,7 +73,7 @@ To enable on-device CDP debugging in environments 2 and 3, add **one line** to y
73
73
 
74
74
  ```ts
75
75
  // main.tsx (or the top of your mini-app entry)
76
- import '@ait-co/devtools/in-app/auto';
76
+ import '@ait-co/debug-console/auto';
77
77
  ```
78
78
 
79
79
  What this single line does:
@@ -85,7 +85,9 @@ What this single line does:
85
85
 
86
86
  For environment 3 (intoss-private relay), the relay QR deep-link carries `?debug=1&relay=<wss>` query params, so this one line is all the wiring you need. Environment 2 (PWA, `tunnel: { cdp: true }`) works the same way.
87
87
 
88
- > For dog-food builds with TOTP authentication, inject `__DEBUG_TOTP_SECRET__` via your build define and use `@ait-co/devtools/in-app` directly with `evaluateDebugGate({ verifyTotpCode })` + `maybeAttach()`. `in-app/auto` does not inject a TOTP verifier, so Layer C3 is disabled.
88
+ The old `@ait-co/devtools/in-app/auto` path still resolves in 0.2.x as an inert no-op stub and is removed in 1.0.0 migrate the import to the path above.
89
+
90
+ > For dog-food builds with TOTP authentication, inject `__DEBUG_TOTP_SECRET__` via your build define and use `@ait-co/debug-console` directly with `evaluateDebugGate({ verifyTotpCode })` + `maybeAttach()`. `in-app/auto` does not inject a TOTP verifier, so Layer C3 is disabled.
89
91
 
90
92
  ## Five common problems
91
93
 
@@ -99,7 +101,7 @@ No page has joined the relay yet. Re-enter via `start_attach` → QR scan on you
99
101
 
100
102
  **"Tunnel down" — no response or timeout**
101
103
 
102
- A cloudflared quick tunnel can drop after a few hours. Restart the `devtools-mcp` process to get a new tunnel URL, then scan the new QR. (Related: [#290](https://github.com/apps-in-toss-community/devtools/issues/290))
104
+ A cloudflared quick tunnel can drop after a few hours. Restart the `debugger` process to get a new tunnel URL, then scan the new QR. (Related: [#290](https://github.com/apps-in-toss-community/devtools/issues/290))
103
105
 
104
106
  **"Page crash" — list_pages shows a non-null crashDetectedAt**
105
107
 
@@ -107,7 +109,7 @@ The page on the phone died (OOM, JS exception, or native bridge crash). Relaunch
107
109
 
108
110
  **"SDK not available" — window.__sdkCall not injected**
109
111
 
110
- When `call_sdk` returns `ok: false, error: "window.__sdkCall is not available"`, the SDK bridge has not been installed. Check that `import '@ait-co/devtools/in-app/auto'` is present at the top of your mini-app entry — see the "On-device debugging in one line" section above. This error is the expected result in environment 2 (PWA). (Related: [#285](https://github.com/apps-in-toss-community/devtools/issues/285))
112
+ When `call_sdk` returns `ok: false, error: "window.__sdkCall is not available"`, the SDK bridge has not been installed. Check that `import '@ait-co/debug-console/auto'` is present at the top of your mini-app entry — see the "On-device debugging in one line" section above. This error is the expected result in environment 2 (PWA). (Related: [#285](https://github.com/apps-in-toss-community/devtools/issues/285))
111
113
 
112
114
  **"QR scanned but auth rejected" — TOTP code expired**
113
115
 
@@ -138,6 +140,26 @@ devtools runs two npm dist-tags off the same code at once. Pick the channel that
138
140
 
139
141
  When 3.0 ships GA, the stable `latest` peer moves up to the 3.0 line and the beta channel is retired. Calling an API that devtools has not yet mocked will throw a runtime error — please [file an issue](https://github.com/apps-in-toss-community/devtools/issues) for missing APIs.
140
142
 
143
+ ### Debugging packages (environments 2 and 3)
144
+
145
+ **If you only use environment 1 (local browser + mock + panel), the install above is all you need.** Nothing else to add.
146
+
147
+ For on-device CDP debugging — `tunnel: { cdp: true }` on environment 2, or relay attach on environment 3 — install the two debugging packages as well:
148
+
149
+ ```bash
150
+ pnpm add -D @ait-co/debugger @ait-co/debug-console
151
+ ```
152
+
153
+ | Package | Role | Can enter a bundle |
154
+ |---|---|---|
155
+ | [`@ait-co/debugger`](https://www.npmjs.com/package/@ait-co/debugger) | MCP daemon · real-device test runner · dev-bridge (environment 2 CDP relay + QR dashboard) | No — devDependency / `npx` only |
156
+ | [`@ait-co/debug-console`](https://www.npmjs.com/package/@ait-co/debug-console) | On-device attach + in-app eruda console | Yes — the only one that enters a debug build |
157
+
158
+ Both are **optional peers** of devtools.
159
+
160
+ - Without `@ait-co/debugger`, `tunnel: { cdp: true }` skips the CDP wiring, degrades to the plain screen-preview tunnel, and prints the install hint once.
161
+ - Without `@ait-co/debug-console`, the unplugin injects no in-app attach at all — the attach code cannot structurally enter your bundle, which is the technical boundary of the debug surface.
162
+
141
163
  ## Reference consumer
142
164
 
143
165
  [`sdk-example`](https://github.com/apps-in-toss-community/sdk-example) is the reference consumer of devtools. It's a catalog app where every SDK API can be run interactively, and the web demo is live at <https://sdk-example.aitc.dev/>. When you add a new mock, confirming that it works on the sdk-example card is the first sanity check. That said, this repo's E2E suite runs against an **internal self-contained fixture (`e2e/fixture/`)** without cloning sdk-example — so a broken sdk-example won't affect devtools CI.
@@ -280,7 +302,7 @@ aitDevtools.vite({ tunnel: { cdp: true } }); // real-device preview + on-device
280
302
 
281
303
  ## Production builds
282
304
 
283
- By default, the devtools plugin **automatically disables itself in production** (`NODE_ENV === 'production'` causes both the alias transform and the Panel injection to be skipped). No conditional configuration is needed to keep it safe.
305
+ By default, the devtools plugin **automatically disables itself in production** (`NODE_ENV === 'production'` causes both the alias transform and the Panel injection to be skipped). No conditional configuration is needed to keep it safe. `@ait-co/devtools` is a devDependency, and its contribution to a production bundle is zero bytes. CI enforces this by building a real consumer fixture and grepping the output.
284
306
 
285
307
  To use devtools in a production build — for example in a staging environment — use the `forceEnable` option:
286
308
 
@@ -391,9 +413,9 @@ The launcher **only works when launched as an installed PWA from the home screen
391
413
  >
392
414
  > The `tunnel` option only works in Vite dev mode — no tunnel is started for production builds, even with `forceEnable`. It is silently ignored for other bundlers (Webpack/Rspack, etc.). When the option is enabled, `cloudflared` and `qrcode-terminal` are loaded via dynamic import only, so they do not appear in the bundle graph when the option is off.
393
415
 
394
- ### One-line setup (planned)
416
+ ### One-line setup
395
417
 
396
- The per-project steps above (vite.config patch + `onlyBuiltDependencies` + `dev:phone` script) are planned to be absorbed into a single command like `/ait setup phone` in the future [`agent-plugin`](https://github.com/apps-in-toss-community/agent-plugin) (command name is tentative). Since this README serves as the spec for that automation, the manual steps will remain documented here even after automation is available.
418
+ The per-project steps above (vite.config patch + `onlyBuiltDependencies` + `dev:phone` script) are automated by a single [`agent-plugin`](https://github.com/apps-in-toss-community/agent-plugin) command, `/ait:setup-phone-preview`. Since this README serves as the spec for that automation, the manual steps stay documented here alongside it.
397
419
 
398
420
  ## Device API mode system
399
421
 
@@ -621,6 +643,7 @@ __ait.update({ networkStatus: 'OFFLINE' });
621
643
  __ait.patch('permissions', { camera: 'denied' });
622
644
  __ait.patch('deviceModes', { location: 'web' });
623
645
  __ait.patch('iap', { nextResult: 'USER_CANCELED' });
646
+ __ait.patch('failureModes', { loadAdMob: 'PLACEMENT_ID_FETCH_FAILED' }); // reproduce a real-device ad placement lookup failure
624
647
 
625
648
  // Trigger events
626
649
  __ait.trigger('backEvent');
@@ -735,6 +758,8 @@ unsubscribe(); // unsubscribe
735
758
  | `TossAds.destroy/destroyAll` | No-op |
736
759
  | `loadFullScreenAd` / `showFullScreenAd` | Similar flow to GoogleAdMob |
737
760
 
761
+ > Unless a failure dial is set (`failureModes.loadAdMob`, panel `forceNoFill`), the events above fire the same way every time — the mock does not use `adGroupId` to decide the outcome, and it does not model a server-side placement-resolution step. A real device can fail placement lookup itself before any ad exists (e.g. `PLACEMENT_ID_FETCH_FAILED`) and reject immediately, so a mock `loaded` event is not a signal that an ad will actually serve on a real device. To reproduce this failure locally: `__ait.patch('failureModes', { loadAdMob: 'PLACEMENT_ID_FETCH_FAILED' })`.
762
+
738
763
  ### Events
739
764
 
740
765
  | API | Mock behavior |
@@ -842,6 +867,19 @@ it('can write and read from Storage', async () => {
842
867
  });
843
868
  ```
844
869
 
870
+ ## On-device test runner (`debugger-test`)
871
+
872
+ "Using in tests" above verifies mocks in desktop jsdom. The runner that runs the same style of tests **against the real SDK inside the Toss app WebView on a real phone (environment 3)** moved to `@ait-co/debugger` (#818) — the bin is now `debugger-test`, renamed from `devtools-test`.
873
+
874
+ ```bash
875
+ pnpm add -D @ait-co/debugger
876
+ pnpm exec debugger-test 'src/**/*.ait.test.ts' \
877
+ --scheme-url "intoss-private://my-mini-app?_deploymentId=<uuid>" \
878
+ --cell-sdk-line 3.x --cell-platform ios --report-dir .ait-report
879
+ ```
880
+
881
+ The full flag reference, QR-scan procedure, and artifact layout are now documented in `@ait-co/debugger` — see `debugger-test --help`. The one line this package still owns is the mini-app entry point: `import '@ait-co/debug-console/auto'` ([section above](#on-device-debugging-in-one-line)).
882
+
845
883
  ## SDK update tracking
846
884
 
847
885
  devtools tracks [`@apps-in-toss/web-framework`](https://www.npmjs.com/package/@apps-in-toss/web-framework), and [`sdk-example`](https://github.com/apps-in-toss-community/sdk-example) tracks both the original SDK and devtools. When a new SDK version is released, the flow is: (1) devtools catches up on mock/type signatures → (2) sdk-example incorporates both new versions together. If a devtools-only PR breaks sdk-example, both are addressed together.
@@ -956,176 +994,40 @@ import '@ait-co/devtools/panel';
956
994
 
957
995
  ## MCP Server
958
996
 
959
- 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.
960
-
961
- A local browser (env 1) and a phone Toss WebView (env 2/3) both speak CDP, so every tool works identically in both environments — the only difference is the attach strategy (`--target=relay` vs `--target=local`).
962
-
963
- | Mode + target | Invocation | Env vars | Target | Tools |
964
- |---|---|---|---|---|
965
- | `--target=mobile` (env 2) | `devtools-mcp` → `start_debug({mode:'relay-sandbox'})` | `AIT_RELAY_BASE_URL`, `AIT_TUNNEL_BASE_URL` | Real-device Safari/WebKit PWA (external Chii relay + cloudflared tunnel, env 2) | console/network/page + DOM/snapshot/screenshot |
966
- | `--mode=debug --target=relay` (default, env 3) | `devtools-mcp` → `start_debug({mode: 'relay-staging'})` | — | Dog-food bundle on a phone (CDP/Chii relay + cloudflared tunnel, env 3) | same + `AIT.*` |
967
- | `--mode=debug --target=local` (env 1) | `devtools-mcp --target=local` | `MCP_ENV=mock` (auto) | Local Chromium launched by the MCP server (CDP direct-attach, no relay needed, env 1) | same |
968
- | `--mode=dev` | `devtools-mcp --mode=dev` | `MCP_ENV=mock` (auto) | Mock state from a running Vite dev server (AIT.* only, no CDP) | `AIT.*` (+ `devtools_get_mock_state` alias) |
969
-
970
- `--target=local` opens `AIT_DEVTOOLS_URL` (default `http://localhost:5173`) and attaches directly to a local Chromium — no relay or tunnel required. `--mode=dev` reads the mock-state HTTP endpoint of the Vite dev server and does not provide CDP tools. Switch environments in-session with `start_debug(mode)`: `relay-sandbox` (env 2 PWA), `relay-staging` (env 3 dogfood), `local-browser` (env 1).
971
-
972
- #### Environment 2 (real-device PWA CDP) — `--target=mobile`
973
-
974
- Debug on a real phone using Safari/WebKit without Toss review. The Vite dev server with [`tunnel:{cdp:true}`](#tunnel-option) brings up both an app HTTP tunnel and a Chii relay tunnel. The MCP server attaches to that relay and provides `start_attach` → launcher QR.
975
-
976
- **Setup procedure:**
977
-
978
- 1. Start the Vite dev server in CDP tunnel mode:
979
- ```bash
980
- AIT_TUNNEL_CDP=1 pnpm exec vite --config e2e/fixture/vite.config.ts
981
- ```
982
- The terminal banner prints two URLs:
983
- - **App HTTP tunnel** `https://<A>.trycloudflare.com` → set as `AIT_TUNNEL_BASE_URL`
984
- - **Relay wss tunnel** `wss://<B>.trycloudflare.com` → set `AIT_RELAY_BASE_URL` to its `https://` form
985
-
986
- 2. Start the MCP server in mobile mode (separate terminal):
987
- ```json
988
- {
989
- "mcpServers": {
990
- "ait-debug": {
991
- "command": "npx",
992
- "args": ["-y", "@ait-co/devtools", "devtools-mcp"],
993
- "env": {
994
- "AIT_RELAY_BASE_URL": "https://<B>.trycloudflare.com",
995
- "AIT_TUNNEL_BASE_URL": "https://<A>.trycloudflare.com"
996
- }
997
- }
998
- }
999
- }
1000
- ```
1001
-
1002
- 3. In a Claude Code session:
1003
- ```
1004
- start_debug({mode: 'relay-sandbox'})
1005
- start_attach()
1006
- ```
1007
- Scan the QR with your phone camera. The launcher PWA opens the app in a frame and injects Chii target.js.
1008
-
1009
- 4. `list_pages()` → expect one page. Use `take_screenshot()` and other CDP tools.
1010
-
1011
- **Env 2 fidelity boundary**: uses the mock SDK (`call_sdk` hits the mock). For real SDK fidelity, move to env 3. CDP runs on the real WebKit engine, so DOM, console, and screenshot reflect the real device screen.
1012
-
1013
- **Local-PC verification**: `e2e/launcher-cdp.test.ts` automates node-side relay startup (`startChiiRelay({port:0})`) and launcher param forwarding (Playwright). Browser-side Chii target.js injection is not automated in CI due to the localhost host gate (Layer B1) and ws:// vs wss:// constraints — completed by the manual procedure above on a real device with a trycloudflare.com hostname.
1014
-
1015
- ### Debug mode (CDP via Chii)
1016
-
1017
- For a step-by-step walkthrough of the on-device relay debug loop (dog-food build → QR scan → relay attach) including common failure recovery, see **[`docs/dogfood-relay-loop.md`](./docs/dogfood-relay-loop.md)** (Korean). For crash triage — `list_pages.crashDetectedAt`, iOS Console.app `.ips` analysis, and the redact procedure — see **[`docs/crash-triage.md`](./docs/crash-triage.md)** (Korean).
1018
-
1019
- Read-only tools only. Tools are registered in two tiers based on attach state — before attach, only the bootstrap tools (`start_attach`, `list_pages`) are visible; once a relay/local page attaches, the attach-dependent tools are registered dynamically in the same session via `notifications/tools/list_changed` (no session restart needed). The phone attach roundtrip is fully wired; all that remains is a single on-device acceptance run. The tool layer is CI-verified via a mockable injectable CDP connection / AIT source.
1020
-
1021
- Running `devtools-mcp` as a stdio server starts a local Chii relay on an OS-assigned port and opens a cloudflared quick tunnel, printing a public `wss://*.trycloudflare.com` URL and a QR code in the terminal (secrets/auth codes are never printed). When the phone enters the dog-food entry point, the in-app attach UI connects to the relay with that URL, and the agent reads console/network/page state via `chrome-devtools-mcp`-compatible tools — diagnosing regressions without anyone watching the phone.
1022
-
1023
- Environment 3 (intoss-private relay) — start `devtools-mcp` as-is, then enter via `start_debug(mode)`:
997
+ The MCP surface (daemon, attach, CDP tools) moved to `@ait-co/debugger` (#818). Point your agent's registration at debugger, not devtools:
1024
998
 
1025
999
  ```json
1026
1000
  {
1027
1001
  "mcpServers": {
1028
1002
  "ait-debug": {
1029
- "command": "pnpm",
1030
- "args": ["exec", "devtools-mcp"]
1003
+ "command": "npx",
1004
+ "args": ["-y", "-p", "@ait-co/debugger", "debugger"]
1031
1005
  }
1032
1006
  }
1033
1007
  }
1034
1008
  ```
1035
1009
 
1036
- - Environment 3 (dog-food relay): `start_debug({mode: 'relay-staging'})`
1037
- **`start_debug(mode)` is the single in-session entry path.**
1038
-
1039
- | Tool | CDP / AIT backing | Description |
1040
- |---|---|---|
1041
- | `list_console_messages` | `Runtime.consoleAPICalled` | Recent console.log/warn/error messages (level, text, timestamp, args) |
1042
- | `list_network_requests` | `Network.requestWillBeSent` + `responseReceived` | Recent XHR/fetch requests (url, method, status, timing) |
1043
- | `list_pages` | Chii relay target list | Attached pages + tunnel status + wss URL |
1044
- | `start_attach` | (pure synthesis + attach wait) | Splices `debug=1` + the relay URL into an `ait deploy --scheme-only` URL, prints a QR, then waits in the same call until the phone attaches (QR generation and attach in one call). A `mode` arg can switch the session environment too, and the TOTP code is re-minted automatically during the wait. Entry tool for env 2 and 3 (bootstrap) — no `list_pages` needed first |
1045
- | `get_dom_document` | `DOM.getDocument` | DOM tree read (structural/layout regression diagnosis) |
1046
- | `take_snapshot` | `DOMSnapshot.captureSnapshot` | Page snapshot (documents + interned strings, visual regression) |
1047
- | `take_screenshot` | `Page.captureScreenshot` | Page PNG screenshot (returned as an MCP image content block) |
1048
- | `measure_safe_area` | `Runtime.evaluate` | Runs a safe-area probe on the attached page → returns normalized safe-area insets, viewport geometry, DPR, and User-Agent. Read-only. Use in a relay session to get ground-truth values for upgrading a viewport preset from extrapolated/placeholder to measured. Requires attach (`list_pages` first) |
1049
- | `evaluate` | `Runtime.evaluate` | Evaluates an arbitrary JS expression on the attached page (returnByValue) and returns the result. **Not read-only** — the expression can have side effects (DOM mutations, SDK calls, state changes). Requires attach |
1050
- | `call_sdk` | `window.__sdkCall` bridge (via `Runtime.evaluate`) | Calls a dog-food SDK method via the `window.__sdkCall` bridge (exported by `@apps-in-toss/web-framework` in `__DEBUG_BUILD__` bundles only). **Not read-only** — SDK calls have side effects (navigation, payments, permissions, etc.). Hits the real SDK on env 3, mock SDK on env 1. Env 2 (PWA) does not inject the SDK — not available there. Requires attach. Returns `{ok,value}` / `{ok,error}` |
1051
- | `AIT.getSdkCallHistory` | AIT domain | SDK call trace (method, args, result/error, timestamp) |
1052
- | `AIT.getMockState` | AIT domain | Mock state snapshot (`window.__ait`) |
1053
- | `AIT.getOperationalEnvironment` | AIT domain | `getOperationalEnvironment()` + SDK version |
1054
-
1055
- `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.
1056
-
1057
- ### Dev mode (mock state)
1058
-
1059
- `devtools-mcp --mode=dev` reads the mock state from a running browser. It shares the same `AIT.*` tool surface as debug mode.
1060
-
1061
- #### Architecture
1062
-
1063
- ```
1064
- Browser (aitState)
1065
- └─ POST /api/ait-devtools/state (auto-pushed by the panel on every state change)
1066
- └─ Vite dev server (unplugin with mcp: true)
1067
- └─ GET /api/ait-devtools/state
1068
- └─ MCP stdio server (dist/mcp/server.js)
1069
- └─ AI agent (AIT.getMockState tool)
1070
- ```
1071
-
1072
- #### Setup
1073
-
1074
- **1. Add `mcp: true` to the Vite plugin**
1075
-
1076
- ```ts
1077
- // vite.config.ts
1078
- import aitDevtools from '@ait-co/devtools/unplugin';
1079
-
1080
- export default {
1081
- plugins: [aitDevtools.vite({ mcp: true })],
1082
- };
1083
- ```
1084
-
1085
- **2. Configure your MCP client (e.g. Claude Code `.claude/settings.json`)**
1086
-
1087
- ```json
1088
- {
1089
- "mcpServers": {
1090
- "ait-devtools": {
1091
- "command": "pnpm",
1092
- "args": ["exec", "devtools-mcp", "--mode=dev"],
1093
- "env": {
1094
- "AIT_DEVTOOLS_URL": "http://localhost:5173"
1095
- }
1096
- }
1097
- }
1098
- }
1099
- ```
1100
-
1101
- `AIT_DEVTOOLS_URL` defaults to `http://localhost:5173` — you can omit it if you're using the default port.
1102
-
1103
- **3. Open the app in your browser, then call the tool from your AI agent**
1104
-
1105
- ```
1106
- > AIT.getMockState
1107
- ```
1108
-
1109
- Returns the full current mock state (permissions, location, auth, network, IAP, etc.) as JSON.
1110
-
1111
- | Tool | Description |
1112
- |---|---|
1113
- | `AIT.getMockState` | Returns the current `AitDevtoolsState` snapshot (read-only) |
1114
- | `AIT.getOperationalEnvironment` | Environment + version derived from the mock state's `environment` + `appVersion` |
1115
- | `AIT.getSdkCallHistory` | Empty in dev mode (the HTTP endpoint records no trace) |
1116
- | `devtools_get_mock_state` | Backward-compatible alias of `AIT.getMockState` (prefer `AIT.getMockState` in new configs) |
1010
+ What this gives you: CDP observation of a running mini-app across environments 1 (local browser), 2 (PWA), and 3 (intoss-private WebView) — console, network, DOM, snapshot, screenshot — plus `start_attach` for on-device entry in environments 2/3. The full tool list, mode/target matrix, and per-environment config live in the [`@ait-co/debugger`](https://www.npmjs.com/package/@ait-co/debugger) package docs.
1117
1011
 
1118
1012
  ## Package export structure
1119
1013
 
1014
+ The entry points this package actually ships:
1015
+
1120
1016
  | Import path | Purpose |
1121
1017
  |---|---|
1122
- | `@ait-co/devtools` or `@ait-co/devtools/mock` | All mock exports (bundler alias target) |
1018
+ | `@ait-co/devtools` (= `/mock`) | Bundler alias target, all mock exports |
1123
1019
  | `@ait-co/devtools/panel` | Floating DevTools Panel (auto-mounts on import) |
1124
1020
  | `@ait-co/devtools/unplugin` | Bundler plugin (.vite, .webpack, .rspack, .esbuild, .rollup) |
1125
- | `@ait-co/devtools/mcp/server` | Dev-mode MCP stdio server function (Node.js) |
1126
- | `@ait-co/devtools/mcp/cli` | `devtools-mcp` bin entry point (debug / dev mode, Node.js) |
1127
- | `@ait-co/devtools/in-app` | In-app debug attach — runtime gate (layers B/C) + Chii target.js injection. The consumer wraps the import in `if (__DEBUG_BUILD__)` so it is DCE'd from release builds — dog-food builds only |
1128
- | `@ait-co/devtools/in-app/auto` | Self-gating side-effect entry a single `import '@ait-co/devtools/in-app/auto'` line wires attach + SDK bridge. Active only when `?debug=1` / `?relay=` are in the URL or it is a DEV build; stays dormant on normal production loads. See the [section above](#on-device-debugging-in-one-line) |
1021
+
1022
+ Everything below is a **transition stub** it exists only in 0.2.x and is removed in 1.0.0 (#818). Migrate to the new package.
1023
+
1024
+ | Import path | New home | On import |
1025
+ |---|---|---|
1026
+ | `@ait-co/devtools/mcp/server` | `@ait-co/debugger/mcp/server` | throws |
1027
+ | `@ait-co/devtools/mcp/cli` | `@ait-co/debugger/mcp/cli` | throws |
1028
+ | `@ait-co/devtools/test-runner` | `@ait-co/debugger/test-runner` | throws |
1029
+ | `@ait-co/devtools/in-app` | `@ait-co/debug-console` | no-op + one `console.error` |
1030
+ | `@ait-co/devtools/in-app/auto` | `@ait-co/debug-console/auto` | no-op + one `console.error` |
1129
1031
 
1130
1032
  ## License
1131
1033