@pyric/cli 0.1.0-alpha.19 → 0.1.0-alpha.21

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 (642) hide show
  1. package/README.md +64 -89
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +68 -1
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +68 -1
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/bridge/client/dispatch.d.ts +25 -19
  7. package/dist/bridge/client/dispatch.d.ts.map +1 -1
  8. package/dist/bridge/client/dispatch.js +41 -48
  9. package/dist/bridge/client/dispatch.js.map +1 -1
  10. package/dist/bridge/client/tool-family-factories.d.ts +26 -0
  11. package/dist/bridge/client/tool-family-factories.d.ts.map +1 -0
  12. package/dist/bridge/client/tool-family-factories.js +10 -0
  13. package/dist/bridge/client/tool-family-factories.js.map +1 -0
  14. package/dist/bridge/server/mcp-contract.d.ts +7 -6
  15. package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
  16. package/dist/bridge/server/mcp-contract.js +9 -48
  17. package/dist/bridge/server/mcp-contract.js.map +1 -1
  18. package/dist/bridge/server/peer.d.ts +11 -1
  19. package/dist/bridge/server/peer.d.ts.map +1 -1
  20. package/dist/bridge/server/peer.js +22 -1
  21. package/dist/bridge/server/peer.js.map +1 -1
  22. package/dist/bridge/server/tool-family-factories.d.ts +30 -0
  23. package/dist/bridge/server/tool-family-factories.d.ts.map +1 -0
  24. package/dist/bridge/server/tool-family-factories.js +22 -0
  25. package/dist/bridge/server/tool-family-factories.js.map +1 -0
  26. package/dist/bridge/server/tool-metadata.d.ts +17 -18
  27. package/dist/bridge/server/tool-metadata.d.ts.map +1 -1
  28. package/dist/bridge/server/tool-metadata.js +24 -59
  29. package/dist/bridge/server/tool-metadata.js.map +1 -1
  30. package/dist/bridge/tool-families.d.ts +48 -0
  31. package/dist/bridge/tool-families.d.ts.map +1 -0
  32. package/dist/bridge/tool-families.generated.d.ts +32 -0
  33. package/dist/bridge/tool-families.generated.d.ts.map +1 -0
  34. package/dist/bridge/tool-families.generated.js +15 -0
  35. package/dist/bridge/tool-families.generated.js.map +1 -0
  36. package/dist/bridge/tool-families.js +51 -0
  37. package/dist/bridge/tool-families.js.map +1 -0
  38. package/dist/bridge/tool-family-records/conformance.d.ts +7 -0
  39. package/dist/bridge/tool-family-records/conformance.d.ts.map +1 -0
  40. package/dist/bridge/tool-family-records/conformance.js +6 -0
  41. package/dist/bridge/tool-family-records/conformance.js.map +1 -0
  42. package/dist/bridge/tool-family-records/firestore-data.d.ts +7 -0
  43. package/dist/bridge/tool-family-records/firestore-data.d.ts.map +1 -0
  44. package/dist/bridge/tool-family-records/firestore-data.js +15 -0
  45. package/dist/bridge/tool-family-records/firestore-data.js.map +1 -0
  46. package/dist/bridge/tool-family-records/firestore-inspect.d.ts +7 -0
  47. package/dist/bridge/tool-family-records/firestore-inspect.d.ts.map +1 -0
  48. package/dist/bridge/tool-family-records/firestore-inspect.js +6 -0
  49. package/dist/bridge/tool-family-records/firestore-inspect.js.map +1 -0
  50. package/dist/bridge/tool-family-records/firestore-rules.d.ts +7 -0
  51. package/dist/bridge/tool-family-records/firestore-rules.d.ts.map +1 -0
  52. package/dist/bridge/tool-family-records/firestore-rules.js +15 -0
  53. package/dist/bridge/tool-family-records/firestore-rules.js.map +1 -0
  54. package/dist/bridge/tool-family-records/firestore-simulator.d.ts +7 -0
  55. package/dist/bridge/tool-family-records/firestore-simulator.d.ts.map +1 -0
  56. package/dist/bridge/tool-family-records/firestore-simulator.js +16 -0
  57. package/dist/bridge/tool-family-records/firestore-simulator.js.map +1 -0
  58. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts +7 -0
  59. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts.map +1 -0
  60. package/dist/bridge/tool-family-records/rtdb-inspection.js +6 -0
  61. package/dist/bridge/tool-family-records/rtdb-inspection.js.map +1 -0
  62. package/dist/bundler/externals.d.ts +37 -0
  63. package/dist/bundler/externals.d.ts.map +1 -0
  64. package/dist/bundler/externals.js +52 -0
  65. package/dist/bundler/externals.js.map +1 -0
  66. package/dist/bundler/index.d.ts +17 -0
  67. package/dist/bundler/index.d.ts.map +1 -0
  68. package/dist/bundler/index.js +17 -0
  69. package/dist/bundler/index.js.map +1 -0
  70. package/dist/cli/index.d.ts +2 -2
  71. package/dist/cli/index.d.ts.map +1 -1
  72. package/dist/cli/index.js +48 -42
  73. package/dist/cli/index.js.map +1 -1
  74. package/dist/cli/inlined-sdk-scanner.d.ts +6 -0
  75. package/dist/cli/inlined-sdk-scanner.d.ts.map +1 -0
  76. package/dist/cli/inlined-sdk-scanner.js +82 -0
  77. package/dist/cli/inlined-sdk-scanner.js.map +1 -0
  78. package/dist/cli/mcp-proxy.js +3 -3
  79. package/dist/cli/mcp-proxy.js.map +1 -1
  80. package/dist/cli/parse-args.d.ts +1 -1
  81. package/dist/cli/parse-args.d.ts.map +1 -1
  82. package/dist/cli/parse-args.js +51 -15
  83. package/dist/cli/parse-args.js.map +1 -1
  84. package/dist/cli/pyric-config.d.ts +24 -0
  85. package/dist/cli/pyric-config.d.ts.map +1 -0
  86. package/dist/cli/pyric-config.js +28 -0
  87. package/dist/cli/pyric-config.js.map +1 -0
  88. package/dist/cli/sandbox-interlock.d.ts +97 -0
  89. package/dist/cli/sandbox-interlock.d.ts.map +1 -0
  90. package/dist/cli/sandbox-interlock.js +112 -0
  91. package/dist/cli/sandbox-interlock.js.map +1 -0
  92. package/dist/cli/{dev-runner.d.ts → sandbox-runner.d.ts} +53 -48
  93. package/dist/cli/sandbox-runner.d.ts.map +1 -0
  94. package/dist/cli/{dev-runner.js → sandbox-runner.js} +105 -67
  95. package/dist/cli/sandbox-runner.js.map +1 -0
  96. package/dist/cli/serve.d.ts +12 -14
  97. package/dist/cli/serve.d.ts.map +1 -1
  98. package/dist/cli/serve.js +155 -116
  99. package/dist/cli/serve.js.map +1 -1
  100. package/dist/cli/snapshot.js +5 -5
  101. package/dist/cli/snapshot.js.map +1 -1
  102. package/dist/cli/unsupported-runtime.d.ts +27 -0
  103. package/dist/cli/unsupported-runtime.d.ts.map +1 -0
  104. package/dist/cli/unsupported-runtime.js +63 -0
  105. package/dist/cli/unsupported-runtime.js.map +1 -0
  106. package/dist/cli/verify.js +1 -1
  107. package/dist/cli/verify.js.map +1 -1
  108. package/dist/conformance/.generated/can-i-use-browser.d.ts +1 -1
  109. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  110. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  111. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  112. package/dist/conformance/.generated/can-i-use.d.ts +1 -1
  113. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  114. package/dist/conformance/.generated/can-i-use.js +1 -1
  115. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  116. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  117. package/dist/conformance/.generated/conformance-docs.js +1 -1
  118. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  119. package/dist/functions-rtdb/child.d.ts +37 -0
  120. package/dist/functions-rtdb/child.d.ts.map +1 -1
  121. package/dist/functions-rtdb/child.js +90 -21
  122. package/dist/functions-rtdb/child.js.map +1 -1
  123. package/dist/functions-rtdb/development-runtime.d.ts +3 -0
  124. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
  125. package/dist/functions-rtdb/development-runtime.js +2 -1
  126. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  127. package/dist/functions-rtdb/project.js +8 -8
  128. package/dist/functions-rtdb/project.js.map +1 -1
  129. package/dist/google-endpoints.d.ts +67 -0
  130. package/dist/google-endpoints.d.ts.map +1 -0
  131. package/dist/google-endpoints.js +119 -0
  132. package/dist/google-endpoints.js.map +1 -0
  133. package/dist/next/guard.js +1 -1
  134. package/dist/next/guard.js.map +1 -1
  135. package/dist/next/runtime-env.d.ts.map +1 -1
  136. package/dist/next/runtime-env.js +5 -0
  137. package/dist/next/runtime-env.js.map +1 -1
  138. package/dist/next/with-pyric.d.ts +1 -1
  139. package/dist/next/with-pyric.js +1 -1
  140. package/dist/register/beacon.d.ts +69 -0
  141. package/dist/register/beacon.d.ts.map +1 -0
  142. package/dist/register/beacon.js +199 -0
  143. package/dist/register/beacon.js.map +1 -0
  144. package/dist/register/index.d.ts.map +1 -1
  145. package/dist/register/index.js +65 -6
  146. package/dist/register/index.js.map +1 -1
  147. package/dist/register/net-guard.d.ts +110 -0
  148. package/dist/register/net-guard.d.ts.map +1 -0
  149. package/dist/register/net-guard.js +462 -0
  150. package/dist/register/net-guard.js.map +1 -0
  151. package/dist/remote/index.d.ts +1 -1
  152. package/dist/remote/index.js +9 -9
  153. package/dist/remote/index.js.map +1 -1
  154. package/dist/serve/ai-diagnostics-relay.d.ts +63 -0
  155. package/dist/serve/ai-diagnostics-relay.d.ts.map +1 -0
  156. package/dist/serve/ai-diagnostics-relay.js +125 -0
  157. package/dist/serve/ai-diagnostics-relay.js.map +1 -0
  158. package/dist/serve/ai-proxy.d.ts +92 -0
  159. package/dist/serve/ai-proxy.d.ts.map +1 -0
  160. package/dist/serve/ai-proxy.js +269 -0
  161. package/dist/serve/ai-proxy.js.map +1 -0
  162. package/dist/serve/ai-status.d.ts +44 -0
  163. package/dist/serve/ai-status.d.ts.map +1 -0
  164. package/dist/serve/ai-status.js +77 -0
  165. package/dist/serve/ai-status.js.map +1 -0
  166. package/dist/serve/ai-terminal-blocks.d.ts +97 -0
  167. package/dist/serve/ai-terminal-blocks.d.ts.map +1 -0
  168. package/dist/serve/ai-terminal-blocks.js +128 -0
  169. package/dist/serve/ai-terminal-blocks.js.map +1 -0
  170. package/dist/serve/ai-terminal-text.d.ts +36 -0
  171. package/dist/serve/ai-terminal-text.d.ts.map +1 -0
  172. package/dist/serve/ai-terminal-text.js +48 -0
  173. package/dist/serve/ai-terminal-text.js.map +1 -0
  174. package/dist/serve/beacon-route.d.ts +53 -0
  175. package/dist/serve/beacon-route.d.ts.map +1 -0
  176. package/dist/serve/beacon-route.js +101 -0
  177. package/dist/serve/beacon-route.js.map +1 -0
  178. package/dist/serve/bundler.js +10 -10
  179. package/dist/serve/bundler.js.map +1 -1
  180. package/dist/serve/entries/active-auth-registry.d.ts +16 -0
  181. package/dist/serve/entries/active-auth-registry.d.ts.map +1 -0
  182. package/dist/serve/entries/active-auth-registry.js +48 -0
  183. package/dist/serve/entries/active-auth-registry.js.map +1 -0
  184. package/dist/serve/entries/active-auth.d.ts +18 -0
  185. package/dist/serve/entries/active-auth.d.ts.map +1 -0
  186. package/dist/serve/entries/active-auth.js +84 -0
  187. package/dist/serve/entries/active-auth.js.map +1 -0
  188. package/dist/serve/entries/ai.d.ts.map +1 -1
  189. package/dist/serve/entries/ai.js +27 -1
  190. package/dist/serve/entries/ai.js.map +1 -1
  191. package/dist/serve/entries/auth-helper-core.d.ts +1 -0
  192. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  193. package/dist/serve/entries/auth-helper-core.js +4 -0
  194. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  195. package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -1
  196. package/dist/serve/entries/auth-helper-dom.js +29 -3
  197. package/dist/serve/entries/auth-helper-dom.js.map +1 -1
  198. package/dist/serve/entries/auth-helper-runtime.js +1 -1
  199. package/dist/serve/entries/auth-helper-runtime.js.map +1 -1
  200. package/dist/serve/entries/auth.d.ts.map +1 -1
  201. package/dist/serve/entries/auth.js +8 -0
  202. package/dist/serve/entries/auth.js.map +1 -1
  203. package/dist/serve/entries/bridge-url.d.ts +1 -1
  204. package/dist/serve/entries/bridge-url.js +1 -1
  205. package/dist/serve/entries/firestore.js +3 -3
  206. package/dist/serve/entries/firestore.js.map +1 -1
  207. package/dist/serve/entries/init.d.ts.map +1 -1
  208. package/dist/serve/entries/init.js +70 -4
  209. package/dist/serve/entries/init.js.map +1 -1
  210. package/dist/serve/entries/keepalive.js +1 -1
  211. package/dist/serve/entries/keepalive.js.map +1 -1
  212. package/dist/serve/entries/runtime.d.ts.map +1 -1
  213. package/dist/serve/entries/runtime.js +30 -14
  214. package/dist/serve/entries/runtime.js.map +1 -1
  215. package/dist/serve/entries/storage.js +1 -1
  216. package/dist/serve/entries/storage.js.map +1 -1
  217. package/dist/serve/entries/worker-runtime.js +1 -1
  218. package/dist/serve/entries/worker-runtime.js.map +1 -1
  219. package/dist/serve/init-payload.d.ts +4 -0
  220. package/dist/serve/init-payload.d.ts.map +1 -1
  221. package/dist/serve/namespace.d.ts +20 -5
  222. package/dist/serve/namespace.d.ts.map +1 -1
  223. package/dist/serve/namespace.js +93 -129
  224. package/dist/serve/namespace.js.map +1 -1
  225. package/dist/serve/rules.d.ts.map +1 -1
  226. package/dist/serve/rules.js +44 -21
  227. package/dist/serve/rules.js.map +1 -1
  228. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  229. package/dist/serve/runtime/chip-config.js +16 -2
  230. package/dist/serve/runtime/chip-config.js.map +1 -1
  231. package/dist/serve/runtime/chip-dialog.d.ts +18 -0
  232. package/dist/serve/runtime/chip-dialog.d.ts.map +1 -0
  233. package/dist/serve/runtime/chip-dialog.js +315 -0
  234. package/dist/serve/runtime/chip-dialog.js.map +1 -0
  235. package/dist/serve/runtime/chip-install.d.ts +2 -0
  236. package/dist/serve/runtime/chip-install.d.ts.map +1 -1
  237. package/dist/serve/runtime/chip-install.js +9 -4
  238. package/dist/serve/runtime/chip-install.js.map +1 -1
  239. package/dist/serve/runtime/chip-user-search.d.ts +16 -0
  240. package/dist/serve/runtime/chip-user-search.d.ts.map +1 -0
  241. package/dist/serve/runtime/chip-user-search.js +354 -0
  242. package/dist/serve/runtime/chip-user-search.js.map +1 -0
  243. package/dist/serve/runtime/chip.d.ts +10 -0
  244. package/dist/serve/runtime/chip.d.ts.map +1 -1
  245. package/dist/serve/runtime/chip.js +149 -15
  246. package/dist/serve/runtime/chip.js.map +1 -1
  247. package/dist/serve/runtime/identity.d.ts +17 -0
  248. package/dist/serve/runtime/identity.d.ts.map +1 -0
  249. package/dist/serve/runtime/identity.js +10 -0
  250. package/dist/serve/runtime/identity.js.map +1 -0
  251. package/dist/serve/runtime/manifest.d.ts +1 -1
  252. package/dist/serve/runtime/manifest.d.ts.map +1 -1
  253. package/dist/serve/runtime/manifest.js +1 -1
  254. package/dist/serve/runtime/manifest.js.map +1 -1
  255. package/dist/serve/runtime/status.d.ts.map +1 -1
  256. package/dist/serve/runtime/status.js +23 -0
  257. package/dist/serve/runtime/status.js.map +1 -1
  258. package/dist/serve/sandbox-session.d.ts +8 -0
  259. package/dist/serve/sandbox-session.d.ts.map +1 -1
  260. package/dist/serve/sandbox-session.js +12 -4
  261. package/dist/serve/sandbox-session.js.map +1 -1
  262. package/dist/serve/server.d.ts +7 -0
  263. package/dist/serve/server.d.ts.map +1 -1
  264. package/dist/serve/server.js +15 -1
  265. package/dist/serve/server.js.map +1 -1
  266. package/dist/serve/site-ui/404.html +1 -1
  267. package/dist/serve/site-ui/_astro/{RulesCodeEditor.Bl-XMkhD.js → RulesCodeEditor.DsTAsKIa.js} +1 -1
  268. package/dist/serve/site-ui/_astro/_slug_.Da5VLhW1.css +1 -0
  269. package/dist/serve/site-ui/_astro/_studio_.BnfYCKoI.css +1 -0
  270. package/dist/serve/site-ui/_astro/app.BOr2kwae.js +115 -0
  271. package/dist/serve/site-ui/_astro/app.DhAcImFD.js +1 -0
  272. package/dist/serve/site-ui/_astro/app.pMSnN6Qw.css +1 -0
  273. package/dist/serve/site-ui/_astro/{chess-showcase.Dh5D8kqe.js → chess-showcase.Bn_pP6UJ.js} +2 -2
  274. package/dist/serve/site-ui/_astro/{example-runtime.CuyAjjiG.js → example-runtime.CXopTGv7.js} +1 -1
  275. package/dist/serve/site-ui/_astro/index.Tb-31efc.css +1 -0
  276. package/dist/serve/site-ui/_astro/index.UkCBr-_0.css +1 -0
  277. package/dist/serve/site-ui/_astro/sandbox-controls.rOuZTOUG.js +510 -0
  278. package/dist/serve/site-ui/_astro/{seed.CSUkloMi.js → seed.03a08f9t.js} +2 -2
  279. package/dist/serve/site-ui/_astro/writes.BsPBG3dp.js +653 -0
  280. package/dist/serve/site-ui/auth/index.html +5 -3
  281. package/dist/serve/site-ui/david-east.jpg +0 -0
  282. package/dist/serve/site-ui/docs/_rhythm/index.html +6 -3
  283. package/dist/serve/site-ui/docs/_rhythm.md +1 -1
  284. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +18 -15
  285. package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +16 -16
  286. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +6 -5
  287. package/dist/serve/site-ui/docs/agent/watch-and-review.md +1 -5
  288. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +8 -5
  289. package/dist/serve/site-ui/docs/agent/work-with-an-agent.md +4 -4
  290. package/dist/serve/site-ui/docs/ai-compat/index.html +5 -2
  291. package/dist/serve/site-ui/docs/api-reference/index.html +13 -2
  292. package/dist/serve/site-ui/docs/api-reference.md +8 -0
  293. package/dist/serve/site-ui/docs/app-compat/index.html +5 -2
  294. package/dist/serve/site-ui/docs/auth-compat/index.html +7 -4
  295. package/dist/serve/site-ui/docs/auth-compat.md +2 -2
  296. package/dist/serve/site-ui/docs/build/ai-logic/index.html +10 -2
  297. package/dist/serve/site-ui/docs/build/ai-logic.md +6 -0
  298. package/dist/serve/site-ui/docs/build/authentication/index.html +7 -4
  299. package/dist/serve/site-ui/docs/build/authentication.md +2 -2
  300. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +5 -2
  301. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +5 -2
  302. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +6 -3
  303. package/dist/serve/site-ui/docs/build/cloud-storage.md +1 -1
  304. package/dist/serve/site-ui/docs/build/realtime-database/index.html +9 -6
  305. package/dist/serve/site-ui/docs/build/realtime-database.md +4 -4
  306. package/dist/serve/site-ui/docs/conformance-scores/index.html +10 -3
  307. package/dist/serve/site-ui/docs/conformance-scores.md +5 -1
  308. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -3
  309. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +1 -1
  310. package/dist/serve/site-ui/docs/database-compat/index.html +48 -45
  311. package/dist/serve/site-ui/docs/database-compat.md +43 -43
  312. package/dist/serve/site-ui/docs/examples/chess/index.html +5 -2
  313. package/dist/serve/site-ui/docs/examples/index.html +5 -2
  314. package/dist/serve/site-ui/docs/firestore-compat/index.html +8 -5
  315. package/dist/serve/site-ui/docs/firestore-compat.md +3 -3
  316. package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +319 -0
  317. package/dist/serve/site-ui/docs/firestore-flutter-compat.md +344 -0
  318. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +5 -2
  319. package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +105 -0
  320. package/dist/serve/site-ui/docs/get-started/backend-bundlers.md +165 -0
  321. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +9 -6
  322. package/dist/serve/site-ui/docs/get-started/how-the-swap-works.md +5 -5
  323. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +9 -6
  324. package/dist/serve/site-ui/docs/get-started/nextjs.md +4 -4
  325. package/dist/serve/site-ui/docs/get-started/start-building/index.html +14 -9
  326. package/dist/serve/site-ui/docs/get-started/start-building.md +16 -10
  327. package/dist/serve/site-ui/docs/get-started/vite/index.html +6 -3
  328. package/dist/serve/site-ui/docs/get-started/vite.md +1 -1
  329. package/dist/serve/site-ui/docs/index.json +3128 -1613
  330. package/dist/serve/site-ui/docs/messaging-compat/index.html +5 -2
  331. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +5 -2
  332. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +6 -4
  333. package/dist/serve/site-ui/docs/observe/see-whats-happening.md +2 -4
  334. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +9 -6
  335. package/dist/serve/site-ui/docs/observe/shape-your-data.md +4 -4
  336. package/dist/serve/site-ui/docs/overview/index.html +16 -10
  337. package/dist/serve/site-ui/docs/overview.md +19 -11
  338. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +5 -2
  339. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +5 -2
  340. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +5 -2
  341. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +8 -5
  342. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +3 -3
  343. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +5 -2
  344. package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +501 -0
  345. package/dist/serve/site-ui/docs/pyric-admin-reference-api.md +587 -0
  346. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +5 -2
  347. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +5 -2
  348. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +5 -2
  349. package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +124 -0
  350. package/dist/serve/site-ui/docs/pyric-analytics-reference-api.md +287 -0
  351. package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +87 -0
  352. package/dist/serve/site-ui/docs/pyric-app-check-reference-api.md +199 -0
  353. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +5 -2
  354. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +10 -3
  355. package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +2 -1
  356. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +5 -2
  357. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +5 -2
  358. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +6 -3
  359. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api.md +1 -1
  360. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +5 -2
  361. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +56 -0
  362. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api.md +72 -0
  363. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +6 -2
  364. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api.md +1 -0
  365. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +5 -2
  366. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +6 -2
  367. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api.md +1 -0
  368. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +5 -2
  369. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +5 -2
  370. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +6 -3
  371. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +1 -1
  372. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +5 -2
  373. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +5 -2
  374. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +39 -11
  375. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +17 -9
  376. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +137 -94
  377. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +61 -1
  378. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +6 -3
  379. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +1 -1
  380. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +6 -3
  381. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +2 -2
  382. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +167 -96
  383. package/dist/serve/site-ui/docs/pyric-database-reference-api.md +108 -2
  384. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +559 -0
  385. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api.md +1240 -0
  386. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +44 -12
  387. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +18 -8
  388. package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +67 -0
  389. package/dist/serve/site-ui/docs/pyric-functions-reference-api.md +149 -0
  390. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +10 -4
  391. package/dist/serve/site-ui/docs/pyric-messaging-reference-api.md +5 -2
  392. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +10 -4
  393. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api.md +5 -2
  394. package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +35 -0
  395. package/dist/serve/site-ui/docs/pyric-performance-reference-api.md +69 -0
  396. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +132 -0
  397. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api.md +307 -0
  398. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +5 -2
  399. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +56 -18
  400. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +48 -9
  401. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +6 -3
  402. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api.md +2 -2
  403. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +243 -50
  404. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +148 -31
  405. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +26 -5
  406. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +24 -2
  407. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +30 -97
  408. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api.md +20 -51
  409. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +5 -2
  410. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +6 -3
  411. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api.md +1 -1
  412. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +5 -2
  413. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +5 -2
  414. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +5 -2
  415. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +6 -3
  416. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api.md +1 -1
  417. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +128 -27
  418. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api.md +58 -5
  419. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -2
  420. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +5 -2
  421. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +5 -2
  422. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +5 -2
  423. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +8 -6
  424. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +3 -4
  425. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +5 -2
  426. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +5 -2
  427. package/dist/serve/site-ui/docs/reference/cli/index.html +156 -0
  428. package/dist/serve/site-ui/docs/reference/cli.md +120 -0
  429. package/dist/serve/site-ui/docs/rules-compat/index.html +14 -3
  430. package/dist/serve/site-ui/docs/rules-compat.md +9 -1
  431. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +5 -2
  432. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +5 -2
  433. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +6 -3
  434. package/dist/serve/site-ui/docs/secure/read-a-denial.md +1 -1
  435. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +5 -2
  436. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +5 -2
  437. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +5 -2
  438. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +5 -2
  439. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +5 -2
  440. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +7 -4
  441. package/dist/serve/site-ui/docs/ship/ship-to-production.md +2 -2
  442. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +9 -6
  443. package/dist/serve/site-ui/docs/ship/test-in-node.md +4 -4
  444. package/dist/serve/site-ui/docs/storage-compat/index.html +17 -14
  445. package/dist/serve/site-ui/docs/storage-compat.md +12 -12
  446. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +5 -2
  447. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +5 -2
  448. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +5 -2
  449. package/dist/serve/site-ui/docs/tutorial/index.html +10 -7
  450. package/dist/serve/site-ui/docs/tutorial.md +4 -4
  451. package/dist/serve/site-ui/examples/chess/index.html +4 -2
  452. package/dist/serve/site-ui/firestore/index.html +5 -3
  453. package/dist/serve/site-ui/hero-charcoal.jpg +0 -0
  454. package/dist/serve/site-ui/index.html +9 -7
  455. package/dist/serve/site-ui/llms.txt +13 -3
  456. package/dist/serve/site-ui/pyric-campfire-full.png +0 -0
  457. package/dist/serve/site-ui/pyric-campfire.png +0 -0
  458. package/dist/serve/site-ui/rtdb/index.html +5 -3
  459. package/dist/serve/site-ui/settings/index.html +5 -3
  460. package/dist/serve/site-ui/storage/index.html +5 -3
  461. package/dist/serve/site-ui/studio/index.html +13 -0
  462. package/dist/serve/site-ui/studio-routes.json +1 -1
  463. package/dist/serve/site-ui/traffic/index.html +5 -3
  464. package/dist/serve/studio/disk-workspace.d.ts.map +1 -1
  465. package/dist/serve/studio/disk-workspace.js +64 -2
  466. package/dist/serve/studio/disk-workspace.js.map +1 -1
  467. package/dist/serve/studio/routes.d.ts +9 -0
  468. package/dist/serve/studio/routes.d.ts.map +1 -1
  469. package/dist/serve/studio/routes.js +47 -7
  470. package/dist/serve/studio/routes.js.map +1 -1
  471. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  472. package/dist/serve/vite-ai-config.js +38 -8
  473. package/dist/serve/vite-ai-config.js.map +1 -1
  474. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  475. package/dist/serve/vite-module-swap.js +0 -28
  476. package/dist/serve/vite-module-swap.js.map +1 -1
  477. package/dist/serve/vite-plugin.d.ts +7 -7
  478. package/dist/serve/vite-plugin.js +1 -1
  479. package/dist/serve/vite-plugin.js.map +1 -1
  480. package/dist/serve/vite-sandbox-generation.d.ts +1 -1
  481. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
  482. package/dist/serve/vite-sandbox-generation.js +13 -1
  483. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  484. package/dist/serve/worker/client/auth.js +1 -2
  485. package/dist/serve/worker/client/auth.js.map +1 -1
  486. package/dist/serve/worker/client/core.d.ts +21 -1
  487. package/dist/serve/worker/client/core.d.ts.map +1 -1
  488. package/dist/serve/worker/client/core.js +79 -3
  489. package/dist/serve/worker/client/core.js.map +1 -1
  490. package/dist/serve/worker/client/disconnect.js +1 -1
  491. package/dist/serve/worker/client/disconnect.js.map +1 -1
  492. package/dist/serve/worker/client/presence.d.ts.map +1 -1
  493. package/dist/serve/worker/client/presence.js +18 -5
  494. package/dist/serve/worker/client/presence.js.map +1 -1
  495. package/dist/serve/worker/client.d.ts +1 -1
  496. package/dist/serve/worker/client.d.ts.map +1 -1
  497. package/dist/serve/worker/client.js +1 -1
  498. package/dist/serve/worker/client.js.map +1 -1
  499. package/dist/serve/worker/context-resolver.d.ts +30 -0
  500. package/dist/serve/worker/context-resolver.d.ts.map +1 -0
  501. package/dist/serve/worker/context-resolver.js +44 -0
  502. package/dist/serve/worker/context-resolver.js.map +1 -0
  503. package/dist/serve/worker/entry.js +23 -19
  504. package/dist/serve/worker/entry.js.map +1 -1
  505. package/dist/serve/worker/host/core.d.ts +1 -0
  506. package/dist/serve/worker/host/core.d.ts.map +1 -1
  507. package/dist/serve/worker/host/core.js +12 -6
  508. package/dist/serve/worker/host/core.js.map +1 -1
  509. package/dist/serve/worker/host/storage.js +2 -2
  510. package/dist/serve/worker/host-ai.d.ts.map +1 -1
  511. package/dist/serve/worker/host-ai.js +15 -0
  512. package/dist/serve/worker/host-ai.js.map +1 -1
  513. package/dist/serve/worker/host-auth.js +1 -2
  514. package/dist/serve/worker/host-auth.js.map +1 -1
  515. package/dist/serve/worker/index.d.ts +1 -1
  516. package/dist/serve/worker/index.d.ts.map +1 -1
  517. package/dist/serve/worker/index.js +2 -2
  518. package/dist/serve/worker/index.js.map +1 -1
  519. package/dist/serve/worker/port-lifecycle.d.ts +18 -0
  520. package/dist/serve/worker/port-lifecycle.d.ts.map +1 -0
  521. package/dist/serve/worker/port-lifecycle.js +28 -0
  522. package/dist/serve/worker/port-lifecycle.js.map +1 -0
  523. package/dist/serve/worker/protocol.d.ts +4 -0
  524. package/dist/serve/worker/protocol.d.ts.map +1 -1
  525. package/dist/serve/worker/protocol.js.map +1 -1
  526. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  527. package/dist/serve/worker/serve-init.js +15 -3
  528. package/dist/serve/worker/serve-init.js.map +1 -1
  529. package/dist/verify/fixture.d.ts +1 -1
  530. package/package.json +17 -6
  531. package/src/assurance/.generated/conformance-verdicts.ts +68 -1
  532. package/src/bridge/client/dispatch.ts +52 -56
  533. package/src/bridge/client/tool-family-factories.ts +34 -0
  534. package/src/bridge/server/mcp-contract.ts +15 -59
  535. package/src/bridge/server/peer.ts +24 -1
  536. package/src/bridge/server/tool-family-factories.ts +40 -0
  537. package/src/bridge/server/tool-metadata.ts +29 -61
  538. package/src/bridge/tool-families.generated.ts +17 -0
  539. package/src/bridge/tool-families.ts +87 -0
  540. package/src/bridge/tool-family-records/conformance.ts +6 -0
  541. package/src/bridge/tool-family-records/firestore-data.ts +15 -0
  542. package/src/bridge/tool-family-records/firestore-inspect.ts +6 -0
  543. package/src/bridge/tool-family-records/firestore-rules.ts +15 -0
  544. package/src/bridge/tool-family-records/firestore-simulator.ts +16 -0
  545. package/src/bridge/tool-family-records/rtdb-inspection.ts +6 -0
  546. package/src/bundler/externals.ts +55 -0
  547. package/src/bundler/index.ts +21 -0
  548. package/src/cli/cli.test.ts +2 -46
  549. package/src/cli/index.ts +48 -42
  550. package/src/cli/inlined-sdk-scanner.ts +77 -0
  551. package/src/cli/mcp-proxy.ts +4 -4
  552. package/src/cli/parse-args.ts +61 -15
  553. package/src/cli/pyric-config.ts +45 -0
  554. package/src/cli/sandbox-interlock.ts +167 -0
  555. package/src/cli/{dev-runner.ts → sandbox-runner.ts} +142 -86
  556. package/src/cli/serve.ts +182 -115
  557. package/src/cli/snapshot.ts +5 -5
  558. package/src/cli/unsupported-runtime.ts +68 -0
  559. package/src/cli/verify.ts +1 -1
  560. package/src/conformance/.generated/can-i-use-browser.ts +2 -2
  561. package/src/conformance/.generated/can-i-use.ts +2 -2
  562. package/src/conformance/.generated/conformance-docs.ts +1 -1
  563. package/src/functions-rtdb/child.ts +115 -21
  564. package/src/functions-rtdb/development-runtime.ts +5 -1
  565. package/src/functions-rtdb/project.ts +8 -8
  566. package/src/google-endpoints.ts +155 -0
  567. package/src/next/guard.ts +1 -1
  568. package/src/next/runtime-env.ts +5 -0
  569. package/src/next/with-pyric.ts +1 -1
  570. package/src/register/beacon.ts +232 -0
  571. package/src/register/index.ts +68 -6
  572. package/src/register/net-guard.ts +567 -0
  573. package/src/remote/index.ts +9 -9
  574. package/src/serve/ai-diagnostics-relay.ts +243 -0
  575. package/src/serve/ai-proxy.ts +327 -0
  576. package/src/serve/ai-status.ts +109 -0
  577. package/src/serve/ai-terminal-blocks.ts +210 -0
  578. package/src/serve/ai-terminal-text.ts +52 -0
  579. package/src/serve/beacon-route.ts +141 -0
  580. package/src/serve/bundler.ts +10 -10
  581. package/src/serve/entries/active-auth-registry.ts +56 -0
  582. package/src/serve/entries/active-auth.ts +100 -0
  583. package/src/serve/entries/ai.ts +27 -1
  584. package/src/serve/entries/auth-helper-core.ts +5 -0
  585. package/src/serve/entries/auth-helper-dom.ts +27 -3
  586. package/src/serve/entries/auth-helper-runtime.ts +1 -1
  587. package/src/serve/entries/auth.ts +8 -0
  588. package/src/serve/entries/bridge-url.ts +1 -1
  589. package/src/serve/entries/firestore.ts +3 -3
  590. package/src/serve/entries/init.ts +78 -3
  591. package/src/serve/entries/keepalive.ts +1 -1
  592. package/src/serve/entries/runtime.ts +29 -14
  593. package/src/serve/entries/storage.ts +1 -1
  594. package/src/serve/entries/worker-runtime.ts +1 -1
  595. package/src/serve/init-payload.ts +4 -0
  596. package/src/serve/namespace.ts +117 -145
  597. package/src/serve/rules.ts +47 -22
  598. package/src/serve/runtime/chip-config.ts +16 -2
  599. package/src/serve/runtime/chip-dialog.ts +366 -0
  600. package/src/serve/runtime/chip-install.ts +10 -4
  601. package/src/serve/runtime/chip-user-search.ts +391 -0
  602. package/src/serve/runtime/chip.ts +177 -15
  603. package/src/serve/runtime/identity.ts +26 -0
  604. package/src/serve/runtime/manifest.ts +1 -1
  605. package/src/serve/runtime/status.ts +24 -0
  606. package/src/serve/sandbox-session.ts +19 -4
  607. package/src/serve/server.ts +18 -1
  608. package/src/serve/studio/disk-workspace.ts +76 -2
  609. package/src/serve/studio/routes.ts +63 -7
  610. package/src/serve/vite-ai-config.ts +37 -7
  611. package/src/serve/vite-module-swap.ts +0 -28
  612. package/src/serve/vite-plugin.ts +8 -8
  613. package/src/serve/vite-sandbox-generation.ts +16 -1
  614. package/src/serve/worker/client/auth.ts +1 -1
  615. package/src/serve/worker/client/core.ts +80 -3
  616. package/src/serve/worker/client/disconnect.ts +1 -1
  617. package/src/serve/worker/client/presence.ts +25 -5
  618. package/src/serve/worker/client.ts +1 -1
  619. package/src/serve/worker/context-resolver.ts +60 -0
  620. package/src/serve/worker/entry.ts +22 -18
  621. package/src/serve/worker/host/core.ts +9 -7
  622. package/src/serve/worker/host/storage.ts +2 -2
  623. package/src/serve/worker/host-ai.ts +15 -0
  624. package/src/serve/worker/host-auth.ts +1 -1
  625. package/src/serve/worker/index.ts +4 -1
  626. package/src/serve/worker/port-lifecycle.ts +45 -0
  627. package/src/serve/worker/protocol.ts +2 -1
  628. package/src/serve/worker/serve-init.ts +14 -3
  629. package/src/verify/fixture.ts +1 -1
  630. package/README.md.orig +0 -145
  631. package/dist/cli/dev-runner.d.ts.map +0 -1
  632. package/dist/cli/dev-runner.js.map +0 -1
  633. package/dist/serve/site-ui/_astro/_slug_.CXh9yTP1.css +0 -1
  634. package/dist/serve/site-ui/_astro/_slug_.CupVK4TM.css +0 -1
  635. package/dist/serve/site-ui/_astro/_studio_.CfxiQWkk.css +0 -1
  636. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +0 -1
  637. package/dist/serve/site-ui/_astro/app.Ce3MTLQm.js +0 -1
  638. package/dist/serve/site-ui/_astro/app.taqzyjD0.js +0 -11
  639. package/dist/serve/site-ui/_astro/sandbox-controls.BP4M5f1M.js +0 -1169
  640. package/dist/serve/site-ui/_astro/writes.C57paAj2.js +0 -99
  641. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +0 -582
  642. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +0 -448
