@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,107 @@
1
+ import { dirname, join } from "node:path";
2
+ //#region src/unplugin/relay-url-store.ts
3
+ /**
4
+ * Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).
5
+ *
6
+ * Environment-2 ("AITC Sandbox PWA") cold-start needs two ephemeral URLs that
7
+ * change on every run: the CDP relay's https base and the app tunnel's https
8
+ * base. Rather than making the developer copy-paste them into env vars each
9
+ * time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon
10
+ * (`@ait-co/debugger`) discovers them from there.
11
+ *
12
+ * Why this module is here and not in `@ait-co/debugger`: the writer IS the vite
13
+ * dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon
14
+ * reads `.ait_urls` read-only and never writes it. Splitting the file that way
15
+ * matches who is allowed to mutate it, and it keeps the write path available
16
+ * when `@ait-co/debugger` is not installed at all. The file format is the
17
+ * contract between the two packages; changing it requires changing both sides.
18
+ *
19
+ * Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`:
20
+ * the read path (`readRelayUrls`) moved out with the daemon, so only
21
+ * {@link writeRelayUrls} and {@link deleteRelayUrls} remain.
22
+ *
23
+ * SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —
24
+ * the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,
25
+ * partial values, and the resolved file path MUST NOT appear in any log, error
26
+ * message, stdout, stderr, or assertion output here or at any call site. Only
27
+ * boolean pass/fail signals are safe to surface. The file is written mode 0600.
28
+ */
29
+ /** Project-local ephemeral URL file name (single file, not a directory). */
30
+ const URLS_FILE_NAME = ".ait_urls";
31
+ /**
32
+ * Walks upward from `start` and returns the nearest directory containing a
33
+ * `package.json`. Falls back to `start` when none is found, so a write still
34
+ * lands somewhere deterministic.
35
+ *
36
+ * The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the
37
+ * SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:
38
+ * real mini-apps keep `vite.config.ts` and `package.json` in one directory, so
39
+ * `server.config.root === package.json-dir`. In a monorepo subdir the anchor is
40
+ * the package's own directory — the one the daemon also reaches via its
41
+ * per-session projectRoot.
42
+ */
43
+ function nearestPackageJsonDir(start, existsSyncFn) {
44
+ let dir = start;
45
+ while (true) {
46
+ if (existsSyncFn(join(dir, "package.json"))) return dir;
47
+ const parent = dirname(dir);
48
+ if (parent === dir) return start;
49
+ dir = parent;
50
+ }
51
+ }
52
+ /**
53
+ * Absolute path to the project-local `.ait_urls` file for a given start
54
+ * directory (resolved against the nearest package.json directory).
55
+ *
56
+ * Exported so tests can compute the expected path without duplicating the
57
+ * resolution logic.
58
+ */
59
+ function urlsFilePath(start, existsSyncFn) {
60
+ return join(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);
61
+ }
62
+ /**
63
+ * Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),
64
+ * overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL
65
+ * replaces the previous one on every boot.
66
+ *
67
+ * Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):
68
+ * only the dev server writes this file, so there is no race to guard, and the
69
+ * value must be fresh on every cold-start.
70
+ *
71
+ * SECRET-HANDLING: URL values are never logged.
72
+ */
73
+ async function writeRelayUrls(deps) {
74
+ const { projectRoot, relayBaseUrl, relayLocalUrl, tunnelBaseUrl, fs: fsDep, existsSync: existsSyncDep } = deps;
75
+ const fs = fsDep ?? await import("node:fs");
76
+ const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
77
+ const payload = {};
78
+ if (typeof relayBaseUrl === "string" && relayBaseUrl !== "") payload.relayBaseUrl = relayBaseUrl;
79
+ if (typeof relayLocalUrl === "string" && relayLocalUrl !== "") payload.relayLocalUrl = relayLocalUrl;
80
+ if (typeof tunnelBaseUrl === "string" && tunnelBaseUrl !== "") payload.tunnelBaseUrl = tunnelBaseUrl;
81
+ fs.writeFileSync(filePath, JSON.stringify(payload), {
82
+ mode: 384,
83
+ flag: "w"
84
+ });
85
+ }
86
+ /**
87
+ * Removes `<projectRoot>/.ait_urls` if present, swallowing every error so
88
+ * cleanup always succeeds.
89
+ *
90
+ * Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A
91
+ * stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a
92
+ * doomed attach on the next cold-start — deletion is non-negotiable.
93
+ *
94
+ * SECRET-HANDLING: the file path is never logged.
95
+ */
96
+ async function deleteRelayUrls(deps) {
97
+ const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;
98
+ const fs = fsDep ?? await import("node:fs");
99
+ const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
100
+ try {
101
+ if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
102
+ } catch {}
103
+ }
104
+ //#endregion
105
+ export { deleteRelayUrls, writeRelayUrls };
106
+
107
+ //# sourceMappingURL=relay-url-store-CPZAn-T5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-url-store-CPZAn-T5.js","names":[],"sources":["../src/unplugin/relay-url-store.ts"],"sourcesContent":["/**\n * Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).\n *\n * Environment-2 (\"AITC Sandbox PWA\") cold-start needs two ephemeral URLs that\n * change on every run: the CDP relay's https base and the app tunnel's https\n * base. Rather than making the developer copy-paste them into env vars each\n * time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon\n * (`@ait-co/debugger`) discovers them from there.\n *\n * Why this module is here and not in `@ait-co/debugger`: the writer IS the vite\n * dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon\n * reads `.ait_urls` read-only and never writes it. Splitting the file that way\n * matches who is allowed to mutate it, and it keeps the write path available\n * when `@ait-co/debugger` is not installed at all. The file format is the\n * contract between the two packages; changing it requires changing both sides.\n *\n * Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`:\n * the read path (`readRelayUrls`) moved out with the daemon, so only\n * {@link writeRelayUrls} and {@link deleteRelayUrls} remain.\n *\n * SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —\n * the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,\n * partial values, and the resolved file path MUST NOT appear in any log, error\n * message, stdout, stderr, or assertion output here or at any call site. Only\n * boolean pass/fail signals are safe to surface. The file is written mode 0600.\n */\n\nimport { dirname, join } from 'node:path';\n\n/** Project-local ephemeral URL file name (single file, not a directory). */\nexport const URLS_FILE_NAME = '.ait_urls';\n\n/** Minimal fs subset needed by {@link writeRelayUrls} — injectable for tests. */\nexport interface RelayUrlWriteFs {\n writeFileSync(path: string, data: string, options: { mode: number; flag: string }): void;\n existsSync(path: string): boolean;\n}\n\n/** Minimal fs subset needed by {@link deleteRelayUrls} — injectable for tests. */\nexport interface RelayUrlDeleteFs {\n existsSync(path: string): boolean;\n unlinkSync(path: string): void;\n}\n\n/**\n * Walks upward from `start` and returns the nearest directory containing a\n * `package.json`. Falls back to `start` when none is found, so a write still\n * lands somewhere deterministic.\n *\n * The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the\n * SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:\n * real mini-apps keep `vite.config.ts` and `package.json` in one directory, so\n * `server.config.root === package.json-dir`. In a monorepo subdir the anchor is\n * the package's own directory — the one the daemon also reaches via its\n * per-session projectRoot.\n */\nexport function nearestPackageJsonDir(\n start: string,\n existsSyncFn: (path: string) => boolean,\n): string {\n let dir = start;\n // Stop at the filesystem root (dirname of root === root).\n while (true) {\n if (existsSyncFn(join(dir, 'package.json'))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return start;\n dir = parent;\n }\n}\n\n/**\n * Absolute path to the project-local `.ait_urls` file for a given start\n * directory (resolved against the nearest package.json directory).\n *\n * Exported so tests can compute the expected path without duplicating the\n * resolution logic.\n */\nexport function urlsFilePath(start: string, existsSyncFn: (path: string) => boolean): string {\n return join(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);\n}\n\nexport interface WriteRelayUrlsDeps {\n /** Project root (typically Vite `server.config.root`). */\n projectRoot: string;\n /**\n * The CDP relay's https base URL. Omit when the relay was not started.\n * SECRET-HANDLING: never log this value.\n */\n relayBaseUrl?: string;\n /**\n * The CDP relay's LOCAL http base URL (`http://127.0.0.1:<relay-port>`), used\n * by the daemon to build the Chii inspector URL without a tunnel round-trip\n * (issue #530). Loopback only — no tunnel host, safe to surface.\n */\n relayLocalUrl?: string;\n /**\n * The app tunnel's https base URL. Omit when unavailable.\n * SECRET-HANDLING: never log this value.\n */\n tunnelBaseUrl?: string;\n /** Filesystem operations. Defaults to node:fs synchronous functions. */\n fs?: RelayUrlWriteFs;\n /** existsSync used to resolve the nearest package.json directory. Defaults to node:fs. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),\n * overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL\n * replaces the previous one on every boot.\n *\n * Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):\n * only the dev server writes this file, so there is no race to guard, and the\n * value must be fresh on every cold-start.\n *\n * SECRET-HANDLING: URL values are never logged.\n */\nexport async function writeRelayUrls(deps: WriteRelayUrlsDeps): Promise<void> {\n const {\n projectRoot,\n relayBaseUrl,\n relayLocalUrl,\n tunnelBaseUrl,\n fs: fsDep,\n existsSync: existsSyncDep,\n } = deps;\n\n const fs: RelayUrlWriteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n // Build the payload — omit keys whose values are absent or blank.\n const payload: { relayBaseUrl?: string; relayLocalUrl?: string; tunnelBaseUrl?: string } = {};\n if (typeof relayBaseUrl === 'string' && relayBaseUrl !== '') payload.relayBaseUrl = relayBaseUrl;\n if (typeof relayLocalUrl === 'string' && relayLocalUrl !== '') {\n payload.relayLocalUrl = relayLocalUrl;\n }\n if (typeof tunnelBaseUrl === 'string' && tunnelBaseUrl !== '') {\n payload.tunnelBaseUrl = tunnelBaseUrl;\n }\n\n // SECRET-HANDLING: the JSON content (which includes URL values) goes to the\n // file only — never to any log, stdout, or stderr.\n fs.writeFileSync(filePath, JSON.stringify(payload), { mode: 0o600, flag: 'w' });\n}\n\nexport interface DeleteRelayUrlsDeps {\n /** Project root. */\n projectRoot: string;\n /** Filesystem operations. Defaults to node:fs (existsSync + unlinkSync). */\n fs?: RelayUrlDeleteFs;\n /** existsSync used to resolve the nearest package.json directory. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Removes `<projectRoot>/.ait_urls` if present, swallowing every error so\n * cleanup always succeeds.\n *\n * Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A\n * stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a\n * doomed attach on the next cold-start — deletion is non-negotiable.\n *\n * SECRET-HANDLING: the file path is never logged.\n */\nexport async function deleteRelayUrls(deps: DeleteRelayUrlsDeps): Promise<void> {\n const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;\n\n const fs: RelayUrlDeleteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n try {\n if (fs.existsSync(filePath)) fs.unlinkSync(filePath);\n } catch {\n // Swallow ENOENT and any other error — cleanup is best-effort.\n // SECRET-HANDLING: the path is not logged.\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,iBAAiB;;;;;;;;;;;;;AA0B9B,SAAgB,sBACd,OACA,cACQ;CACR,IAAI,MAAM;AAEV,QAAO,MAAM;AACX,MAAI,aAAa,KAAK,KAAK,eAAe,CAAC,CAAE,QAAO;EACpD,MAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,QAAM;;;;;;;;;;AAWV,SAAgB,aAAa,OAAe,cAAiD;AAC3F,QAAO,KAAK,sBAAsB,OAAO,aAAa,EAAE,eAAe;;;;;;;;;;;;;AAuCzE,eAAsB,eAAe,MAAyC;CAC5E,MAAM,EACJ,aACA,cACA,eACA,eACA,IAAI,OACJ,YAAY,kBACV;CAEJ,MAAM,KAAsB,SAAU,MAAM,OAAO;CAGnD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;CAGxD,MAAM,UAAqF,EAAE;AAC7F,KAAI,OAAO,iBAAiB,YAAY,iBAAiB,GAAI,SAAQ,eAAe;AACpF,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAE1B,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAK1B,IAAG,cAAc,UAAU,KAAK,UAAU,QAAQ,EAAE;EAAE,MAAM;EAAO,MAAM;EAAK,CAAC;;;;;;;;;;;;AAsBjF,eAAsB,gBAAgB,MAA0C;CAC9E,MAAM,EAAE,aAAa,IAAI,OAAO,YAAY,kBAAkB;CAE9D,MAAM,KAAuB,SAAU,MAAM,OAAO;CAGpD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;AAExD,KAAI;AACF,MAAI,GAAG,WAAW,SAAS,CAAE,IAAG,WAAW,SAAS;SAC9C"}
@@ -0,0 +1,108 @@
1
+ let node_path = require("node:path");
2
+ //#region src/unplugin/relay-url-store.ts
3
+ /**
4
+ * Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).
5
+ *
6
+ * Environment-2 ("AITC Sandbox PWA") cold-start needs two ephemeral URLs that
7
+ * change on every run: the CDP relay's https base and the app tunnel's https
8
+ * base. Rather than making the developer copy-paste them into env vars each
9
+ * time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon
10
+ * (`@ait-co/debugger`) discovers them from there.
11
+ *
12
+ * Why this module is here and not in `@ait-co/debugger`: the writer IS the vite
13
+ * dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon
14
+ * reads `.ait_urls` read-only and never writes it. Splitting the file that way
15
+ * matches who is allowed to mutate it, and it keeps the write path available
16
+ * when `@ait-co/debugger` is not installed at all. The file format is the
17
+ * contract between the two packages; changing it requires changing both sides.
18
+ *
19
+ * Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`:
20
+ * the read path (`readRelayUrls`) moved out with the daemon, so only
21
+ * {@link writeRelayUrls} and {@link deleteRelayUrls} remain.
22
+ *
23
+ * SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —
24
+ * the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,
25
+ * partial values, and the resolved file path MUST NOT appear in any log, error
26
+ * message, stdout, stderr, or assertion output here or at any call site. Only
27
+ * boolean pass/fail signals are safe to surface. The file is written mode 0600.
28
+ */
29
+ /** Project-local ephemeral URL file name (single file, not a directory). */
30
+ const URLS_FILE_NAME = ".ait_urls";
31
+ /**
32
+ * Walks upward from `start` and returns the nearest directory containing a
33
+ * `package.json`. Falls back to `start` when none is found, so a write still
34
+ * lands somewhere deterministic.
35
+ *
36
+ * The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the
37
+ * SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:
38
+ * real mini-apps keep `vite.config.ts` and `package.json` in one directory, so
39
+ * `server.config.root === package.json-dir`. In a monorepo subdir the anchor is
40
+ * the package's own directory — the one the daemon also reaches via its
41
+ * per-session projectRoot.
42
+ */
43
+ function nearestPackageJsonDir(start, existsSyncFn) {
44
+ let dir = start;
45
+ while (true) {
46
+ if (existsSyncFn((0, node_path.join)(dir, "package.json"))) return dir;
47
+ const parent = (0, node_path.dirname)(dir);
48
+ if (parent === dir) return start;
49
+ dir = parent;
50
+ }
51
+ }
52
+ /**
53
+ * Absolute path to the project-local `.ait_urls` file for a given start
54
+ * directory (resolved against the nearest package.json directory).
55
+ *
56
+ * Exported so tests can compute the expected path without duplicating the
57
+ * resolution logic.
58
+ */
59
+ function urlsFilePath(start, existsSyncFn) {
60
+ return (0, node_path.join)(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);
61
+ }
62
+ /**
63
+ * Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),
64
+ * overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL
65
+ * replaces the previous one on every boot.
66
+ *
67
+ * Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):
68
+ * only the dev server writes this file, so there is no race to guard, and the
69
+ * value must be fresh on every cold-start.
70
+ *
71
+ * SECRET-HANDLING: URL values are never logged.
72
+ */
73
+ async function writeRelayUrls(deps) {
74
+ const { projectRoot, relayBaseUrl, relayLocalUrl, tunnelBaseUrl, fs: fsDep, existsSync: existsSyncDep } = deps;
75
+ const fs = fsDep ?? await import("node:fs");
76
+ const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
77
+ const payload = {};
78
+ if (typeof relayBaseUrl === "string" && relayBaseUrl !== "") payload.relayBaseUrl = relayBaseUrl;
79
+ if (typeof relayLocalUrl === "string" && relayLocalUrl !== "") payload.relayLocalUrl = relayLocalUrl;
80
+ if (typeof tunnelBaseUrl === "string" && tunnelBaseUrl !== "") payload.tunnelBaseUrl = tunnelBaseUrl;
81
+ fs.writeFileSync(filePath, JSON.stringify(payload), {
82
+ mode: 384,
83
+ flag: "w"
84
+ });
85
+ }
86
+ /**
87
+ * Removes `<projectRoot>/.ait_urls` if present, swallowing every error so
88
+ * cleanup always succeeds.
89
+ *
90
+ * Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A
91
+ * stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a
92
+ * doomed attach on the next cold-start — deletion is non-negotiable.
93
+ *
94
+ * SECRET-HANDLING: the file path is never logged.
95
+ */
96
+ async function deleteRelayUrls(deps) {
97
+ const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;
98
+ const fs = fsDep ?? await import("node:fs");
99
+ const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
100
+ try {
101
+ if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
102
+ } catch {}
103
+ }
104
+ //#endregion
105
+ exports.deleteRelayUrls = deleteRelayUrls;
106
+ exports.writeRelayUrls = writeRelayUrls;
107
+
108
+ //# sourceMappingURL=relay-url-store-DLjlvMSA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-url-store-DLjlvMSA.cjs","names":[],"sources":["../src/unplugin/relay-url-store.ts"],"sourcesContent":["/**\n * Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).\n *\n * Environment-2 (\"AITC Sandbox PWA\") cold-start needs two ephemeral URLs that\n * change on every run: the CDP relay's https base and the app tunnel's https\n * base. Rather than making the developer copy-paste them into env vars each\n * time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon\n * (`@ait-co/debugger`) discovers them from there.\n *\n * Why this module is here and not in `@ait-co/debugger`: the writer IS the vite\n * dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon\n * reads `.ait_urls` read-only and never writes it. Splitting the file that way\n * matches who is allowed to mutate it, and it keeps the write path available\n * when `@ait-co/debugger` is not installed at all. The file format is the\n * contract between the two packages; changing it requires changing both sides.\n *\n * Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`:\n * the read path (`readRelayUrls`) moved out with the daemon, so only\n * {@link writeRelayUrls} and {@link deleteRelayUrls} remain.\n *\n * SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —\n * the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,\n * partial values, and the resolved file path MUST NOT appear in any log, error\n * message, stdout, stderr, or assertion output here or at any call site. Only\n * boolean pass/fail signals are safe to surface. The file is written mode 0600.\n */\n\nimport { dirname, join } from 'node:path';\n\n/** Project-local ephemeral URL file name (single file, not a directory). */\nexport const URLS_FILE_NAME = '.ait_urls';\n\n/** Minimal fs subset needed by {@link writeRelayUrls} — injectable for tests. */\nexport interface RelayUrlWriteFs {\n writeFileSync(path: string, data: string, options: { mode: number; flag: string }): void;\n existsSync(path: string): boolean;\n}\n\n/** Minimal fs subset needed by {@link deleteRelayUrls} — injectable for tests. */\nexport interface RelayUrlDeleteFs {\n existsSync(path: string): boolean;\n unlinkSync(path: string): void;\n}\n\n/**\n * Walks upward from `start` and returns the nearest directory containing a\n * `package.json`. Falls back to `start` when none is found, so a write still\n * lands somewhere deterministic.\n *\n * The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the\n * SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:\n * real mini-apps keep `vite.config.ts` and `package.json` in one directory, so\n * `server.config.root === package.json-dir`. In a monorepo subdir the anchor is\n * the package's own directory — the one the daemon also reaches via its\n * per-session projectRoot.\n */\nexport function nearestPackageJsonDir(\n start: string,\n existsSyncFn: (path: string) => boolean,\n): string {\n let dir = start;\n // Stop at the filesystem root (dirname of root === root).\n while (true) {\n if (existsSyncFn(join(dir, 'package.json'))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return start;\n dir = parent;\n }\n}\n\n/**\n * Absolute path to the project-local `.ait_urls` file for a given start\n * directory (resolved against the nearest package.json directory).\n *\n * Exported so tests can compute the expected path without duplicating the\n * resolution logic.\n */\nexport function urlsFilePath(start: string, existsSyncFn: (path: string) => boolean): string {\n return join(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);\n}\n\nexport interface WriteRelayUrlsDeps {\n /** Project root (typically Vite `server.config.root`). */\n projectRoot: string;\n /**\n * The CDP relay's https base URL. Omit when the relay was not started.\n * SECRET-HANDLING: never log this value.\n */\n relayBaseUrl?: string;\n /**\n * The CDP relay's LOCAL http base URL (`http://127.0.0.1:<relay-port>`), used\n * by the daemon to build the Chii inspector URL without a tunnel round-trip\n * (issue #530). Loopback only — no tunnel host, safe to surface.\n */\n relayLocalUrl?: string;\n /**\n * The app tunnel's https base URL. Omit when unavailable.\n * SECRET-HANDLING: never log this value.\n */\n tunnelBaseUrl?: string;\n /** Filesystem operations. Defaults to node:fs synchronous functions. */\n fs?: RelayUrlWriteFs;\n /** existsSync used to resolve the nearest package.json directory. Defaults to node:fs. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),\n * overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL\n * replaces the previous one on every boot.\n *\n * Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):\n * only the dev server writes this file, so there is no race to guard, and the\n * value must be fresh on every cold-start.\n *\n * SECRET-HANDLING: URL values are never logged.\n */\nexport async function writeRelayUrls(deps: WriteRelayUrlsDeps): Promise<void> {\n const {\n projectRoot,\n relayBaseUrl,\n relayLocalUrl,\n tunnelBaseUrl,\n fs: fsDep,\n existsSync: existsSyncDep,\n } = deps;\n\n const fs: RelayUrlWriteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n // Build the payload — omit keys whose values are absent or blank.\n const payload: { relayBaseUrl?: string; relayLocalUrl?: string; tunnelBaseUrl?: string } = {};\n if (typeof relayBaseUrl === 'string' && relayBaseUrl !== '') payload.relayBaseUrl = relayBaseUrl;\n if (typeof relayLocalUrl === 'string' && relayLocalUrl !== '') {\n payload.relayLocalUrl = relayLocalUrl;\n }\n if (typeof tunnelBaseUrl === 'string' && tunnelBaseUrl !== '') {\n payload.tunnelBaseUrl = tunnelBaseUrl;\n }\n\n // SECRET-HANDLING: the JSON content (which includes URL values) goes to the\n // file only — never to any log, stdout, or stderr.\n fs.writeFileSync(filePath, JSON.stringify(payload), { mode: 0o600, flag: 'w' });\n}\n\nexport interface DeleteRelayUrlsDeps {\n /** Project root. */\n projectRoot: string;\n /** Filesystem operations. Defaults to node:fs (existsSync + unlinkSync). */\n fs?: RelayUrlDeleteFs;\n /** existsSync used to resolve the nearest package.json directory. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Removes `<projectRoot>/.ait_urls` if present, swallowing every error so\n * cleanup always succeeds.\n *\n * Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A\n * stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a\n * doomed attach on the next cold-start — deletion is non-negotiable.\n *\n * SECRET-HANDLING: the file path is never logged.\n */\nexport async function deleteRelayUrls(deps: DeleteRelayUrlsDeps): Promise<void> {\n const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;\n\n const fs: RelayUrlDeleteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n try {\n if (fs.existsSync(filePath)) fs.unlinkSync(filePath);\n } catch {\n // Swallow ENOENT and any other error — cleanup is best-effort.\n // SECRET-HANDLING: the path is not logged.\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,iBAAiB;;;;;;;;;;;;;AA0B9B,SAAgB,sBACd,OACA,cACQ;CACR,IAAI,MAAM;AAEV,QAAO,MAAM;AACX,MAAI,cAAA,GAAA,UAAA,MAAkB,KAAK,eAAe,CAAC,CAAE,QAAO;EACpD,MAAM,UAAA,GAAA,UAAA,SAAiB,IAAI;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,QAAM;;;;;;;;;;AAWV,SAAgB,aAAa,OAAe,cAAiD;AAC3F,SAAA,GAAA,UAAA,MAAY,sBAAsB,OAAO,aAAa,EAAE,eAAe;;;;;;;;;;;;;AAuCzE,eAAsB,eAAe,MAAyC;CAC5E,MAAM,EACJ,aACA,cACA,eACA,eACA,IAAI,OACJ,YAAY,kBACV;CAEJ,MAAM,KAAsB,SAAU,MAAM,OAAO;CAGnD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;CAGxD,MAAM,UAAqF,EAAE;AAC7F,KAAI,OAAO,iBAAiB,YAAY,iBAAiB,GAAI,SAAQ,eAAe;AACpF,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAE1B,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAK1B,IAAG,cAAc,UAAU,KAAK,UAAU,QAAQ,EAAE;EAAE,MAAM;EAAO,MAAM;EAAK,CAAC;;;;;;;;;;;;AAsBjF,eAAsB,gBAAgB,MAA0C;CAC9E,MAAM,EAAE,aAAa,IAAI,OAAO,YAAY,kBAAkB;CAE9D,MAAM,KAAuB,SAAU,MAAM,OAAO;CAGpD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;AAExD,KAAI;AACF,MAAI,GAAG,WAAW,SAAS,CAAE,IAAG,WAAW,SAAS;SAC9C"}
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ //#region src/stubs/moved.ts
3
+ /**
4
+ * Shared copy for the transition stubs left behind by the debug-surface split
5
+ * (#818).
6
+ *
7
+ * TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a
8
+ * consumer still on a pre-0.2.0 wiring gets a sentence telling them where the
9
+ * code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0
10
+ * drops them, the same import fails with the resolver's own error — which is
11
+ * the correct end state, just a worse first encounter.
12
+ *
13
+ * Two stub shapes, and the difference between them is a safety property, not a
14
+ * style choice:
15
+ *
16
+ * - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)
17
+ * THROW on import. They only ever run in a developer's terminal, so failing
18
+ * loudly at the earliest possible moment is right.
19
+ * - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code
20
+ * could be sitting in a shipped production bundle; a throw there takes the
21
+ * user's mini-app down. They degrade to a no-op plus one `console.error`.
22
+ */
23
+ /** The package that now owns the MCP daemon, test runner, and dev bridge. */
24
+ const DEBUGGER_PACKAGE = "@ait-co/debugger";
25
+ /**
26
+ * Builds the migration sentence for a moved subpath.
27
+ *
28
+ * SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,
29
+ * URLs, or environment values.
30
+ */
31
+ function movedMessage(oldSubpath, newPackage, install) {
32
+ return [
33
+ `[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,
34
+ `이 기능은 '${newPackage}' 로 이동했습니다.`,
35
+ `설치: ${install}`
36
+ ].join(" ");
37
+ }
38
+ //#endregion
39
+ //#region src/stubs/bin-devtools-mcp.ts
40
+ /**
41
+ * TRANSITION STUB — REMOVE IN 1.0.0.
42
+ *
43
+ * The `devtools-mcp` bin moved to `@ait-co/debugger`, where it is named
44
+ * `debugger` (#818). The rename is why this stub can exist at all: had the new
45
+ * package kept the old bin name, both packages installed side by side would
46
+ * fight over the same `node_modules/.bin/devtools-mcp` symlink and whichever
47
+ * won would be arbitrary. Different names, no collision.
48
+ *
49
+ * Prints the migration notice to stderr (not stdout — an MCP host may be
50
+ * reading stdout as a JSON-RPC stream) and exits non-zero so a script that
51
+ * still calls the old bin fails rather than silently continuing.
52
+ */
53
+ process.stderr.write(`${movedMessage("devtools-mcp", `${DEBUGGER_PACKAGE} (bin: debugger)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\n`);
54
+ process.exit(1);
55
+ //#endregion
56
+ export {};
57
+
58
+ //# sourceMappingURL=bin-devtools-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin-devtools-mcp.js","names":[],"sources":["../../src/stubs/moved.ts","../../src/stubs/bin-devtools-mcp.ts"],"sourcesContent":["/**\n * Shared copy for the transition stubs left behind by the debug-surface split\n * (#818).\n *\n * TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a\n * consumer still on a pre-0.2.0 wiring gets a sentence telling them where the\n * code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0\n * drops them, the same import fails with the resolver's own error — which is\n * the correct end state, just a worse first encounter.\n *\n * Two stub shapes, and the difference between them is a safety property, not a\n * style choice:\n *\n * - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)\n * THROW on import. They only ever run in a developer's terminal, so failing\n * loudly at the earliest possible moment is right.\n * - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code\n * could be sitting in a shipped production bundle; a throw there takes the\n * user's mini-app down. They degrade to a no-op plus one `console.error`.\n */\n\n/** The package that now owns the MCP daemon, test runner, and dev bridge. */\nexport const DEBUGGER_PACKAGE = '@ait-co/debugger';\n\n/** The package that now owns the on-device attach + eruda console. */\nexport const DEBUG_CONSOLE_PACKAGE = '@ait-co/debug-console';\n\n/**\n * Builds the migration sentence for a moved subpath.\n *\n * SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,\n * URLs, or environment values.\n */\nexport function movedMessage(oldSubpath: string, newPackage: string, install: string): string {\n return [\n `[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,\n `이 기능은 '${newPackage}' 로 이동했습니다.`,\n `설치: ${install}`,\n ].join(' ');\n}\n","/**\n * TRANSITION STUB — REMOVE IN 1.0.0.\n *\n * The `devtools-mcp` bin moved to `@ait-co/debugger`, where it is named\n * `debugger` (#818). The rename is why this stub can exist at all: had the new\n * package kept the old bin name, both packages installed side by side would\n * fight over the same `node_modules/.bin/devtools-mcp` symlink and whichever\n * won would be arbitrary. Different names, no collision.\n *\n * Prints the migration notice to stderr (not stdout — an MCP host may be\n * reading stdout as a JSON-RPC stream) and exits non-zero so a script that\n * still calls the old bin fails rather than silently continuing.\n */\n\nimport { DEBUGGER_PACKAGE, movedMessage } from './moved.js';\n\nprocess.stderr.write(\n `${movedMessage('devtools-mcp', `${DEBUGGER_PACKAGE} (bin: debugger)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\\n`,\n);\nprocess.exit(1);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,mBAAmB;;;;;;;AAWhC,SAAgB,aAAa,YAAoB,YAAoB,SAAyB;AAC5F,QAAO;EACL,uBAAuB,WAAW;EAClC,UAAU,WAAW;EACrB,OAAO;EACR,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;;;ACtBb,QAAQ,OAAO,MACb,GAAG,aAAa,gBAAgB,GAAG,iBAAiB,mBAAmB,eAAe,mBAAmB,CAAC,IAC3G;AACD,QAAQ,KAAK,EAAE"}
@@ -0,0 +1,2 @@
1
+
2
+ export { };
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ //#region src/stubs/moved.ts
3
+ /**
4
+ * Shared copy for the transition stubs left behind by the debug-surface split
5
+ * (#818).
6
+ *
7
+ * TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a
8
+ * consumer still on a pre-0.2.0 wiring gets a sentence telling them where the
9
+ * code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0
10
+ * drops them, the same import fails with the resolver's own error — which is
11
+ * the correct end state, just a worse first encounter.
12
+ *
13
+ * Two stub shapes, and the difference between them is a safety property, not a
14
+ * style choice:
15
+ *
16
+ * - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)
17
+ * THROW on import. They only ever run in a developer's terminal, so failing
18
+ * loudly at the earliest possible moment is right.
19
+ * - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code
20
+ * could be sitting in a shipped production bundle; a throw there takes the
21
+ * user's mini-app down. They degrade to a no-op plus one `console.error`.
22
+ */
23
+ /** The package that now owns the MCP daemon, test runner, and dev bridge. */
24
+ const DEBUGGER_PACKAGE = "@ait-co/debugger";
25
+ /**
26
+ * Builds the migration sentence for a moved subpath.
27
+ *
28
+ * SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,
29
+ * URLs, or environment values.
30
+ */
31
+ function movedMessage(oldSubpath, newPackage, install) {
32
+ return [
33
+ `[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,
34
+ `이 기능은 '${newPackage}' 로 이동했습니다.`,
35
+ `설치: ${install}`
36
+ ].join(" ");
37
+ }
38
+ //#endregion
39
+ //#region src/stubs/bin-devtools-test.ts
40
+ /**
41
+ * TRANSITION STUB — REMOVE IN 1.0.0.
42
+ *
43
+ * The `devtools-test` bin moved to `@ait-co/debugger`, where it is named
44
+ * `debugger-test` (#818). See `src/stubs/bin-devtools-mcp.ts` for why the
45
+ * rename is what makes a stub bin safe to keep.
46
+ *
47
+ * Prints the migration notice to stderr and exits non-zero so a CI step still
48
+ * calling the old bin fails loudly instead of reporting a vacuous success.
49
+ */
50
+ process.stderr.write(`${movedMessage("devtools-test", `${DEBUGGER_PACKAGE} (bin: debugger-test)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\n`);
51
+ process.exit(1);
52
+ //#endregion
53
+ export {};
54
+
55
+ //# sourceMappingURL=bin-devtools-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin-devtools-test.js","names":[],"sources":["../../src/stubs/moved.ts","../../src/stubs/bin-devtools-test.ts"],"sourcesContent":["/**\n * Shared copy for the transition stubs left behind by the debug-surface split\n * (#818).\n *\n * TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a\n * consumer still on a pre-0.2.0 wiring gets a sentence telling them where the\n * code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0\n * drops them, the same import fails with the resolver's own error — which is\n * the correct end state, just a worse first encounter.\n *\n * Two stub shapes, and the difference between them is a safety property, not a\n * style choice:\n *\n * - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)\n * THROW on import. They only ever run in a developer's terminal, so failing\n * loudly at the earliest possible moment is right.\n * - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code\n * could be sitting in a shipped production bundle; a throw there takes the\n * user's mini-app down. They degrade to a no-op plus one `console.error`.\n */\n\n/** The package that now owns the MCP daemon, test runner, and dev bridge. */\nexport const DEBUGGER_PACKAGE = '@ait-co/debugger';\n\n/** The package that now owns the on-device attach + eruda console. */\nexport const DEBUG_CONSOLE_PACKAGE = '@ait-co/debug-console';\n\n/**\n * Builds the migration sentence for a moved subpath.\n *\n * SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,\n * URLs, or environment values.\n */\nexport function movedMessage(oldSubpath: string, newPackage: string, install: string): string {\n return [\n `[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,\n `이 기능은 '${newPackage}' 로 이동했습니다.`,\n `설치: ${install}`,\n ].join(' ');\n}\n","/**\n * TRANSITION STUB — REMOVE IN 1.0.0.\n *\n * The `devtools-test` bin moved to `@ait-co/debugger`, where it is named\n * `debugger-test` (#818). See `src/stubs/bin-devtools-mcp.ts` for why the\n * rename is what makes a stub bin safe to keep.\n *\n * Prints the migration notice to stderr and exits non-zero so a CI step still\n * calling the old bin fails loudly instead of reporting a vacuous success.\n */\n\nimport { DEBUGGER_PACKAGE, movedMessage } from './moved.js';\n\nprocess.stderr.write(\n `${movedMessage('devtools-test', `${DEBUGGER_PACKAGE} (bin: debugger-test)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\\n`,\n);\nprocess.exit(1);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,mBAAmB;;;;;;;AAWhC,SAAgB,aAAa,YAAoB,YAAoB,SAAyB;AAC5F,QAAO;EACL,uBAAuB,WAAW;EAClC,UAAU,WAAW;EACrB,OAAO;EACR,CAAC,KAAK,IAAI;;;;;;;;;;;;;;ACzBb,QAAQ,OAAO,MACb,GAAG,aAAa,iBAAiB,GAAG,iBAAiB,wBAAwB,eAAe,mBAAmB,CAAC,IACjH;AACD,QAAQ,KAAK,EAAE"}
@@ -1,231 +1 @@
1
- import { i as createRelayPool, n as RelayConnectionFactory, t as RELAY_POOL_NAME } from "../pool-DcaaOwUq.js";
2
-
3
- //#region src/test-runner/relay-factory.d.ts
4
- /** Options for {@link createRelayConnectionFactory}. */
5
- interface RelayConnectionFactoryOptions {
6
- /**
7
- * intoss-private:// scheme URL from `ait deploy --scheme-only` (env3). The
8
- * phone cold-loads the candidate bundle this URL points at. SECRET-HANDLING:
9
- * never logged.
10
- *
11
- * Ignored when {@link attachLauncher} is `true` — the env-2 launcher path
12
- * builds its attach URL from {@link appUrl} + the relay wss, not a scheme URL.
13
- * Pass `''` in that case.
14
- */
15
- schemeUrl: string;
16
- /**
17
- * env-2 (AITC Sandbox PWA) attach mode (devtools#774). When `true`, `open()`
18
- * builds the attach URL as a **launcher deep-link**
19
- * (`buildLauncherAttachUrl(appUrl, wssUrl, totp)` — the same env-2 path the
20
- * MCP daemon takes via `prepareAttach(deps, 'relay-mobile', …)`, issue #378)
21
- * instead of an intoss-private scheme deep-link. The relay boot, QR
22
- * rendering, dashboard, and attach-wait are byte-for-byte identical to env 3;
23
- * only the URL family differs. Omitted/false keeps the env-3 scheme path
24
- * unchanged (zero behavior change).
25
- */
26
- attachLauncher?: boolean;
27
- /**
28
- * The consumer dev server's HTTP tunnel URL (e.g. an sdk-example
29
- * `dev:phone:cdp` `*.trycloudflare.com` URL) that the launcher PWA frames.
30
- * REQUIRED when {@link attachLauncher} is `true`; ignored otherwise.
31
- *
32
- * Threaded to the `relay-mobile` `prepareAttach` branch via the
33
- * `AIT_TUNNEL_BASE_URL` env var (the same key the MCP daemon reads), so the
34
- * exact same env-2 assembly runs — no divergent code path.
35
- *
36
- * SECRET-HANDLING: this is a tunnel host at the same sensitivity as the relay
37
- * wss — NEVER logged. It rides only inside the QR/dashboard attach capsule.
38
- */
39
- appUrl?: string;
40
- /**
41
- * Project root for the `.ait_relay` secret lookup (read-only). Defaults to
42
- * `process.cwd()`.
43
- */
44
- projectRoot?: string;
45
- /**
46
- * Attach wait timeout in ms — how long `open()` waits for the phone to scan
47
- * the QR and attach. Omitted (the default) means **wait indefinitely** —
48
- * the runner stays up until the user stops it (Ctrl-C/SIGTERM). QR-scan
49
- * wait is a human-paced action; there is no sound default bound for it
50
- * (devtools#735). Pass an explicit value to opt into a bounded wait (CI/
51
- * headless callers — `--attach-timeout` on the CLI). (The per-file evaluate
52
- * timeout is separate, passed via the pool's `run` options.)
53
- */
54
- timeoutMs?: number;
55
- /** Disable browser auto-open of the QR dashboard (text QR only). */
56
- headless?: boolean;
57
- /**
58
- * Cell axes injected as `__AIT_CELL__` before the first test bundle runs, so
59
- * sdk-example's capture picks up the correct sdkLine/platform. Optional — when
60
- * omitted no cell is injected. The values are not secrets.
61
- */
62
- cell?: {
63
- sdkLine: string;
64
- platform: string;
65
- };
66
- /**
67
- * When `true`, injects `__AIT_STUB_BLOCKING__ = true` before the first test
68
- * bundle runs (devtools#740, DT-2) — `bundle.ts`'s sdk-redirect module reads
69
- * this flag via `isStubBlockingEnabled()` and answers the blocking-UI APIs
70
- * in `bridge-stub.ts`'s `STUB_REGISTRY` from fixtures instead of forwarding
71
- * them to native. Optional — omitted/false means no flag is injected, which
72
- * is byte-for-byte the pre-#740 behavior (the sdk-redirect module treats
73
- * absence the same as `false`). Not a secret.
74
- */
75
- stubBlocking?: boolean;
76
- /**
77
- * Injects `__AIT_PACE_MS__ = paceMs` before the first test bundle runs
78
- * (devtools#767) — `runtime.ts`'s test-execution loop reads this page
79
- * global and waits `paceMs` before every test after the first one that
80
- * actually runs. Optional — omitted/0 means no flag is injected, which is
81
- * byte-for-byte the pre-#767 behavior (the loop treats an absent/non-
82
- * positive value as "no pacing"). Not a secret. This is the PAGE-side half
83
- * of `--pace`; the RUNNER-side (file-to-file) half is a plain `opts.paceMs`
84
- * forwarded to `runTestFilesOverRelay` by the caller (cli.ts) — this
85
- * factory only owns the page-global injection.
86
- */
87
- paceMs?: number;
88
- /**
89
- * Injects `__AIT_PACE_METHOD_MS__ = paceMethodMs` before the first test
90
- * bundle runs (devtools#769) — `bundle.ts`'s sdk-redirect virtual module
91
- * reads this page global via `method-pace.ts#getPaceMethodMs()` and paces
92
- * every SDK call to a minimum interval BETWEEN calls to the SAME named
93
- * function, independent of `--pace`'s test-to-test/file-to-file spacing.
94
- * Optional — omitted/0 means no flag is injected, which is byte-for-byte
95
- * the pre-#769 behavior (`getPaceMethodMs()` treats an absent/non-positive
96
- * value as "no pacing", and `wrapWithMethodPacing` returns the SDK object
97
- * untouched in that case). Not a secret.
98
- */
99
- paceMethodMs?: number;
100
- /**
101
- * Overrides the dashboard HTTP server's bind base port (devtools#752).
102
- * Threaded straight through to `startQrHttpServer`'s `dashboardPort`
103
- * option — see that option's doc for the increment-on-EADDRINUSE scan
104
- * behaviour and the `AIT_DEBUG_HTTP_PORT` env fallback. Omitted means
105
- * `startQrHttpServer` resolves its own default (env → fixed default).
106
- */
107
- dashboardPort?: number;
108
- /**
109
- * Receives the QR/attach render content (text chunks) from
110
- * `renderAndMaybeWait`, so the caller decides whether to print them — e.g.
111
- * suppress on non-interactive stdout.
112
- *
113
- * REQUIRED (not optional) on purpose: these chunks contain the QR payload
114
- * (which encodes the relay wss + TOTP `at=` code) and the attach JSON block.
115
- * Making the hook mandatory means the factory never falls back to printing
116
- * them itself — a downstream `vitest.config.ts` consumer that wires this via
117
- * the `@ait-co/devtools/test-runner` barrel is forced to make an explicit
118
- * stdout decision rather than silently leaking the secret-bearing block.
119
- *
120
- * SECRET-HANDLING: when a non-interactive caller is detected the hook MUST
121
- * suppress the WHOLE chunk (not just `attachUrl`), since `relayUrl` rides in
122
- * the same block.
123
- */
124
- onQrContent: (textChunks: string[]) => void;
125
- }
126
- /**
127
- * Builds a {@link RelayConnectionFactory} that opens a standalone relay
128
- * connection for env 3 (intoss-private scheme, default) or env 2 (AITC Sandbox
129
- * PWA launcher deep-link, when `opts.attachLauncher` is set — devtools#774).
130
- *
131
- * `open()` performs the full attach lifecycle and BLOCKS while a human scans
132
- * the rendered QR with their phone — there is no way around the manual scan.
133
- * By default the wait is UNBOUNDED (`opts.timeoutMs` omitted): the
134
- * runner stays up until the user stops it (Ctrl-C/SIGTERM), since QR-scan is
135
- * a human-paced action with no sound default bound (devtools#735). Passing an
136
- * explicit `timeoutMs` opts into the old bounded behavior (CI/headless
137
- * callers). It resolves with the live `CdpConnection` once a matching page
138
- * attaches; `close()` tears the relay family down.
139
- *
140
- * The factory holds the booted relay family in a closure so `close()` can stop
141
- * it. A second `open()` on the same factory boots a fresh family (the previous
142
- * one should have been `close()`d first).
143
- */
144
- declare function createRelayConnectionFactory(opts: RelayConnectionFactoryOptions): RelayConnectionFactory;
145
- //#endregion
146
- //#region src/test-runner/config.d.ts
147
- /**
148
- * Resolved phone-test configuration returned by `definePhoneTestConfig`.
149
- */
150
- interface PhoneTestConfig {
151
- /**
152
- * Glob patterns (relative to cwd) for test files to run on the device.
153
- * Defaults to `['**\/*.ait.test.ts']`.
154
- */
155
- include: string[];
156
- /**
157
- * Per-file evaluate timeout in milliseconds. Defaults to 30 000.
158
- */
159
- timeoutMs: number;
160
- /**
161
- * Additional esbuild `external` patterns for bundling.
162
- * The SDK package is always external; add more here if needed.
163
- */
164
- extraExternals: string[];
165
- }
166
- /** User-facing config shape accepted by `definePhoneTestConfig`. */
167
- interface PhoneTestUserConfig {
168
- include?: string[];
169
- timeoutMs?: number;
170
- extraExternals?: string[];
171
- }
172
- /**
173
- * Define a phone-relay test configuration.
174
- *
175
- * Merges user overrides with sensible defaults and returns a resolved
176
- * `PhoneTestConfig`. This object can be passed to `runTestFilesOverRelay`
177
- * (via the CLI or custom scripts) to run tests on a real device WebView.
178
- */
179
- declare function definePhoneTestConfig(userConfig?: PhoneTestUserConfig): PhoneTestConfig;
180
- /**
181
- * The slice of a Vitest `test` config this helper produces — `pool`,
182
- * `include`, and `testTimeout`. Typed structurally (not against Vitest's
183
- * `InlineConfig`) so consumers can spread it into their own `defineConfig`
184
- * without this module taking a value dependency on `vitest`.
185
- */
186
- interface PhoneVitestTestConfig {
187
- /** The relay `PoolRunnerInitializer`, matched by `getFilePoolName`. */
188
- pool: ReturnType<typeof createRelayPool>;
189
- /** Glob patterns for device test files. */
190
- include: string[];
191
- /** Per-test timeout in ms (mirrors the relay per-file evaluate timeout). */
192
- testTimeout: number;
193
- }
194
- /** User config accepted by {@link definePhoneVitestConfig}. */
195
- interface PhoneVitestUserConfig extends PhoneTestUserConfig {
196
- /**
197
- * Opens/closes the CDP relay connection that tests run over. Required —
198
- * without it there is no device to dispatch files to.
199
- *
200
- * SECRET-HANDLING: the factory owns the relay wss/TOTP; this config object
201
- * never stores or logs those values.
202
- */
203
- connection: RelayConnectionFactory;
204
- /**
205
- * When `true`, the relay pool harvests `__AIT_CAPTURE__` console lines during
206
- * the run (forwarded as `collectCaptures` to `runTestFilesOverRelay`), so
207
- * `RelayRunReport.captures` is populated; a downstream consumer persists the
208
- * artifacts (pool-side artifact writing + cell-meta wiring lands in PR-S1).
209
- * Omitted/`false` = no capture harvest (build-only, zero listener overhead).
210
- */
211
- collectCaptures?: boolean;
212
- }
213
- /**
214
- * Build the Vitest `test` config slice for running tests on a device over the
215
- * relay. Spread the result into your Vitest config:
216
- *
217
- * @example
218
- * // vitest.config.ts
219
- * import { defineConfig } from 'vitest/config';
220
- * import { definePhoneVitestConfig } from '@ait-co/devtools/test-runner';
221
- * export default defineConfig({
222
- * test: definePhoneVitestConfig({ connection: myRelayFactory }),
223
- * });
224
- *
225
- * Files matching `include` are dispatched to the relay pool (named
226
- * {@link RELAY_POOL_NAME}); everything else runs in Vitest's default pool.
227
- */
228
- declare function definePhoneVitestConfig(userConfig: PhoneVitestUserConfig): PhoneVitestTestConfig;
229
- //#endregion
230
- export { PhoneTestConfig, PhoneTestUserConfig, PhoneVitestTestConfig, PhoneVitestUserConfig, RELAY_POOL_NAME, type RelayConnectionFactory, type RelayConnectionFactoryOptions, createRelayConnectionFactory, createRelayPool, definePhoneTestConfig, definePhoneVitestConfig };
231
- //# sourceMappingURL=config.d.ts.map
1
+ export { };