@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
@@ -0,0 +1,131 @@
1
+ //#region src/unplugin/optional-peers.ts
2
+ /**
3
+ * Optional-peer resolution gates for the debug surface (issue #817).
4
+ *
5
+ * The debug surface now ships as two SEPARATE packages, declared here as
6
+ * OPTIONAL peerDependencies of `@ait-co/devtools`:
7
+ *
8
+ * - `@ait-co/debugger` — MCP daemon / test runner / dev-bridge. devDependency
9
+ * or `npx` only; never part of an app bundle.
10
+ * - `@ait-co/debug-console` — on-device attach + eruda console. The ONLY debug
11
+ * package that can legitimately enter an app bundle.
12
+ *
13
+ * Neither may become a hard dependency. The overwhelming majority of consumers
14
+ * use environment 1 only (browser + mock SDK + panel) and must install NOTHING
15
+ * extra — that is the whole point of splitting the packages apart. So every
16
+ * call site reaches them through the resolution gates below and degrades
17
+ * gracefully when they are absent:
18
+ *
19
+ * - env-2 CDP wiring (`tunnel.cdp`) → falls back to the plain screen-preview
20
+ * tunnel (no relay, no dashboard) and prints {@link INSTALL_HINT}.
21
+ * - in-app attach injection → the snippet is simply not injected, so the
22
+ * attach code is STRUCTURALLY ABSENT from the bundle rather than merely
23
+ * gated at runtime. This gate is the technical enforcement point of the
24
+ * debug surface's security scope: no `@ait-co/debug-console` installed
25
+ * means no attach code can reach a bundle at all.
26
+ *
27
+ * The `import.meta.resolve` probe follows the `MOCK_PATH` precedent in
28
+ * `./index.ts`: resolution is attempted once at plugin-load time and a failure
29
+ * is a plain "not installed" signal, never an error.
30
+ *
31
+ * SECRET-HANDLING: nothing here touches a relay URL, tunnel host, TOTP secret
32
+ * or code. The only strings emitted are fixed specifiers and the install hint.
33
+ */
34
+ /** Subpath of `@ait-co/debugger` that the unplugin's dev loop delegates to. */
35
+ const DEBUGGER_DEV_BRIDGE_ID = "@ait-co/debugger/dev-bridge";
36
+ /** The on-device attach package injected into a consumer entry point. */
37
+ const DEBUG_CONSOLE_ID = "@ait-co/debug-console";
38
+ /** One-line install hint printed whenever a gate closes on a missing package. */
39
+ const INSTALL_HINT = "pnpm add -D @ait-co/debugger @ait-co/debug-console";
40
+ /**
41
+ * Returns whether `specifier` resolves from this package's location.
42
+ *
43
+ * `import.meta.resolve` throws (rather than returning a falsy value) for an
44
+ * unresolvable specifier, and is itself absent on a few older runtimes — both
45
+ * are treated as "not installed", which is the safe direction: the caller then
46
+ * takes the degraded path instead of importing something that is not there.
47
+ */
48
+ function canResolveOptionalPeer(specifier) {
49
+ try {
50
+ return typeof {}.resolve(specifier) === "string";
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
55
+ /** Whether `@ait-co/debugger`'s dev-bridge is installed (env-2 CDP path). */
56
+ function hasDebugger() {
57
+ return canResolveOptionalPeer(DEBUGGER_DEV_BRIDGE_ID);
58
+ }
59
+ /** Whether `@ait-co/debug-console` is installed (in-app attach injection). */
60
+ function hasDebugConsole() {
61
+ return canResolveOptionalPeer(DEBUG_CONSOLE_ID);
62
+ }
63
+ /**
64
+ * Whether `code` already wires the in-app debug attach itself.
65
+ *
66
+ * Both the current (`@ait-co/debug-console`) and the pre-split
67
+ * (`@ait-co/devtools/in-app`) specifier count, so a consumer who wired either
68
+ * one by hand never gets a duplicate auto-injection.
69
+ */
70
+ function hasInAppWiring(code) {
71
+ return code.includes("@ait-co/debug-console") || code.includes("@ait-co/devtools/in-app");
72
+ }
73
+ /**
74
+ * The gated dynamic-import snippet prepended to a consumer entry point.
75
+ *
76
+ * The runtime gate (`?debug=1` + a `relay` param) keeps the chunk unloaded on a
77
+ * normal page load, and a production build dead-code-eliminates it. The
78
+ * build-time gate is {@link hasDebugConsole} at the call site: when the package
79
+ * is absent this snippet is never produced, so the attach code cannot be in the
80
+ * bundle at all.
81
+ */
82
+ function buildInAppSnippet() {
83
+ return [
84
+ "// @ait-co/devtools: in-app attach auto-injected by unplugin — 수동 배선 불필요",
85
+ "if (typeof window !== 'undefined') {",
86
+ " const __ait_p = new URLSearchParams(window.location.search);",
87
+ " if (__ait_p.get('debug') === '1' && __ait_p.get('relay')) {",
88
+ ` void import('${DEBUG_CONSOLE_ID}').then((m) => m.maybeAttach());`,
89
+ " }",
90
+ "}"
91
+ ].join("\n");
92
+ }
93
+ //#endregion
94
+ Object.defineProperty(exports, "DEBUGGER_DEV_BRIDGE_ID", {
95
+ enumerable: true,
96
+ get: function() {
97
+ return DEBUGGER_DEV_BRIDGE_ID;
98
+ }
99
+ });
100
+ Object.defineProperty(exports, "INSTALL_HINT", {
101
+ enumerable: true,
102
+ get: function() {
103
+ return INSTALL_HINT;
104
+ }
105
+ });
106
+ Object.defineProperty(exports, "buildInAppSnippet", {
107
+ enumerable: true,
108
+ get: function() {
109
+ return buildInAppSnippet;
110
+ }
111
+ });
112
+ Object.defineProperty(exports, "hasDebugConsole", {
113
+ enumerable: true,
114
+ get: function() {
115
+ return hasDebugConsole;
116
+ }
117
+ });
118
+ Object.defineProperty(exports, "hasDebugger", {
119
+ enumerable: true,
120
+ get: function() {
121
+ return hasDebugger;
122
+ }
123
+ });
124
+ Object.defineProperty(exports, "hasInAppWiring", {
125
+ enumerable: true,
126
+ get: function() {
127
+ return hasInAppWiring;
128
+ }
129
+ });
130
+
131
+ //# sourceMappingURL=optional-peers-CDEFhlhJ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-peers-CDEFhlhJ.cjs","names":[],"sources":["../src/unplugin/optional-peers.ts"],"sourcesContent":["/**\n * Optional-peer resolution gates for the debug surface (issue #817).\n *\n * The debug surface now ships as two SEPARATE packages, declared here as\n * OPTIONAL peerDependencies of `@ait-co/devtools`:\n *\n * - `@ait-co/debugger` — MCP daemon / test runner / dev-bridge. devDependency\n * or `npx` only; never part of an app bundle.\n * - `@ait-co/debug-console` — on-device attach + eruda console. The ONLY debug\n * package that can legitimately enter an app bundle.\n *\n * Neither may become a hard dependency. The overwhelming majority of consumers\n * use environment 1 only (browser + mock SDK + panel) and must install NOTHING\n * extra — that is the whole point of splitting the packages apart. So every\n * call site reaches them through the resolution gates below and degrades\n * gracefully when they are absent:\n *\n * - env-2 CDP wiring (`tunnel.cdp`) → falls back to the plain screen-preview\n * tunnel (no relay, no dashboard) and prints {@link INSTALL_HINT}.\n * - in-app attach injection → the snippet is simply not injected, so the\n * attach code is STRUCTURALLY ABSENT from the bundle rather than merely\n * gated at runtime. This gate is the technical enforcement point of the\n * debug surface's security scope: no `@ait-co/debug-console` installed\n * means no attach code can reach a bundle at all.\n *\n * The `import.meta.resolve` probe follows the `MOCK_PATH` precedent in\n * `./index.ts`: resolution is attempted once at plugin-load time and a failure\n * is a plain \"not installed\" signal, never an error.\n *\n * SECRET-HANDLING: nothing here touches a relay URL, tunnel host, TOTP secret\n * or code. The only strings emitted are fixed specifiers and the install hint.\n */\n\n/** Subpath of `@ait-co/debugger` that the unplugin's dev loop delegates to. */\nexport const DEBUGGER_DEV_BRIDGE_ID = '@ait-co/debugger/dev-bridge';\n\n/** The on-device attach package injected into a consumer entry point. */\nexport const DEBUG_CONSOLE_ID = '@ait-co/debug-console';\n\n/**\n * The pre-split in-app specifier. Still recognised for DEDUPE only — a consumer\n * who wired `@ait-co/devtools/in-app` by hand must not also receive the new\n * auto-injected snippet. It is never injected any more.\n */\nexport const LEGACY_IN_APP_ID = '@ait-co/devtools/in-app';\n\n/** One-line install hint printed whenever a gate closes on a missing package. */\nexport const INSTALL_HINT = 'pnpm add -D @ait-co/debugger @ait-co/debug-console';\n\n/**\n * Returns whether `specifier` resolves from this package's location.\n *\n * `import.meta.resolve` throws (rather than returning a falsy value) for an\n * unresolvable specifier, and is itself absent on a few older runtimes — both\n * are treated as \"not installed\", which is the safe direction: the caller then\n * takes the degraded path instead of importing something that is not there.\n */\nexport function canResolveOptionalPeer(specifier: string): boolean {\n try {\n return typeof import.meta.resolve(specifier) === 'string';\n } catch {\n return false;\n }\n}\n\n/** Whether `@ait-co/debugger`'s dev-bridge is installed (env-2 CDP path). */\nexport function hasDebugger(): boolean {\n return canResolveOptionalPeer(DEBUGGER_DEV_BRIDGE_ID);\n}\n\n/** Whether `@ait-co/debug-console` is installed (in-app attach injection). */\nexport function hasDebugConsole(): boolean {\n return canResolveOptionalPeer(DEBUG_CONSOLE_ID);\n}\n\n/**\n * Whether `code` already wires the in-app debug attach itself.\n *\n * Both the current (`@ait-co/debug-console`) and the pre-split\n * (`@ait-co/devtools/in-app`) specifier count, so a consumer who wired either\n * one by hand never gets a duplicate auto-injection.\n */\nexport function hasInAppWiring(code: string): boolean {\n return code.includes(DEBUG_CONSOLE_ID) || code.includes(LEGACY_IN_APP_ID);\n}\n\n/**\n * The gated dynamic-import snippet prepended to a consumer entry point.\n *\n * The runtime gate (`?debug=1` + a `relay` param) keeps the chunk unloaded on a\n * normal page load, and a production build dead-code-eliminates it. The\n * build-time gate is {@link hasDebugConsole} at the call site: when the package\n * is absent this snippet is never produced, so the attach code cannot be in the\n * bundle at all.\n */\nexport function buildInAppSnippet(): string {\n return [\n '// @ait-co/devtools: in-app attach auto-injected by unplugin — 수동 배선 불필요',\n \"if (typeof window !== 'undefined') {\",\n ' const __ait_p = new URLSearchParams(window.location.search);',\n \" if (__ait_p.get('debug') === '1' && __ait_p.get('relay')) {\",\n ` void import('${DEBUG_CONSOLE_ID}').then((m) => m.maybeAttach());`,\n ' }',\n '}',\n ].join('\\n');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,MAAa,yBAAyB;;AAGtC,MAAa,mBAAmB;;AAUhC,MAAa,eAAe;;;;;;;;;AAU5B,SAAgB,uBAAuB,WAA4B;AACjE,KAAI;AACF,SAAO,OAAA,EAAA,CAAmB,QAAQ,UAAU,KAAK;SAC3C;AACN,SAAO;;;;AAKX,SAAgB,cAAuB;AACrC,QAAO,uBAAuB,uBAAuB;;;AAIvD,SAAgB,kBAA2B;AACzC,QAAO,uBAAuB,iBAAiB;;;;;;;;;AAUjD,SAAgB,eAAe,MAAuB;AACpD,QAAO,KAAK,SAAA,wBAA0B,IAAI,KAAK,SAAA,0BAA0B;;;;;;;;;;;AAY3E,SAAgB,oBAA4B;AAC1C,QAAO;EACL;EACA;EACA;EACA;EACA,oBAAoB,iBAAiB;EACrC;EACA;EACD,CAAC,KAAK,KAAK"}
@@ -0,0 +1,96 @@
1
+ //#region src/unplugin/optional-peers.ts
2
+ /**
3
+ * Optional-peer resolution gates for the debug surface (issue #817).
4
+ *
5
+ * The debug surface now ships as two SEPARATE packages, declared here as
6
+ * OPTIONAL peerDependencies of `@ait-co/devtools`:
7
+ *
8
+ * - `@ait-co/debugger` — MCP daemon / test runner / dev-bridge. devDependency
9
+ * or `npx` only; never part of an app bundle.
10
+ * - `@ait-co/debug-console` — on-device attach + eruda console. The ONLY debug
11
+ * package that can legitimately enter an app bundle.
12
+ *
13
+ * Neither may become a hard dependency. The overwhelming majority of consumers
14
+ * use environment 1 only (browser + mock SDK + panel) and must install NOTHING
15
+ * extra — that is the whole point of splitting the packages apart. So every
16
+ * call site reaches them through the resolution gates below and degrades
17
+ * gracefully when they are absent:
18
+ *
19
+ * - env-2 CDP wiring (`tunnel.cdp`) → falls back to the plain screen-preview
20
+ * tunnel (no relay, no dashboard) and prints {@link INSTALL_HINT}.
21
+ * - in-app attach injection → the snippet is simply not injected, so the
22
+ * attach code is STRUCTURALLY ABSENT from the bundle rather than merely
23
+ * gated at runtime. This gate is the technical enforcement point of the
24
+ * debug surface's security scope: no `@ait-co/debug-console` installed
25
+ * means no attach code can reach a bundle at all.
26
+ *
27
+ * The `import.meta.resolve` probe follows the `MOCK_PATH` precedent in
28
+ * `./index.ts`: resolution is attempted once at plugin-load time and a failure
29
+ * is a plain "not installed" signal, never an error.
30
+ *
31
+ * SECRET-HANDLING: nothing here touches a relay URL, tunnel host, TOTP secret
32
+ * or code. The only strings emitted are fixed specifiers and the install hint.
33
+ */
34
+ /** Subpath of `@ait-co/debugger` that the unplugin's dev loop delegates to. */
35
+ const DEBUGGER_DEV_BRIDGE_ID = "@ait-co/debugger/dev-bridge";
36
+ /** The on-device attach package injected into a consumer entry point. */
37
+ const DEBUG_CONSOLE_ID = "@ait-co/debug-console";
38
+ /** One-line install hint printed whenever a gate closes on a missing package. */
39
+ const INSTALL_HINT = "pnpm add -D @ait-co/debugger @ait-co/debug-console";
40
+ /**
41
+ * Returns whether `specifier` resolves from this package's location.
42
+ *
43
+ * `import.meta.resolve` throws (rather than returning a falsy value) for an
44
+ * unresolvable specifier, and is itself absent on a few older runtimes — both
45
+ * are treated as "not installed", which is the safe direction: the caller then
46
+ * takes the degraded path instead of importing something that is not there.
47
+ */
48
+ function canResolveOptionalPeer(specifier) {
49
+ try {
50
+ return typeof import.meta.resolve(specifier) === "string";
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
55
+ /** Whether `@ait-co/debugger`'s dev-bridge is installed (env-2 CDP path). */
56
+ function hasDebugger() {
57
+ return canResolveOptionalPeer(DEBUGGER_DEV_BRIDGE_ID);
58
+ }
59
+ /** Whether `@ait-co/debug-console` is installed (in-app attach injection). */
60
+ function hasDebugConsole() {
61
+ return canResolveOptionalPeer(DEBUG_CONSOLE_ID);
62
+ }
63
+ /**
64
+ * Whether `code` already wires the in-app debug attach itself.
65
+ *
66
+ * Both the current (`@ait-co/debug-console`) and the pre-split
67
+ * (`@ait-co/devtools/in-app`) specifier count, so a consumer who wired either
68
+ * one by hand never gets a duplicate auto-injection.
69
+ */
70
+ function hasInAppWiring(code) {
71
+ return code.includes("@ait-co/debug-console") || code.includes("@ait-co/devtools/in-app");
72
+ }
73
+ /**
74
+ * The gated dynamic-import snippet prepended to a consumer entry point.
75
+ *
76
+ * The runtime gate (`?debug=1` + a `relay` param) keeps the chunk unloaded on a
77
+ * normal page load, and a production build dead-code-eliminates it. The
78
+ * build-time gate is {@link hasDebugConsole} at the call site: when the package
79
+ * is absent this snippet is never produced, so the attach code cannot be in the
80
+ * bundle at all.
81
+ */
82
+ function buildInAppSnippet() {
83
+ return [
84
+ "// @ait-co/devtools: in-app attach auto-injected by unplugin — 수동 배선 불필요",
85
+ "if (typeof window !== 'undefined') {",
86
+ " const __ait_p = new URLSearchParams(window.location.search);",
87
+ " if (__ait_p.get('debug') === '1' && __ait_p.get('relay')) {",
88
+ ` void import('${DEBUG_CONSOLE_ID}').then((m) => m.maybeAttach());`,
89
+ " }",
90
+ "}"
91
+ ].join("\n");
92
+ }
93
+ //#endregion
94
+ export { hasDebugger as a, hasDebugConsole as i, INSTALL_HINT as n, hasInAppWiring as o, buildInAppSnippet as r, DEBUGGER_DEV_BRIDGE_ID as t };
95
+
96
+ //# sourceMappingURL=optional-peers-FdVbUJst.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-peers-FdVbUJst.js","names":[],"sources":["../src/unplugin/optional-peers.ts"],"sourcesContent":["/**\n * Optional-peer resolution gates for the debug surface (issue #817).\n *\n * The debug surface now ships as two SEPARATE packages, declared here as\n * OPTIONAL peerDependencies of `@ait-co/devtools`:\n *\n * - `@ait-co/debugger` — MCP daemon / test runner / dev-bridge. devDependency\n * or `npx` only; never part of an app bundle.\n * - `@ait-co/debug-console` — on-device attach + eruda console. The ONLY debug\n * package that can legitimately enter an app bundle.\n *\n * Neither may become a hard dependency. The overwhelming majority of consumers\n * use environment 1 only (browser + mock SDK + panel) and must install NOTHING\n * extra — that is the whole point of splitting the packages apart. So every\n * call site reaches them through the resolution gates below and degrades\n * gracefully when they are absent:\n *\n * - env-2 CDP wiring (`tunnel.cdp`) → falls back to the plain screen-preview\n * tunnel (no relay, no dashboard) and prints {@link INSTALL_HINT}.\n * - in-app attach injection → the snippet is simply not injected, so the\n * attach code is STRUCTURALLY ABSENT from the bundle rather than merely\n * gated at runtime. This gate is the technical enforcement point of the\n * debug surface's security scope: no `@ait-co/debug-console` installed\n * means no attach code can reach a bundle at all.\n *\n * The `import.meta.resolve` probe follows the `MOCK_PATH` precedent in\n * `./index.ts`: resolution is attempted once at plugin-load time and a failure\n * is a plain \"not installed\" signal, never an error.\n *\n * SECRET-HANDLING: nothing here touches a relay URL, tunnel host, TOTP secret\n * or code. The only strings emitted are fixed specifiers and the install hint.\n */\n\n/** Subpath of `@ait-co/debugger` that the unplugin's dev loop delegates to. */\nexport const DEBUGGER_DEV_BRIDGE_ID = '@ait-co/debugger/dev-bridge';\n\n/** The on-device attach package injected into a consumer entry point. */\nexport const DEBUG_CONSOLE_ID = '@ait-co/debug-console';\n\n/**\n * The pre-split in-app specifier. Still recognised for DEDUPE only — a consumer\n * who wired `@ait-co/devtools/in-app` by hand must not also receive the new\n * auto-injected snippet. It is never injected any more.\n */\nexport const LEGACY_IN_APP_ID = '@ait-co/devtools/in-app';\n\n/** One-line install hint printed whenever a gate closes on a missing package. */\nexport const INSTALL_HINT = 'pnpm add -D @ait-co/debugger @ait-co/debug-console';\n\n/**\n * Returns whether `specifier` resolves from this package's location.\n *\n * `import.meta.resolve` throws (rather than returning a falsy value) for an\n * unresolvable specifier, and is itself absent on a few older runtimes — both\n * are treated as \"not installed\", which is the safe direction: the caller then\n * takes the degraded path instead of importing something that is not there.\n */\nexport function canResolveOptionalPeer(specifier: string): boolean {\n try {\n return typeof import.meta.resolve(specifier) === 'string';\n } catch {\n return false;\n }\n}\n\n/** Whether `@ait-co/debugger`'s dev-bridge is installed (env-2 CDP path). */\nexport function hasDebugger(): boolean {\n return canResolveOptionalPeer(DEBUGGER_DEV_BRIDGE_ID);\n}\n\n/** Whether `@ait-co/debug-console` is installed (in-app attach injection). */\nexport function hasDebugConsole(): boolean {\n return canResolveOptionalPeer(DEBUG_CONSOLE_ID);\n}\n\n/**\n * Whether `code` already wires the in-app debug attach itself.\n *\n * Both the current (`@ait-co/debug-console`) and the pre-split\n * (`@ait-co/devtools/in-app`) specifier count, so a consumer who wired either\n * one by hand never gets a duplicate auto-injection.\n */\nexport function hasInAppWiring(code: string): boolean {\n return code.includes(DEBUG_CONSOLE_ID) || code.includes(LEGACY_IN_APP_ID);\n}\n\n/**\n * The gated dynamic-import snippet prepended to a consumer entry point.\n *\n * The runtime gate (`?debug=1` + a `relay` param) keeps the chunk unloaded on a\n * normal page load, and a production build dead-code-eliminates it. The\n * build-time gate is {@link hasDebugConsole} at the call site: when the package\n * is absent this snippet is never produced, so the attach code cannot be in the\n * bundle at all.\n */\nexport function buildInAppSnippet(): string {\n return [\n '// @ait-co/devtools: in-app attach auto-injected by unplugin — 수동 배선 불필요',\n \"if (typeof window !== 'undefined') {\",\n ' const __ait_p = new URLSearchParams(window.location.search);',\n \" if (__ait_p.get('debug') === '1' && __ait_p.get('relay')) {\",\n ` void import('${DEBUG_CONSOLE_ID}').then((m) => m.maybeAttach());`,\n ' }',\n '}',\n ].join('\\n');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,MAAa,yBAAyB;;AAGtC,MAAa,mBAAmB;;AAUhC,MAAa,eAAe;;;;;;;;;AAU5B,SAAgB,uBAAuB,WAA4B;AACjE,KAAI;AACF,SAAO,OAAO,OAAO,KAAK,QAAQ,UAAU,KAAK;SAC3C;AACN,SAAO;;;;AAKX,SAAgB,cAAuB;AACrC,QAAO,uBAAuB,uBAAuB;;;AAIvD,SAAgB,kBAA2B;AACzC,QAAO,uBAAuB,iBAAiB;;;;;;;;;AAUjD,SAAgB,eAAe,MAAuB;AACpD,QAAO,KAAK,SAAA,wBAA0B,IAAI,KAAK,SAAA,0BAA0B;;;;;;;;;;;AAY3E,SAAgB,oBAA4B;AAC1C,QAAO;EACL;EACA;EACA;EACA;EACA,oBAAoB,iBAAiB;EACrC;EACA;EACD,CAAC,KAAK,KAAK"}
@@ -25339,57 +25339,6 @@ const en = {
25339
25339
  "notifications.option.newAgreement": "newAgreement (first-time agree)",
25340
25340
  "notifications.option.alreadyAgreed": "alreadyAgreed (already opted-in)",
25341
25341
  "notifications.option.agreementRejected": "agreementRejected (user declined)",
25342
- "dashboard.lang.ko": "한국어",
25343
- "dashboard.lang.en": "English",
25344
- "dashboard.title": "AIT Debug Dashboard",
25345
- "dashboard.updated": "Last updated: {ts}",
25346
- "dashboard.tunnel.section": "Tunnel status",
25347
- "dashboard.tunnel.up": "Connected",
25348
- "dashboard.tunnel.down": "Disconnected",
25349
- "dashboard.attach.section": "Attach QR",
25350
- "dashboard.attach.hint": "Call the start_attach MCP tool to show the QR here.",
25351
- "dashboard.attach.tunnelDown": "Relay disconnected — this QR is no longer valid. Restart the relay, then regenerate the QR.",
25352
- "dashboard.pages.section": "Connected Pages",
25353
- "dashboard.pages.empty": "No attached pages",
25354
- "dashboard.url.copy": "Copy",
25355
- "dashboard.url.copied": "Copied",
25356
- "dashboard.inspector.section": "Inspector",
25357
- "dashboard.inspector.open": "Open DevTools",
25358
- "dashboard.inspector.waiting": "Attach a page to enable the \"Open DevTools\" button",
25359
- "inspector.error.noTarget": "No page attached. Attach a device and try again.",
25360
- "inspector.error.relayDown": "Relay is not active. Start a relay session first.",
25361
- "dashboard.watchdog.title": "Server has shut down",
25362
- "dashboard.watchdog.body": "The MCP server has stopped. This session is no longer active. You may close this tab.",
25363
- "dashboard.watchdog.close": "Close tab",
25364
- "dashboard.conn.lost": "Connection lost — reconnecting…",
25365
- "dashboard.session.completeTitle": "Test run complete",
25366
- "dashboard.session.completeBody": "The runner exited cleanly. See your terminal for results.",
25367
- "dashboard.session.shutdownTitle": "Debug server stopped",
25368
- "dashboard.session.shutdownBody": "The MCP server has shut down; this session is no longer live. You can close this tab.",
25369
- "attach.title": "AIT Debug Session — QR Scan",
25370
- "attach.deployment": "deployment: {label}",
25371
- "attach.steps.section": "How to scan",
25372
- "attach.faq.section": "Troubleshooting checklist",
25373
- "attach.url.section": "URL (fallback)",
25374
- "attach.mode.sandbox": "env 2 — AITC Sandbox App (PWA)",
25375
- "attach.mode.intossDev": "env 3 — intoss-private relay dev",
25376
- "attach.sandbox.step1": "Launch the launcher PWA icon on your home screen (if the Safari address bar is visible, it is not standalone).",
25377
- "attach.sandbox.step2": "Scan this QR code with <strong>\"Scan QR with camera\"</strong> inside the launcher.",
25378
- "attach.sandbox.step3": "The mini-app opens fullscreen and the debug session attaches automatically.",
25379
- "attach.sandbox.step4": "<strong>Keep the app in the foreground until the test run finishes</strong> — backgrounding it will drop the debug session.",
25380
- "attach.sandbox.faq.notInstalled": "<strong>Launcher is not installed</strong> — open <code>devtools.aitc.dev/launcher/</code> once and add it to your home screen",
25381
- "attach.sandbox.faq.cameraApp": "<strong>Scanning with the camera app opens a Safari tab (bottom tab bar visible)</strong> — relaunch from the launcher icon and use the in-app scanner",
25382
- "attach.sandbox.faq.totp": "<strong>QR expired (TOTP — 30-second step, ±6 steps (~3 min) accepted)</strong> — scan a fresh QR code",
25383
- "attach.sandbox.faq.chii": "<strong>Chii injection failure / console is empty</strong> — verify the mini-app bundle has an <code>in-app</code> debug import",
25384
- "attach.intoss.step1": "Open the Toss app.",
25385
- "attach.intoss.step2": "Scan the QR code with your phone camera app.",
25386
- "attach.intoss.step3": "Tap <strong>\"Open in Toss\"</strong> when the popup appears.",
25387
- "attach.intoss.step4": "The mini-app opens and the debug session attaches automatically.",
25388
- "attach.intoss.step5": "<strong>Keep the Toss app in the foreground until the test run finishes</strong> — backgrounding it will drop the debug session.",
25389
- "attach.intoss.faq.appNotOpen": "<strong>Toss app does not open</strong> — check app version; scan with the system camera app (not the Toss in-app QR reader)",
25390
- "attach.intoss.faq.prepare": "<strong>Mini-app stuck in PREPARE state</strong> — verify the deep-link has a <code>_deploymentId</code> parameter",
25391
- "attach.intoss.faq.chii": "<strong>Chii injection failure / console is empty</strong> — verify the mini-app bundle has an <code>in-app</code> debug import",
25392
- "attach.intoss.faq.totp": "<strong>TOTP gate Layer C is inactive</strong> — check that <code>AIT_DEBUG_TOTP_SECRET</code> is set on the relay server",
25393
25342
  "launcher.title": "AITC DevTools Launcher",
25394
25343
  "launcher.description": "Scan the terminal QR code or paste the tunnel URL.",
25395
25344
  "launcher.installCta": "Install launcher to your phone",
@@ -25568,57 +25517,6 @@ const ko = {
25568
25517
  "notifications.option.newAgreement": "newAgreement (최초 동의)",
25569
25518
  "notifications.option.alreadyAgreed": "alreadyAgreed (이미 동의됨)",
25570
25519
  "notifications.option.agreementRejected": "agreementRejected (사용자 거절)",
25571
- "dashboard.lang.ko": "한국어",
25572
- "dashboard.lang.en": "English",
25573
- "dashboard.title": "AIT 디버그 Dashboard",
25574
- "dashboard.updated": "마지막 갱신: {ts}",
25575
- "dashboard.tunnel.section": "터널 상태",
25576
- "dashboard.tunnel.up": "연결됨",
25577
- "dashboard.tunnel.down": "끊어짐",
25578
- "dashboard.attach.section": "Attach QR",
25579
- "dashboard.attach.hint": "start_attach MCP tool을 호출하면 QR이 여기에 표시됩니다.",
25580
- "dashboard.attach.tunnelDown": "relay 연결이 끊겼습니다 — 이 QR은 더 이상 유효하지 않습니다. relay를 재시작한 뒤 QR을 다시 생성하세요.",
25581
- "dashboard.pages.section": "연결된 Pages",
25582
- "dashboard.pages.empty": "attach된 페이지 없음",
25583
- "dashboard.url.copy": "복사",
25584
- "dashboard.url.copied": "복사됨",
25585
- "dashboard.inspector.section": "인스펙터",
25586
- "dashboard.inspector.open": "디버그 툴 열기",
25587
- "dashboard.inspector.waiting": "페이지를 attach하면 \"디버그 툴 열기\" 버튼이 표시됩니다",
25588
- "inspector.error.noTarget": "연결된 페이지가 없습니다. 기기를 attach한 후 다시 시도하세요.",
25589
- "inspector.error.relayDown": "relay가 활성화되지 않았습니다. start_debug로 relay를 기동하세요.",
25590
- "dashboard.watchdog.title": "서버가 종료되었습니다",
25591
- "dashboard.watchdog.body": "MCP server가 종료되어 이 세션이 더 이상 유효하지 않습니다. 이 탭을 닫아도 됩니다.",
25592
- "dashboard.watchdog.close": "탭 닫기",
25593
- "dashboard.conn.lost": "연결 끊김 — 재연결 시도 중…",
25594
- "dashboard.session.completeTitle": "테스트 실행 완료",
25595
- "dashboard.session.completeBody": "러너가 정상 종료되었습니다. 결과는 터미널에서 확인하세요.",
25596
- "dashboard.session.shutdownTitle": "디버그 서버가 종료되었습니다",
25597
- "dashboard.session.shutdownBody": "MCP server가 종료되어 이 세션이 더 이상 유효하지 않습니다. 이 탭을 닫아도 됩니다.",
25598
- "attach.title": "AIT 디버그 세션 — QR 스캔",
25599
- "attach.deployment": "deployment: {label}",
25600
- "attach.steps.section": "스캔 절차",
25601
- "attach.faq.section": "진단 체크리스트",
25602
- "attach.url.section": "URL (fallback)",
25603
- "attach.mode.sandbox": "환경 2 — AITC Sandbox App (PWA)",
25604
- "attach.mode.intossDev": "환경 3 — intoss-private relay dev",
25605
- "attach.sandbox.step1": "홈 화면의 launcher PWA 아이콘으로 실행하세요 (Safari 주소창이 보이면 standalone이 아닙니다).",
25606
- "attach.sandbox.step2": "launcher 안의 <strong>\"QR 카메라로 스캔\"</strong>으로 이 QR 코드를 스캔하세요.",
25607
- "attach.sandbox.step3": "미니앱이 풀스크린으로 열리고 디버그 세션이 자동으로 attach됩니다.",
25608
- "attach.sandbox.step4": "<strong>테스트가 끝날 때까지 앱을 화면 앞에 유지하세요</strong> — 백그라운드로 전환하면 디버그 세션이 끊어집니다.",
25609
- "attach.sandbox.faq.notInstalled": "<strong>launcher가 설치돼 있지 않은 경우</strong> — <code>devtools.aitc.dev/launcher/</code>를 한 번 열어 홈 화면에 추가하세요",
25610
- "attach.sandbox.faq.cameraApp": "<strong>카메라 앱으로 스캔하면 Safari 탭으로 열립니다 (하단 탭 바 노출)</strong> — launcher 아이콘으로 다시 실행해 인앱 스캔을 사용하세요",
25611
- "attach.sandbox.faq.totp": "<strong>QR이 만료된 경우 (TOTP — 코드 1개는 30초 창, 만료 후 ~3분(±6 step) 이내 소급 허용)</strong> — 새 QR을 다시 스캔하세요",
25612
- "attach.sandbox.faq.chii": "<strong>Chii 주입 실패 / 콘솔이 비어 있는 경우</strong> — 미니앱 번들에 <code>in-app</code> debug import가 있는지 확인",
25613
- "attach.intoss.step1": "토스 앱을 실행하세요.",
25614
- "attach.intoss.step2": "폰 카메라 앱으로 QR 코드를 스캔하세요.",
25615
- "attach.intoss.step3": "팝업이 뜨면 <strong>\"토스로 열기\"</strong>를 탭하세요.",
25616
- "attach.intoss.step4": "미니앱이 열리고 디버그 세션이 자동으로 attach됩니다.",
25617
- "attach.intoss.step5": "<strong>테스트가 끝날 때까지 토스 앱을 화면 앞에 유지하세요</strong> — 백그라운드로 전환하면 디버그 세션이 끊어집니다.",
25618
- "attach.intoss.faq.appNotOpen": "<strong>토스 앱이 안 열리는 경우</strong> — 앱 버전 확인, 카메라 앱으로 스캔 (토스 앱 내 QR 리더 X)",
25619
- "attach.intoss.faq.prepare": "<strong>미니앱이 PREPARE 상태에서 멈추는 경우</strong> — deep-link에 <code>_deploymentId</code> 파라미터가 있는지 확인",
25620
- "attach.intoss.faq.chii": "<strong>Chii 주입 실패 / 콘솔이 비어 있는 경우</strong> — 미니앱 번들에 <code>in-app</code> debug import가 있는지 확인",
25621
- "attach.intoss.faq.totp": "<strong>TOTP gate Layer C가 비활성인 경우</strong> — relay 서버에 <code>AIT_DEBUG_TOTP_SECRET</code>이 설정돼 있는지 확인",
25622
25520
  "launcher.title": "AITC DevTools Launcher",
25623
25521
  "launcher.description": "터미널 QR을 스캔하거나 URL을 입력하세요.",
25624
25522
  "launcher.installCta": "폰에 런처 설치하기",
@@ -30295,7 +30193,7 @@ function Panel() {
30295
30193
  color: "#666",
30296
30194
  fontWeight: 400
30297
30195
  },
30298
- children: ["v", "0.1.143"]
30196
+ children: ["v", "0.2.0"]
30299
30197
  }),
30300
30198
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
30301
30199
  type: "button",