package/src/cli/serve.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `pyric dev` local dev server with the pyric sandbox standing in for
2
+ * `pyric sandbox` is the local server with the Pyric sandbox standing in for
3
3
  * Firebase. Feels like `firebase serve` (banner, labeled lines, port 3473,
4
4
  * SIGINT shutdown) with the sandbox-flavored extras firebase can't do: the
5
5
  * served page runs an in-browser backend, your `firestore.rules` deploy into
@@ -10,8 +10,9 @@
10
10
  * rules load (fail fast on broken rules) → SDK bundle (cached per pyric
11
11
  * version) → static server with the `/__pyric/` namespace + HTML injection.
12
12
  */
13
+ import { randomBytes } from 'node:crypto';
13
14
  import { join, relative, resolve } from 'node:path';
14
- import { existsSync, readdirSync, readFileSync, statSync, watch as watchFile } from 'node:fs';
15
+ import { existsSync, watch as watchFile } from 'node:fs';
15
16
  import type { ParsedArgs } from './parse-args.js';
16
17
  import { readFirebaseJson, readFirebaseRc, type FirebaseJson } from './firebase-json.js';
17
18
  import { bundleSdk, bundleWorker, defaultSdkEntries, resolveSiteUiDir } from '../serve/bundler.js';
@@ -22,23 +23,30 @@ import {
22
23
  embeddedWorkerVersion,
23
24
  } from '../serve/standalone-assets.js';
24
25
  import { hasSandboxBuildMarker } from '../serve/sandbox-marker.js';
26
+ import { formatBeaconReceipt } from '../serve/beacon-route.js';
25
27
  import type { InitPayload } from '../serve/namespace.js';
28
+ import { formatAiStatusLine } from '../serve/ai-status.js';
26
29
  import { injectServeTags } from '../serve/html-injection.js';
27
30
  import { formatActivityWarning } from '../serve/activity-warning.js';
28
31
  import { consoleServeLogger, startStaticServer, stderrServeLogger, type ServeHandle } from '../serve/server.js';
29
32
  import { createBridgeMount } from '../serve/bridge-mount.js';
30
33
  import { openBrowser, shouldAutoOpen } from '../serve/open-browser.js';
34
+ import { readPyricConfig, type PyricConfig } from './pyric-config.js';
31
35
  import {
32
36
  buildChildEnv,
33
- detectPackageManager,
34
37
  formatStartupEnvExport,
35
- readDevScript,
36
38
  registerModuleUrl,
37
- resolveDevChild,
38
- spawnDevChild,
39
+ resolveSandboxChild,
40
+ spawnSandboxChild,
39
41
  waitForSandboxPeer,
40
- type DevChildHandle,
41
- } from './dev-runner.js';
42
+ type SandboxChildHandle,
43
+ } from './sandbox-runner.js';
44
+ import {
45
+ reportLaunchChecks,
46
+ startBeaconWatchdog,
47
+ type BeaconWatchdog,
48
+ } from './sandbox-interlock.js';
49
+ import { scanForInlinedFirebase } from './inlined-sdk-scanner.js';
42
50
  import {
43
51
  createFunctionsDevelopmentRuntime,
44
52
  createHttpFunctionsPeerReadiness,
@@ -60,7 +68,7 @@ interface HostingConfig {
60
68
  rewrites?: Array<{ source?: string; destination?: string }>;
61
69
  }
62
70
 
63
- /** Extract the single hosting config `pyric dev` v1 supports. Arrays
71
+ /** Extract the single hosting config `pyric sandbox` supports. Arrays
64
72
  * (multi-site) take the first entry with a warning — multi-site is out of
65
73
  * scope (plan section 6). */
66
74
  export function extractHosting(config: FirebaseJson | null): HostingConfig | null {
@@ -84,11 +92,17 @@ export interface ServeRuntime {
84
92
  payload: () => InitPayload;
85
93
  /** HTTP MCP endpoint when `--bridge` is on; null otherwise. */
86
94
  mcpUrl: string | null;
87
- /** The Studio app URL (`/__pyric/ui/`) when `--ui` is on and the build is
95
+ /** The Studio hub URL (`/__pyric/ui/studio`) when `--ui` is on and the build is
88
96
  * present; null otherwise. */
89
97
  uiUrl: string | null;
90
98
  /** Persistence summary (null when `--persist` is off). */
91
99
  persist: { restoredDocs: number; restoredUsers: number } | null;
100
+ /** Handshake beacons posted to `/__pyric/beacon` so far, the interlock
101
+ * watchdog's only input. */
102
+ beaconCount: () => number;
103
+ /** The per-launch secret a beacon must present, placed in every child's
104
+ * `PYRIC_BEACON_TOKEN`. */
105
+ beaconToken: string;
92
106
  }
93
107
 
94
108
  /** The `--json` stdout contract — one line, keep stable; agents parse this.
@@ -147,17 +161,25 @@ export async function startServe(opts: {
147
161
  * (the served project's file tree) + `/__pyric/projects` (single-project
148
162
  * store over `cwd`). The Studio app's `local` mode talks to these. */
149
163
  ui?: boolean;
164
+ /** Explicit opt-in to permissive mode (default-allow RTDB rules when unconfigured). */
165
+ permissive?: boolean;
150
166
  logger?: Parameters<typeof startStaticServer>[0]['logger'];
151
167
  }): Promise<ServeRuntime> {
152
168
  const logger = opts.logger ?? consoleServeLogger();
153
169
 
170
+ // Handshake beacons from pyric-launched children, plus the per-launch secret
171
+ // that authorizes one. Both live here because the route does.
172
+ let beaconsSeen = 0;
173
+ const beaconCount = (): number => beaconsSeen;
174
+ const beaconToken = randomBytes(24).toString('base64url');
175
+
154
176
  // --fresh only means anything against the state.json file `--persist`
155
177
  // maintains — without `--persist` there is no file to discard, so
156
178
  // `--fresh` alone was a silent no-op (nothing happened, nothing said so).
157
179
  // Fail fast instead of pretending to reset something.
158
180
  if (opts.fresh && !opts.persist) {
159
181
  throw new Error(
160
- 'pyric dev: --fresh requires --persist (it discards .pyric/state/state.json). ' +
182
+ 'pyric sandbox: --fresh requires --persist (it discards .pyric/state/state.json). ' +
161
183
  'Browser-stored data is cleared from Studio → Settings → Reset, or DevTools → Clear site data.',
162
184
  );
163
185
  }
@@ -172,9 +194,29 @@ export async function startServe(opts: {
172
194
  logger.note(' ⚠ no firebase.json found — serving the current directory without hosting config');
173
195
  }
174
196
 
197
+ const pyricConfig = await readPyricConfig(opts.cwd);
198
+ if (pyricConfig.rules) {
199
+ if (!config) config = {};
200
+ if (typeof pyricConfig.rules === 'string') {
201
+ config.firestore = { ...config.firestore, rules: pyricConfig.rules };
202
+ } else {
203
+ if (pyricConfig.rules.firestore) {
204
+ config.firestore = { ...config.firestore, rules: pyricConfig.rules.firestore };
205
+ }
206
+ if (pyricConfig.rules.database) {
207
+ config.database = { ...config.database, rules: pyricConfig.rules.database };
208
+ }
209
+ if (pyricConfig.rules.storage) {
210
+ const baseStorage =
211
+ typeof config.storage === 'object' && !Array.isArray(config.storage) ? config.storage : {};
212
+ config.storage = { ...baseStorage, rules: pyricConfig.rules.storage };
213
+ }
214
+ }
215
+ }
216
+
175
217
  const hosting = extractHosting(config);
176
218
  if (Array.isArray(config?.hosting) && (config.hosting as unknown[]).length > 1) {
177
- logger.note(' ⚠ multiple hosting sites configured pyric dev v1 serves the first entry only');
219
+ logger.note(' ⚠ multiple hosting sites configured. pyric sandbox serves the first entry only');
178
220
  }
179
221
  const publicDir = resolve(opts.cwd, hosting?.public ?? '.');
180
222
  if (!existsSync(publicDir)) {
@@ -184,31 +226,31 @@ export async function startServe(opts: {
184
226
  const looksLikeBuildOutput = /(^|[\\/])(dist|build|out)$/.test(publicDir);
185
227
  const hint = looksLikeBuildOutput
186
228
  ? `\n No build yet? Run \`bun run dev\` for the live sandbox dev server, ` +
187
- `or \`bun run build\` then \`pyric dev\` to preview the production build.`
229
+ `or \`bun run build\` then \`pyric sandbox\` to preview the production build.`
188
230
  : '';
189
- throw new Error(`pyric dev: hosting.public directory does not exist: ${publicDir}${hint}`);
231
+ throw new Error(`pyric sandbox: hosting.public directory does not exist: ${publicDir}${hint}`);
190
232
  }
191
233
 
192
234
  // The import map can only remap BARE `firebase/*` specifiers. A plain bundler
193
235
  // build (`vite build`) inlines the real SDK into the app chunk, leaving
194
- // nothing to intercept the page would then talk to REAL Firebase endpoints
236
+ // nothing to intercept: the page would then talk to REAL Firebase endpoints
195
237
  // with the sandbox's fake credentials while the injected banner claims
196
- // otherwise. That hole is structural, so `pyric dev` REFUSES such a dist
238
+ // otherwise. That hole is structural, so `pyric sandbox` refuses such a dist
197
239
  // rather than serving it. A pyric SANDBOX build (`vite build --mode
198
240
  // development`) carries the marker and bundles pyric's in-page adapters, so it
199
- // is trusted and the scan is skipped (marker present no real SDK to find).
241
+ // is trusted and the scan is skipped (marker present, no real SDK to find).
200
242
  if (!hasSandboxBuildMarker(publicDir)) {
201
243
  const inlined = scanForInlinedFirebase(publicDir);
202
244
  if (inlined.length > 0) {
203
245
  throw new Error(
204
- `pyric dev: ${inlined[0]} bundles the REAL firebase SDK, so this dist cannot be ` +
246
+ `pyric sandbox: ${inlined[0]} bundles the real Firebase SDK, so this dist cannot be ` +
205
247
  `sandboxed — its firebase/* calls would reach LIVE Google endpoints, not the ` +
206
248
  `pyric sandbox. Two ways forward:\n` +
207
- ` (a) plain \`pyric dev\` runs the child dev-server flow (the @pyric/cli/vite ` +
249
+ ` (a) \`pyric sandbox -- <command>\` runs the child server with the @pyric/cli/vite ` +
208
250
  `plugin swaps firebase/* live) — use \`bun run dev\`;\n` +
209
251
  ` (b) rebuild as a self-contained sandbox bundle and serve THAT: ` +
210
252
  `\`vite build --mode development\` (or pyric({ swapInBuild: true })) then ` +
211
- `\`pyric dev\`.\n` +
253
+ `\`pyric sandbox\`.\n` +
212
254
  `A plain \`vite build\` is your production build — deploy it, don't sandbox it.`,
213
255
  );
214
256
  }
@@ -285,15 +327,21 @@ export async function startServe(opts: {
285
327
  studio: opts.ui ? { siteUiDir } : false,
286
328
  bridgeUrl: () => mount && origin.port > 0 ? mount.wsUrl(origin) : null,
287
329
  activity: (incident) => logger.note(formatActivityWarning(incident)),
330
+ beaconToken,
331
+ beacon: (report) => {
332
+ beaconsSeen += 1;
333
+ logger.note(formatBeaconReceipt(report));
334
+ },
335
+ permissive: opts.permissive,
288
336
  logger,
289
337
  });
290
338
  } catch (error) {
291
339
  bundle.dispose?.();
292
340
  if (error instanceof SandboxSeedError) {
293
341
  if (error.kind === 'read') {
294
- throw new Error(`pyric dev: failed to read --seed ${error.path}: ${error.detail}`);
342
+ throw new Error(`pyric sandbox: failed to read --seed ${error.path}: ${error.detail}`);
295
343
  }
296
- throw new Error(`pyric dev: --seed must be a JSON object of "collection/doc" fields, ${error.detail}`);
344
+ throw new Error(`pyric sandbox: --seed must be a JSON object of "collection/doc" to fields, ${error.detail}`);
297
345
  }
298
346
  throw error;
299
347
  }
@@ -376,7 +424,7 @@ export async function startServe(opts: {
376
424
  };
377
425
  if (bundle.dispose) handle.server.once('close', bundle.dispose);
378
426
  handle.server.once('close', () => void closeOwnedResources());
379
- const uiUrl = siteUiDir ? `${handle.url}/__pyric/ui/` : null;
427
+ const uiUrl = siteUiDir ? `${handle.url}/__pyric/ui/studio` : null;
380
428
  const docsUrl = siteUiDir ? `${handle.url}/__pyric/ui/docs/` : null;
381
429
 
382
430
  // Hot-reload: the static adapter observes the filesystem; the session owns
@@ -472,7 +520,7 @@ export async function startServe(opts: {
472
520
  session.payload().storageRules
473
521
  ? `✔ rules ${session.summary.rules.storage.sourcePath} → deployed to the storage sandbox (hash ${session.summary.rules.storage.hash}; ` +
474
522
  `edits require a restart — storage rules do not hot-reload)`
475
- : `• rules no storage.rules — storage sandbox runs open (no rules configured)`,
523
+ : `• rules no storage.rules — storage sandbox denies client operations by default`,
476
524
  );
477
525
  if (uiUrl) {
478
526
  logger.info(`✔ studio Pyric Studio: ${uiUrl}`);
@@ -483,6 +531,13 @@ export async function startServe(opts: {
483
531
  if (mount) {
484
532
  logger.info(`✔ bridge MCP endpoint: ${mount.mcpUrl(origin)} (sandbox peers over ws at /__pyric/sandbox)`);
485
533
  }
534
+ // AI is a mounted service like the bridge: `/__pyric/ai-proxy` answers from
535
+ // the first request on, whether or not anything is configured. `pyric
536
+ // sandbox` has no AI flag, so the ENGINE is always the page's own `getAI()`
537
+ // choice (resolved lazily in the browser, since nothing here instantiates a
538
+ // broker to find out); what this server does decide is where the proxy
539
+ // forwards, and that is what the line reports.
540
+ logger.info(formatAiStatusLine({}));
486
541
  let persistSummary: ServeRuntime['persist'] = null;
487
542
  const persistence = session.summary.persistence;
488
543
  if (persistence) {
@@ -531,7 +586,8 @@ export async function startServe(opts: {
531
586
  logger.note('');
532
587
  logger.note(' ⚠ the pyric sandbox runs IN the served page — keep the browser tab open.');
533
588
  logger.note(' Firestore/auth data and persistence stop when no page is open.');
534
- return { handle, publicDir, payload, uiUrl, mcpUrl: mount ? mount.mcpUrl(origin) : null, persist: persistSummary };
589
+ const mcpUrl = mount ? mount.mcpUrl(origin) : null;
590
+ return { handle, publicDir, payload, uiUrl, mcpUrl, persist: persistSummary, beaconCount, beaconToken };
535
591
  }
536
592
 
537
593
  /**
@@ -547,7 +603,7 @@ export function bridgeEnabledFromFlags(flags: { get(key: string): unknown }): bo
547
603
  * A dev child also implies the bridge: the runner injects
548
604
  * `PYRIC_SANDBOX=remote:<url>` into the child, whose remote client dials the
549
605
  * `/__pyric/sandbox` WS — without the bridge mount that upgrade 404s and
550
- * plain `pyric dev -- <cmd>` (or a detected dev script) breaks its own
606
+ * `pyric sandbox -- <cmd>` breaks its own
551
607
  * child. Pure + exported for unit coverage.
552
608
  */
553
609
  export function bridgeEnabledFor(
@@ -560,7 +616,7 @@ export function bridgeEnabledFor(
560
616
 
561
617
  /**
562
618
  * Process-level last line of defense for the dev server: a single bad
563
- * request/WS interaction must never take `pyric dev` down. Node kills the
619
+ * request/WS interaction must never take `pyric sandbox` down. Node kills the
564
620
  * process on an unhandled rejection (default `--unhandled-rejections=throw`
565
621
  * since v15) and on any uncaught exception — and the serve process hosts
566
622
  * long-lived, browser-driven machinery (WS peers, SSE streams, file watchers,
@@ -578,13 +634,13 @@ export function installServeProcessGuard(
578
634
  reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);
579
635
  const onRejection = (reason: unknown): void => {
580
636
  log(
581
- ` ✖ pyric dev: UNHANDLED REJECTION (the server was kept alive please report this):\n` +
637
+ ` ✖ pyric sandbox: unhandled rejection. The server was kept alive. Please report this:\n` +
582
638
  ` ${describe(reason).split('\n').join('\n ')}`,
583
639
  );
584
640
  };
585
641
  const onException = (err: unknown): void => {
586
642
  log(
587
- ` ✖ pyric dev: UNCAUGHT EXCEPTION (the server was kept alive please report this):\n` +
643
+ ` ✖ pyric sandbox: uncaught exception. The server was kept alive. Please report this:\n` +
588
644
  ` ${describe(err).split('\n').join('\n ')}`,
589
645
  );
590
646
  };
@@ -596,10 +652,49 @@ export function installServeProcessGuard(
596
652
  };
597
653
  }
598
654
 
655
+ function resolveServePort(flagPort: unknown, configPort?: number): number {
656
+ if (typeof flagPort === 'string') return Number(flagPort);
657
+ if (typeof flagPort === 'number') return flagPort;
658
+ if (typeof configPort === 'number') return configPort;
659
+ return 3473;
660
+ }
661
+
662
+ function resolveProjectIdentifier(
663
+ flagProject?: unknown,
664
+ envProject?: string,
665
+ configProject?: string,
666
+ rcDefault?: string,
667
+ ): string {
668
+ if (typeof flagProject === 'string' && flagProject.length > 0) return flagProject;
669
+ if (typeof envProject === 'string' && envProject.length > 0) return envProject;
670
+ if (typeof configProject === 'string' && configProject.length > 0) return configProject;
671
+ if (typeof rcDefault === 'string' && rcDefault.length > 0) return rcDefault;
672
+ return 'demo-project';
673
+ }
674
+
675
+ function resolveExplicitCommand(parsed: ParsedArgs): string[] | null {
676
+ if (parsed.passthrough && parsed.passthrough.length > 0) {
677
+ return parsed.passthrough;
678
+ }
679
+ if (parsed.positional.length > 0) {
680
+ return parsed.positional;
681
+ }
682
+ return null;
683
+ }
684
+
599
685
  /** CLI entry. Resolves on SIGINT/SIGTERM after a clean stop. */
600
686
  export async function runServe(parsed: ParsedArgs): Promise<number> {
687
+ const cwd = process.cwd();
688
+ let pyricConfig: PyricConfig = {};
689
+ try {
690
+ pyricConfig = await readPyricConfig(cwd);
691
+ } catch (error) {
692
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
693
+ return 2;
694
+ }
695
+
601
696
  const flagPort = parsed.flags.get('port');
602
- const port = typeof flagPort === 'string' ? Number(flagPort) : 3473;
697
+ const port = resolveServePort(flagPort, pyricConfig.port);
603
698
  if (!Number.isFinite(port) || port < 0 || port > 65535) {
604
699
  process.stderr.write(`pyric: invalid --port '${flagPort}'.\n`);
605
700
  return 1;
@@ -610,7 +705,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
610
705
  const only = parsed.flags.get('only');
611
706
  if (typeof only === 'string' && only !== 'hosting') {
612
707
  process.stderr.write(
613
- `pyric: --only '${only}' is not supported pyric dev v1 serves hosting (with the in-page sandbox standing in for firestore/auth).\n`,
708
+ `pyric: --only '${only}' is not supported. pyric sandbox serves hosting with the in-page sandbox standing in for Firestore and Auth.\n`,
614
709
  );
615
710
  return 1;
616
711
  }
@@ -623,7 +718,6 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
623
718
  // Resolve the child plan BEFORE the server starts: a planned child implies
624
719
  // the bridge (see bridgeEnabledFor) — the child's injected PYRIC_SANDBOX
625
720
  // is useless without the /__pyric/sandbox WS mount.
626
- const cwd = process.cwd();
627
721
  let functionsProject: FunctionsRtdbProject | null;
628
722
  let functionsProjectId: string | null = null;
629
723
  try {
@@ -631,22 +725,25 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
631
725
  if (functionsProject) {
632
726
  const flagProject = parsed.flags.get('project');
633
727
  const rc = await readFirebaseRc(cwd);
634
- functionsProjectId =
635
- (typeof flagProject === 'string' ? flagProject : undefined) ??
636
- process.env.PYRIC_PROJECT ??
637
- rc?.projects?.default ??
638
- 'demo-project';
728
+ functionsProjectId = resolveProjectIdentifier(
729
+ flagProject,
730
+ process.env.PYRIC_PROJECT,
731
+ pyricConfig.project,
732
+ rc?.projects?.default,
733
+ );
639
734
  }
640
735
  } catch (error) {
641
736
  process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
642
737
  return 2;
643
738
  }
644
- const plan = resolveDevChild({
645
- passthrough: parsed.passthrough ?? [],
739
+
740
+ const explicitCommand = resolveExplicitCommand(parsed);
741
+
742
+ const plan = resolveSandboxChild({
743
+ explicitCommand,
744
+ configCommand: pyricConfig.command,
646
745
  noRun: Boolean(parsed.flags.get('no-run')),
647
746
  json,
648
- devScript: readDevScript(cwd),
649
- packageManager: detectPackageManager(cwd),
650
747
  });
651
748
  const bridgeOn = bridgeEnabledFor(parsed.flags, plan, functionsProject);
652
749
 
@@ -663,6 +760,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
663
760
  watch: parsed.flags.get('no-watch') ? false : undefined,
664
761
  persist: Boolean(parsed.flags.get('persist')),
665
762
  fresh: Boolean(parsed.flags.get('fresh')),
763
+ permissive: Boolean(parsed.flags.get('permissive')),
666
764
  // --ui mounts the Pyric Studio storage routes (workspace + projects).
667
765
  ui: uiOn,
668
766
  // --no-capture disables the default-on session capture. The pattern
@@ -675,7 +773,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
675
773
  project:
676
774
  typeof parsed.flags.get('project') === 'string'
677
775
  ? (parsed.flags.get('project') as string)
678
- : process.env.PYRIC_PROJECT ?? functionsProjectId ?? undefined,
776
+ : process.env.PYRIC_PROJECT ?? pyricConfig.project ?? functionsProjectId ?? undefined,
679
777
  });
680
778
  } catch (e) {
681
779
  process.stderr.write(`${e instanceof Error ? e.message : String(e)}\n`);
@@ -691,7 +789,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
691
789
  // (the banner went to stderr). Readiness probe: GET /__pyric/init.json.
692
790
  if (json) process.stdout.write(serveJsonLine(runtime) + '\n');
693
791
 
694
- // Footgun guard (hybrid-MCP plan Phase 3): plain `dev` mounts no MCP bridge,
792
+ // A host-only sandbox mounts no MCP bridge unless one is needed.
695
793
  // so a `pyric mcp-proxy` in an editor cannot attach. Nudge toward --bridge.
696
794
  if (!bridgeOn && !json) {
697
795
  process.stderr.write(
@@ -714,7 +812,8 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
714
812
  void openBrowser(targetUrl);
715
813
  }
716
814
 
717
- let devChild: DevChildHandle | null = null;
815
+ let devChild: SandboxChildHandle | null = null;
816
+ let beaconWatchdog: BeaconWatchdog | null = null;
718
817
  let functionsRuntime: FunctionsDevelopmentRuntime | null = null;
719
818
  let resolveFunctionsExit!: (code: number) => void;
720
819
  const functionsExited = new Promise<number>((resolve) => { resolveFunctionsExit = resolve; });
@@ -737,6 +836,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
737
836
  ]);
738
837
  const stopAfterSignal = async (): Promise<number> => {
739
838
  (json ? process.stderr : process.stdout).write('\nShutting down...\n');
839
+ beaconWatchdog?.stop();
740
840
  if (devChild && devChild.child.exitCode === null) devChild.signal(await signal);
741
841
  await functionsRuntime?.close().catch(() => undefined);
742
842
  await runtime.handle.stop().catch(() => undefined);
@@ -781,6 +881,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
781
881
  baseEnv: process.env,
782
882
  serveUrl: runtime.handle.url,
783
883
  registerUrl: registerModuleUrl(),
884
+ beaconToken: runtime.beaconToken,
784
885
  instance: `${functionsProjectId}-default-rtdb`,
785
886
  location: process.env.PYRIC_FUNCTIONS_RTDB_REGION ?? 'us-central1',
786
887
  projectId: functionsProjectId ?? 'demo-project',
@@ -793,7 +894,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
793
894
  if (result.kind === 'no-peer') {
794
895
  process.stderr.write(
795
896
  ` ⚠ functions not started — no browser tab connected after 30s. ` +
796
- `Open ${runtime.handle.url} and restart pyric dev.\n`,
897
+ `Open ${runtime.handle.url} and restart pyric sandbox.\n`,
797
898
  );
798
899
  } else if (result.kind === 'failed') {
799
900
  process.stderr.write(`${result.error.message}\n`);
@@ -810,16 +911,15 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
810
911
  for (const unsupported of ready.unsupportedTriggers) {
811
912
  process.stderr.write(
812
913
  ` ⚠ functions export ${unsupported.exportName} uses unsupported trigger ` +
813
- `${unsupported.eventType}; it will not run in pyric dev.\n`,
914
+ `${unsupported.eventType}; it will not run in pyric sandbox.\n`,
814
915
  );
815
916
  }
816
917
  }
817
918
  }
818
919
 
819
- // The child runner ("one command, not two"): run the user's own dev
820
- // command with the sandbox environment injected. Precedence: `-- <cmd>`
821
- // wins; else the package.json dev script; else host-only. --no-run forces
822
- // host-only; --json defaults to host-only (explicit `--` still wins).
920
+ // Run the explicit or configured command with the sandbox environment.
921
+ // `--no-run` forces host-only. `--json` skips the configured command, but an
922
+ // explicit command still runs.
823
923
  // (`plan` was resolved above so it could imply the bridge mount.)
824
924
  if (plan) {
825
925
  const info = json ? process.stderr : process.stdout;
@@ -838,23 +938,46 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
838
938
  ` ⚠ no browser tab connected after 30s — starting your command anyway; sandbox ops will fail until ${runtime.handle.url} is open.\n`,
839
939
  );
840
940
  }
941
+ } else if (!json) {
942
+ info.write(
943
+ ` ⓘ Auto-open is disabled (--no-open/CI). The pyric sandbox is browser-resident: ` +
944
+ `open ${runtime.handle.url} to connect if your command performs Firebase operations.\n`,
945
+ );
841
946
  }
842
947
  info.write(
843
948
  `✔ run \`${plan.label}\` — firebase-admin/firebase imports are routed to the sandbox at ${runtime.handle.url}\n`,
844
949
  );
845
- devChild = spawnDevChild(plan, {
846
- cwd,
847
- json,
848
- env: buildChildEnv(process.env, {
849
- serveUrl: runtime.handle.url,
850
- registerUrl: registerModuleUrl(),
851
- }),
950
+ const childEnv = buildChildEnv(process.env, {
951
+ serveUrl: runtime.handle.url,
952
+ registerUrl: registerModuleUrl(),
953
+ beaconToken: runtime.beaconToken,
954
+ });
955
+ // What we are handing the child, stated before it starts: the interlock
956
+ // line and the unsupported-runtime check.
957
+ const interlock = reportLaunchChecks({
958
+ childEnv,
959
+ registerUrl: registerModuleUrl(),
960
+ argv: plan.argv,
961
+ write: (line) => info.write(line),
962
+ });
963
+
964
+ devChild = spawnSandboxChild(plan, { cwd, json, env: childEnv });
965
+ // A child still alive well after launch that never posted a beacon is very
966
+ // likely not intercepted. `startBeaconWatchdog` says why this only warns.
967
+ const beaconsAtSpawn = runtime.beaconCount();
968
+ beaconWatchdog = startBeaconWatchdog({
969
+ label: plan.label,
970
+ beacon: interlock.beacon,
971
+ sawBeacon: () => runtime.beaconCount() > beaconsAtSpawn,
972
+ isAlive: () => devChild !== null && devChild.child.exitCode === null,
973
+ warn: (line) => void process.stderr.write(`${line}\n`),
852
974
  });
853
975
  } else if (!json) {
854
976
  process.stdout.write(
855
977
  formatStartupEnvExport({
856
978
  serveUrl: runtime.handle.url,
857
979
  registerUrl: registerModuleUrl(),
980
+ beaconToken: runtime.beaconToken,
858
981
  }),
859
982
  );
860
983
  }
@@ -866,6 +989,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
866
989
  if (settled) return;
867
990
  settled = true;
868
991
  void (async () => {
992
+ beaconWatchdog?.stop();
869
993
  await functionsRuntime?.close().catch(() => undefined);
870
994
  if (devChild && devChild.child.exitCode === null) {
871
995
  devChild.signal('SIGTERM');
@@ -895,7 +1019,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
895
1019
  if (functionsRuntime) {
896
1020
  void functionsExited.then((code) => {
897
1021
  if (!settled && !shuttingDown) {
898
- process.stderr.write(`pyric dev: Functions child exited unexpectedly (code ${code}).\n`);
1022
+ process.stderr.write(`pyric sandbox: Functions child exited unexpectedly (code ${code}).\n`);
899
1023
  finish(code === 0 ? 1 : code);
900
1024
  }
901
1025
  });
@@ -903,60 +1027,3 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
903
1027
  void signal.then(shutdown);
904
1028
  });
905
1029
  }
906
-
907
- /**
908
- * Detect a bundler build that INLINED the real firebase SDK into its served
909
- * assets (`vite build` output). The served import map remaps only bare
910
- * `firebase/*` specifiers, so such a build cannot be sandboxed — its calls
911
- * reach real Google endpoints. Fingerprints are real-SDK-only endpoint hosts
912
- * that never appear in a sandbox-clean app (whose calls all route to
913
- * `/__pyric/*`). Bounded: depth ≤ 4, ≤ 200 script files, first hit per file.
914
- * Returns publicDir-relative paths of offending assets.
915
- */
916
- export function scanForInlinedFirebase(dir: string): string[] {
917
- const FINGERPRINTS = [
918
- 'identitytoolkit.googleapis.com',
919
- 'firestore.googleapis.com',
920
- 'securetoken.googleapis.com',
921
- 'firebasedatabase.app',
922
- ];
923
- const hits: string[] = [];
924
- let scanned = 0;
925
- const walk = (d: string, rel: string, depth: number): void => {
926
- if (depth > 4 || scanned >= 200) return;
927
- let names: string[];
928
- try {
929
- names = readdirSync(d);
930
- } catch {
931
- return;
932
- }
933
- for (const name of names) {
934
- if (scanned >= 200) return;
935
- const p = join(d, name);
936
- const r = rel ? `${rel}/${name}` : name;
937
- let st;
938
- try {
939
- st = statSync(p);
940
- } catch {
941
- continue;
942
- }
943
- if (st.isDirectory()) {
944
- // The pyric namespace itself never lands in hosting.public, but a
945
- // node_modules inside a served dir would be a scan-cost trap.
946
- // Dot-directories (.next, .git, .pyric) are internal caches and must be ignored.
947
- if (name === 'node_modules' || name.startsWith('.')) continue;
948
- walk(p, r, depth + 1);
949
- } else if (/\.(js|mjs)$/.test(name)) {
950
- scanned++;
951
- try {
952
- const text = readFileSync(p, 'utf8');
953
- if (FINGERPRINTS.some((f) => text.includes(f))) hits.push(r);
954
- } catch {
955
- // unreadable asset: skip
956
- }
957
- }
958
- }
959
- };
960
- walk(dir, '', 0);
961
- return hits;
962
- }
@@ -6,13 +6,13 @@
6
6
  * pyric snapshot [--out FILE] [--port N] [--force] [--json]
7
7
  *
8
8
  * Source preference:
9
- * 1. LIVE state from a running `pyric dev --persist`
9
+ * 1. Live state from a running `pyric sandbox --persist`
10
10
  * (`GET /__pyric/state` — `--port`, else the 3473+ scan window),
11
11
  * 2. else the on-disk `.pyric/state/state.json`,
12
12
  * 3. else exit 2 with a clear message.
13
13
  *
14
14
  * The output is a `PyricStateFile` envelope — directly re-servable:
15
- * `pyric dev --seed <out>` (the state-file shape is detected by its
15
+ * `pyric sandbox --seed <out>` (the state-file shape is detected by its
16
16
  * `version` key and seeds docs + users).
17
17
  */
18
18
  import { existsSync, writeFileSync } from 'node:fs';
@@ -44,7 +44,7 @@ async function fetchLive(port: number): Promise<LiveState | null> {
44
44
  if (!body || typeof body !== 'object' || !('version' in body)) return null;
45
45
  return { envelope: body, projectDir: res.headers.get('x-pyric-project-dir') };
46
46
  } catch {
47
- return null; // nothing listening / not a pyric dev — fall through
47
+ return null; // No Pyric sandbox is listening. Fall through.
48
48
  }
49
49
  }
50
50
 
@@ -110,7 +110,7 @@ export async function runSnapshot(parsed: ParsedArgs, deps: SnapshotDeps = {}):
110
110
  }
111
111
  if (!envelope) {
112
112
  err.write(
113
- 'pyric snapshot: no state found no `pyric dev --persist` is running here and ' +
113
+ 'pyric snapshot: no state found. No `pyric sandbox --persist` is running here and ' +
114
114
  'no .pyric/state/state.json exists. Run with --persist (and use the app) first.\n',
115
115
  );
116
116
  return 2;
@@ -158,7 +158,7 @@ export async function runSnapshot(parsed: ParsedArgs, deps: SnapshotDeps = {}):
158
158
  if (redactedCount > 0) {
159
159
  report.write(` ⓘ redacted ${redactedCount} password(s) — re-run with --include-passwords to keep them\n`);
160
160
  }
161
- report.write(` Re-serve it: pyric dev --seed ${typeof outFlag === 'string' ? outFlag : 'pyric-state.json'}\n`);
161
+ report.write(` Re-serve it: pyric sandbox --seed ${typeof outFlag === 'string' ? outFlag : 'pyric-state.json'}\n`);
162
162
  if (json) out.write(JSON.stringify({ out: outPath, docs, users, source, redactedPasswords: redactedCount }) + '\n');
163
163
  return 0;
164
164
  }