@pyric/cli 0.1.0-alpha.16 → 0.1.0-alpha.17

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 (378) hide show
  1. package/README.md +13 -9
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +80 -72
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +80 -72
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/cli/database-rules.d.ts.map +1 -1
  7. package/dist/cli/database-rules.js +6 -4
  8. package/dist/cli/database-rules.js.map +1 -1
  9. package/dist/cli/dev-runner.d.ts +9 -0
  10. package/dist/cli/dev-runner.d.ts.map +1 -1
  11. package/dist/cli/dev-runner.js +18 -0
  12. package/dist/cli/dev-runner.js.map +1 -1
  13. package/dist/cli/serve.d.ts.map +1 -1
  14. package/dist/cli/serve.js +61 -6
  15. package/dist/cli/serve.js.map +1 -1
  16. package/dist/cli/verify.js +2 -2
  17. package/dist/cli/verify.js.map +1 -1
  18. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  19. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  20. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  21. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  22. package/dist/conformance/.generated/can-i-use.js +1 -1
  23. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  24. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  25. package/dist/conformance/.generated/conformance-docs.js +1 -1
  26. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  27. package/dist/next/client-aliases.d.ts +11 -0
  28. package/dist/next/client-aliases.d.ts.map +1 -0
  29. package/dist/next/client-aliases.js +38 -0
  30. package/dist/next/client-aliases.js.map +1 -0
  31. package/dist/next/dev-rewrites.d.ts +9 -0
  32. package/dist/next/dev-rewrites.d.ts.map +1 -0
  33. package/dist/next/dev-rewrites.js +53 -0
  34. package/dist/next/dev-rewrites.js.map +1 -0
  35. package/dist/next/guard.d.ts +15 -0
  36. package/dist/next/guard.d.ts.map +1 -0
  37. package/dist/next/guard.js +52 -0
  38. package/dist/next/guard.js.map +1 -0
  39. package/dist/next/index.d.ts +12 -0
  40. package/dist/next/index.d.ts.map +1 -0
  41. package/dist/next/index.js +11 -0
  42. package/dist/next/index.js.map +1 -0
  43. package/dist/next/runtime-env.d.ts +7 -0
  44. package/dist/next/runtime-env.d.ts.map +1 -0
  45. package/dist/next/runtime-env.js +13 -0
  46. package/dist/next/runtime-env.js.map +1 -0
  47. package/dist/next/server-external-packages.d.ts +10 -0
  48. package/dist/next/server-external-packages.d.ts.map +1 -0
  49. package/dist/next/server-external-packages.js +34 -0
  50. package/dist/next/server-external-packages.js.map +1 -0
  51. package/dist/next/target-url.d.ts +11 -0
  52. package/dist/next/target-url.d.ts.map +1 -0
  53. package/dist/next/target-url.js +36 -0
  54. package/dist/next/target-url.js.map +1 -0
  55. package/dist/next/turbopack-config.d.ts +9 -0
  56. package/dist/next/turbopack-config.d.ts.map +1 -0
  57. package/dist/next/turbopack-config.js +39 -0
  58. package/dist/next/turbopack-config.js.map +1 -0
  59. package/dist/next/types.d.ts +40 -0
  60. package/dist/next/types.d.ts.map +1 -0
  61. package/dist/next/types.js +5 -0
  62. package/dist/next/types.js.map +1 -0
  63. package/dist/next/webpack-config.d.ts +11 -0
  64. package/dist/next/webpack-config.d.ts.map +1 -0
  65. package/dist/next/webpack-config.js +51 -0
  66. package/dist/next/webpack-config.js.map +1 -0
  67. package/dist/next/with-pyric.d.ts +22 -0
  68. package/dist/next/with-pyric.d.ts.map +1 -0
  69. package/dist/next/with-pyric.js +49 -0
  70. package/dist/next/with-pyric.js.map +1 -0
  71. package/dist/register/app-bridge.d.ts +9 -0
  72. package/dist/register/app-bridge.d.ts.map +1 -0
  73. package/dist/register/app-bridge.js +56 -0
  74. package/dist/register/app-bridge.js.map +1 -0
  75. package/dist/register/hooks.d.ts.map +1 -1
  76. package/dist/register/hooks.js +6 -1
  77. package/dist/register/hooks.js.map +1 -1
  78. package/dist/register/index.js +1 -1
  79. package/dist/register/index.js.map +1 -1
  80. package/dist/register/mapping.d.ts +3 -1
  81. package/dist/register/mapping.d.ts.map +1 -1
  82. package/dist/register/mapping.js +41 -5
  83. package/dist/register/mapping.js.map +1 -1
  84. package/dist/rtdb/rules-json.d.ts +12 -0
  85. package/dist/rtdb/rules-json.d.ts.map +1 -1
  86. package/dist/rtdb/rules-json.js +98 -0
  87. package/dist/rtdb/rules-json.js.map +1 -1
  88. package/dist/serve/bundler.d.ts.map +1 -1
  89. package/dist/serve/bundler.js +2 -0
  90. package/dist/serve/bundler.js.map +1 -1
  91. package/dist/serve/discovery.d.ts +4 -4
  92. package/dist/serve/discovery.d.ts.map +1 -1
  93. package/dist/serve/discovery.js +59 -38
  94. package/dist/serve/discovery.js.map +1 -1
  95. package/dist/serve/entries/app-ai-passthrough.d.ts +8 -0
  96. package/dist/serve/entries/app-ai-passthrough.d.ts.map +1 -0
  97. package/dist/serve/entries/app-ai-passthrough.js +59 -0
  98. package/dist/serve/entries/app-ai-passthrough.js.map +1 -0
  99. package/dist/serve/entries/auth-helper-core.js +9 -7
  100. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  101. package/dist/serve/entries/auth.d.ts +1 -0
  102. package/dist/serve/entries/auth.d.ts.map +1 -1
  103. package/dist/serve/entries/auth.js +1 -0
  104. package/dist/serve/entries/auth.js.map +1 -1
  105. package/dist/serve/entries/bridge-url.d.ts.map +1 -1
  106. package/dist/serve/entries/bridge-url.js +7 -2
  107. package/dist/serve/entries/bridge-url.js.map +1 -1
  108. package/dist/serve/entries/database.d.ts +1 -0
  109. package/dist/serve/entries/database.d.ts.map +1 -1
  110. package/dist/serve/entries/database.js +1 -0
  111. package/dist/serve/entries/database.js.map +1 -1
  112. package/dist/serve/entries/firestore.d.ts +1 -0
  113. package/dist/serve/entries/firestore.d.ts.map +1 -1
  114. package/dist/serve/entries/firestore.js +1 -0
  115. package/dist/serve/entries/firestore.js.map +1 -1
  116. package/dist/serve/entries/init.d.ts.map +1 -1
  117. package/dist/serve/entries/init.js +4 -2
  118. package/dist/serve/entries/init.js.map +1 -1
  119. package/dist/serve/entries/runtime.js +23 -0
  120. package/dist/serve/entries/runtime.js.map +1 -1
  121. package/dist/serve/entries/storage.d.ts +2 -0
  122. package/dist/serve/entries/storage.d.ts.map +1 -1
  123. package/dist/serve/entries/storage.js +9 -2
  124. package/dist/serve/entries/storage.js.map +1 -1
  125. package/dist/serve/html-injection.d.ts +3 -1
  126. package/dist/serve/html-injection.d.ts.map +1 -1
  127. package/dist/serve/html-injection.js +27 -1
  128. package/dist/serve/html-injection.js.map +1 -1
  129. package/dist/serve/rules.js +2 -2
  130. package/dist/serve/rules.js.map +1 -1
  131. package/dist/serve/runtime/chip-config.d.ts +1 -1
  132. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  133. package/dist/serve/runtime/chip-config.js +16 -8
  134. package/dist/serve/runtime/chip-config.js.map +1 -1
  135. package/dist/serve/sandbox-session.d.ts +1 -0
  136. package/dist/serve/sandbox-session.d.ts.map +1 -1
  137. package/dist/serve/sandbox-session.js +30 -2
  138. package/dist/serve/sandbox-session.js.map +1 -1
  139. package/dist/serve/site-ui/_astro/_studio_.B6b_G1ev.css +1 -0
  140. package/dist/serve/site-ui/_astro/app.bnmVTkIY.js +11 -0
  141. package/dist/serve/site-ui/_astro/app.t6u-adB_.js +1 -0
  142. package/dist/serve/site-ui/_astro/{chess-showcase.CnoxIle5.js → chess-showcase.kC8dXLKY.js} +1 -1
  143. package/dist/serve/site-ui/_astro/{example-runtime.R1d96L6-.js → example-runtime.D79PnoSk.js} +1 -1
  144. package/dist/serve/site-ui/_astro/index.DzVde04M.js +1 -0
  145. package/dist/serve/site-ui/_astro/reads.BYBRLbsE.js +1 -0
  146. package/dist/serve/site-ui/_astro/sandbox-controls.C9Aaazt8.js +1252 -0
  147. package/dist/serve/site-ui/_astro/{seed.EyI3VYEu.js → seed.DANAIyRw.js} +1 -1
  148. package/dist/serve/site-ui/auth/index.html +2 -2
  149. package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
  150. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +1 -1
  151. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
  152. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
  153. package/dist/serve/site-ui/docs/ai-compat/index.html +85 -85
  154. package/dist/serve/site-ui/docs/ai-compat.md +84 -84
  155. package/dist/serve/site-ui/docs/api-reference/index.html +3 -1
  156. package/dist/serve/site-ui/docs/api-reference.md +2 -0
  157. package/dist/serve/site-ui/docs/app-compat/index.html +28 -28
  158. package/dist/serve/site-ui/docs/app-compat.md +27 -27
  159. package/dist/serve/site-ui/docs/auth-compat/index.html +122 -122
  160. package/dist/serve/site-ui/docs/auth-compat.md +121 -121
  161. package/dist/serve/site-ui/docs/build/ai-logic/index.html +1 -1
  162. package/dist/serve/site-ui/docs/build/authentication/index.html +1 -1
  163. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +1 -1
  164. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
  165. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
  166. package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
  167. package/dist/serve/site-ui/docs/conformance-scores/index.html +4 -4
  168. package/dist/serve/site-ui/docs/conformance-scores.md +3 -3
  169. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -6
  170. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +5 -5
  171. package/dist/serve/site-ui/docs/database-compat/index.html +200 -448
  172. package/dist/serve/site-ui/docs/database-compat.md +198 -461
  173. package/dist/serve/site-ui/docs/examples/chess/index.html +2 -2
  174. package/dist/serve/site-ui/docs/examples/index.html +1 -1
  175. package/dist/serve/site-ui/docs/firestore-compat/index.html +186 -195
  176. package/dist/serve/site-ui/docs/firestore-compat.md +184 -195
  177. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +15 -15
  178. package/dist/serve/site-ui/docs/functions-rtdb-compat.md +14 -14
  179. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
  180. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +57 -0
  181. package/dist/serve/site-ui/docs/get-started/nextjs.md +86 -0
  182. package/dist/serve/site-ui/docs/get-started/start-building/index.html +25 -8
  183. package/dist/serve/site-ui/docs/get-started/start-building.md +34 -5
  184. package/dist/serve/site-ui/docs/get-started/vite/index.html +26 -0
  185. package/dist/serve/site-ui/docs/get-started/vite.md +45 -0
  186. package/dist/serve/site-ui/docs/index.json +668 -103
  187. package/dist/serve/site-ui/docs/messaging-compat/index.html +56 -56
  188. package/dist/serve/site-ui/docs/messaging-compat.md +55 -55
  189. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +1 -1
  190. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
  191. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
  192. package/dist/serve/site-ui/docs/overview/index.html +1 -1
  193. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +39 -13
  194. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api.md +28 -2
  195. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
  196. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +38 -6
  197. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api.md +43 -0
  198. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +9 -1
  199. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +8 -0
  200. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
  201. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +27 -4
  202. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api.md +23 -0
  203. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
  204. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
  205. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
  206. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +1 -1
  207. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
  208. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
  209. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
  210. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
  211. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
  212. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
  213. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
  214. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
  215. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
  216. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +123 -0
  217. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +99 -0
  218. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +127 -0
  219. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api.md +174 -0
  220. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
  221. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
  222. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +570 -326
  223. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +198 -6
  224. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
  225. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +1 -1
  226. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +1 -1
  227. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +2971 -627
  228. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +2873 -517
  229. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
  230. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
  231. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +43 -3
  232. package/dist/serve/site-ui/docs/pyric-rules-reference-api.md +8 -0
  233. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +26 -2
  234. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +24 -0
  235. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
  236. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +77 -9
  237. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +28 -13
  238. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +240 -63
  239. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +164 -5
  240. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
  241. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
  242. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
  243. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
  244. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
  245. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
  246. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
  247. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
  248. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
  249. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
  250. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
  251. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
  252. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +2 -1
  253. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +1 -0
  254. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
  255. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
  256. package/dist/serve/site-ui/docs/rules-compat/index.html +87 -79
  257. package/dist/serve/site-ui/docs/rules-compat.md +86 -78
  258. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
  259. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
  260. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
  261. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
  262. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
  263. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
  264. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
  265. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
  266. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
  267. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
  268. package/dist/serve/site-ui/docs/storage-compat/index.html +119 -125
  269. package/dist/serve/site-ui/docs/storage-compat.md +118 -124
  270. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
  271. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
  272. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +1 -1
  273. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
  274. package/dist/serve/site-ui/docs/tutorial/index.html +1 -1
  275. package/dist/serve/site-ui/examples/chess/index.html +1 -1
  276. package/dist/serve/site-ui/examples/firestore-first-write/index.html +1 -1
  277. package/dist/serve/site-ui/firestore/index.html +2 -2
  278. package/dist/serve/site-ui/index.html +2 -2
  279. package/dist/serve/site-ui/llms.txt +6 -2
  280. package/dist/serve/site-ui/rtdb/index.html +2 -2
  281. package/dist/serve/site-ui/settings/index.html +2 -2
  282. package/dist/serve/site-ui/storage/index.html +2 -2
  283. package/dist/serve/site-ui/traffic/index.html +2 -2
  284. package/dist/serve/vite-ai-config.d.ts +4 -1
  285. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  286. package/dist/serve/vite-ai-config.js +83 -19
  287. package/dist/serve/vite-ai-config.js.map +1 -1
  288. package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -1
  289. package/dist/serve/vite-generation-rules-watch.js +61 -14
  290. package/dist/serve/vite-generation-rules-watch.js.map +1 -1
  291. package/dist/serve/vite-module-swap.d.ts +4 -1
  292. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  293. package/dist/serve/vite-module-swap.js +106 -21
  294. package/dist/serve/vite-module-swap.js.map +1 -1
  295. package/dist/serve/vite-plugin.d.ts.map +1 -1
  296. package/dist/serve/vite-plugin.js +45 -5
  297. package/dist/serve/vite-plugin.js.map +1 -1
  298. package/dist/serve/vite-sandbox-generation.js +1 -1
  299. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  300. package/dist/serve/worker/client/resumable.d.ts +30 -0
  301. package/dist/serve/worker/client/resumable.d.ts.map +1 -0
  302. package/dist/serve/worker/client/resumable.js +416 -0
  303. package/dist/serve/worker/client/resumable.js.map +1 -0
  304. package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -1
  305. package/dist/serve/worker/client/rtdb-references.js +4 -1
  306. package/dist/serve/worker/client/rtdb-references.js.map +1 -1
  307. package/dist/serve/worker/client/storage.d.ts +16 -2
  308. package/dist/serve/worker/client/storage.d.ts.map +1 -1
  309. package/dist/serve/worker/client/storage.js +57 -6
  310. package/dist/serve/worker/client/storage.js.map +1 -1
  311. package/dist/serve/worker/host/rules.d.ts.map +1 -1
  312. package/dist/serve/worker/host/rules.js +2 -1
  313. package/dist/serve/worker/host/rules.js.map +1 -1
  314. package/dist/serve/worker/index.d.ts +1 -1
  315. package/dist/serve/worker/index.d.ts.map +1 -1
  316. package/dist/serve/worker/index.js +1 -1
  317. package/dist/serve/worker/index.js.map +1 -1
  318. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  319. package/dist/serve/worker/serve-init.js +31 -0
  320. package/dist/serve/worker/serve-init.js.map +1 -1
  321. package/package.json +15 -4
  322. package/src/assurance/.generated/conformance-verdicts.ts +80 -72
  323. package/src/cli/cli.test.ts +14 -0
  324. package/src/cli/database-rules.ts +6 -4
  325. package/src/cli/dev-runner.ts +21 -0
  326. package/src/cli/serve.ts +62 -5
  327. package/src/cli/verify.ts +2 -2
  328. package/src/conformance/.generated/can-i-use-browser.ts +1 -1
  329. package/src/conformance/.generated/can-i-use.ts +1 -1
  330. package/src/conformance/.generated/conformance-docs.ts +1 -1
  331. package/src/next/client-aliases.ts +39 -0
  332. package/src/next/dev-rewrites.ts +77 -0
  333. package/src/next/guard.ts +61 -0
  334. package/src/next/index.ts +16 -0
  335. package/src/next/runtime-env.ts +18 -0
  336. package/src/next/server-external-packages.ts +43 -0
  337. package/src/next/target-url.ts +46 -0
  338. package/src/next/turbopack-config.ts +54 -0
  339. package/src/next/types.ts +47 -0
  340. package/src/next/webpack-config.ts +71 -0
  341. package/src/next/with-pyric.ts +58 -0
  342. package/src/register/app-bridge.ts +79 -0
  343. package/src/register/hooks.ts +6 -1
  344. package/src/register/index.ts +1 -1
  345. package/src/register/mapping.ts +50 -4
  346. package/src/rtdb/rules-json.ts +110 -0
  347. package/src/serve/bundler.ts +2 -0
  348. package/src/serve/discovery.ts +65 -44
  349. package/src/serve/entries/app-ai-passthrough.ts +83 -0
  350. package/src/serve/entries/auth-helper-core.ts +9 -7
  351. package/src/serve/entries/auth.ts +1 -0
  352. package/src/serve/entries/bridge-url.ts +9 -2
  353. package/src/serve/entries/database.ts +1 -0
  354. package/src/serve/entries/firestore.ts +1 -0
  355. package/src/serve/entries/init.ts +5 -2
  356. package/src/serve/entries/runtime.ts +25 -0
  357. package/src/serve/entries/storage.ts +12 -1
  358. package/src/serve/html-injection.ts +26 -1
  359. package/src/serve/rules.ts +2 -2
  360. package/src/serve/runtime/chip-config.ts +19 -6
  361. package/src/serve/sandbox-session.ts +31 -2
  362. package/src/serve/vite-ai-config.ts +86 -19
  363. package/src/serve/vite-generation-rules-watch.ts +67 -15
  364. package/src/serve/vite-module-swap.ts +121 -21
  365. package/src/serve/vite-plugin.ts +44 -6
  366. package/src/serve/vite-sandbox-generation.ts +1 -1
  367. package/src/serve/worker/client/resumable.ts +506 -0
  368. package/src/serve/worker/client/rtdb-references.ts +4 -1
  369. package/src/serve/worker/client/storage.ts +77 -7
  370. package/src/serve/worker/host/rules.ts +2 -1
  371. package/src/serve/worker/index.ts +4 -0
  372. package/src/serve/worker/serve-init.ts +30 -0
  373. package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +0 -1
  374. package/dist/serve/site-ui/_astro/app.4HeLP_FA.js +0 -109
  375. package/dist/serve/site-ui/_astro/app.BgSnCR5G.js +0 -1
  376. package/dist/serve/site-ui/_astro/index.BJiOemMX.js +0 -1
  377. package/dist/serve/site-ui/_astro/reads.BrKNdKAa.js +0 -1
  378. package/dist/serve/site-ui/_astro/sandbox-controls.BTb3EbQp.js +0 -1153
@@ -63,6 +63,7 @@ export interface SandboxSession {
63
63
  payload(): InitPayload;
64
64
  handle(req: IncomingMessage, res: ServerResponse, url: URL): boolean | Promise<boolean>;
65
65
  reloadFirestoreRules(): Promise<RulesReloadResult>;
66
+ reloadDatabaseRules(): Promise<RulesReloadResult>;
66
67
  close(): Promise<void>;
67
68
  }
68
69
 
@@ -93,6 +94,8 @@ export async function createSandboxSession(
93
94
  const live = {
94
95
  rules: firestore.rules,
95
96
  rulesHash: firestore.rulesHash,
97
+ databaseRules: database.rules,
98
+ databaseRulesHash: database.rulesHash,
96
99
  };
97
100
  const events = createEventHub();
98
101
  const capture: CaptureStore | undefined = (options.capture ?? true)
@@ -145,8 +148,8 @@ export async function createSandboxSession(
145
148
  const payload = (): InitPayload => ({
146
149
  rules: live.rules,
147
150
  rulesHash: live.rulesHash,
148
- databaseRules: database.rules,
149
- databaseRulesHash: database.rulesHash,
151
+ databaseRules: live.databaseRules,
152
+ databaseRulesHash: live.databaseRulesHash,
150
153
  databaseUrl: database.databaseUrl,
151
154
  storageRules: storage.rules,
152
155
  storageRulesHash: storage.rulesHash,
@@ -217,6 +220,31 @@ export async function createSandboxSession(
217
220
  return { kind: 'rejected', error: error instanceof Error ? error : new Error(String(error)) };
218
221
  }
219
222
  };
223
+ const reloadDatabaseRules = async (): Promise<RulesReloadResult> => {
224
+ const isMissingDatabaseRules = database.sourcePath === null;
225
+ if (isMissingDatabaseRules) {
226
+ return { kind: 'not-configured' };
227
+ }
228
+ try {
229
+ const updated = await loadProjectDatabaseRules(options.projectDir, options.firebaseConfig);
230
+ const isMissingUpdatedRules = updated.rules === null || updated.rulesHash === null;
231
+ if (isMissingUpdatedRules) {
232
+ return { kind: 'not-configured' };
233
+ }
234
+ live.databaseRules = updated.rules;
235
+ live.databaseRulesHash = updated.rulesHash;
236
+ events.broadcast('rtdb-rules-update', { rules: updated.rules, rulesHash: updated.rulesHash });
237
+ return { kind: 'reloaded', rulesHash: updated.rulesHash as string, clients: events.clientCount() };
238
+ } catch (error) {
239
+ const isErrorInstance = error instanceof Error;
240
+ let errorResult: Error = new Error(String(error));
241
+ if (isErrorInstance) {
242
+ errorResult = error as Error;
243
+ }
244
+ return { kind: 'rejected', error: errorResult };
245
+ }
246
+ };
247
+
220
248
  let closePromise: Promise<void> | null = null;
221
249
  const close = (): Promise<void> => {
222
250
  closePromise ??= Promise.resolve().then(() => events.close());
@@ -228,6 +256,7 @@ export async function createSandboxSession(
228
256
  payload,
229
257
  handle: namespace,
230
258
  reloadFirestoreRules,
259
+ reloadDatabaseRules,
231
260
  close,
232
261
  };
233
262
  }
@@ -9,6 +9,8 @@ const AI_PROXY_PATH = '/__pyric/ai-proxy';
9
9
  export type PyricAiEngineConfig = Extract<NonNullable<AIOptions['engine']>, { kind: string }>;
10
10
 
11
11
  export interface PyricAiOptions {
12
+ /** Mode for AI Logic: 'sandbox' (local mirrors) or 'production' (pass-through to Google AI / Vertex AI). */
13
+ mode?: 'sandbox' | 'production';
12
14
  /** Simple OpenAI-compatible model selection through Pyric's same-origin proxy. */
13
15
  model?: string;
14
16
  /** Advanced declarative engine configuration. */
@@ -18,6 +20,7 @@ export interface PyricAiOptions {
18
20
  }
19
21
 
20
22
  export interface ResolvedViteAiConfig {
23
+ mode: 'sandbox' | 'production';
21
24
  engineWire: AiEngineConfigWire | undefined;
22
25
  proxyUpstream: string | undefined;
23
26
  }
@@ -26,8 +29,9 @@ export interface ResolvedViteAiConfig {
26
29
  export function viteWorkerEpochSalt(
27
30
  projectKey: string,
28
31
  engineWire: AiEngineConfigWire | undefined,
32
+ mode: 'sandbox' | 'production' = 'sandbox',
29
33
  ): string {
30
- return JSON.stringify({ projectKey, aiEngine: engineWire ?? null });
34
+ return JSON.stringify({ projectKey, aiEngine: engineWire ?? null, aiMode: mode });
31
35
  }
32
36
 
33
37
  /** Load env using Vite's `envDir`-relative-to-root convention. */
@@ -45,20 +49,30 @@ export function loadViteAiEnv(
45
49
 
46
50
  /** Convert a public declarative engine into the JSON-safe worker wire shape. */
47
51
  export function engineConfigToWire(engine: PyricAiEngineConfig): AiEngineConfigWire {
48
- if (engine.kind === 'openai') {
49
- return {
52
+ const isOpenAiEngine = engine.kind === 'openai';
53
+ if (isOpenAiEngine) {
54
+ const result: Record<string, unknown> = {
50
55
  kind: 'openai',
51
- baseUrl: engine.baseUrl ?? AI_PROXY_PATH,
52
- ...(engine.model !== undefined ? { model: engine.model } : {}),
53
- ...(engine.modelMap !== undefined ? { modelMap: engine.modelMap } : {}),
56
+ baseUrl: engine.baseUrl !== undefined && engine.baseUrl !== null ? engine.baseUrl : AI_PROXY_PATH,
54
57
  };
58
+ const hasModel = engine.model !== undefined;
59
+ if (hasModel) {
60
+ result.model = engine.model;
61
+ }
62
+ const hasModelMap = engine.modelMap !== undefined;
63
+ if (hasModelMap) {
64
+ result.modelMap = engine.modelMap;
65
+ }
66
+ return result as AiEngineConfigWire;
55
67
  }
56
- return {
68
+ const result: Record<string, unknown> = {
57
69
  kind: 'scripted',
58
- ...(engine.script !== undefined
59
- ? { script: engine.script as unknown as Array<Record<string, unknown>> }
60
- : {}),
61
70
  };
71
+ const hasScript = engine.script !== undefined;
72
+ if (hasScript) {
73
+ result.script = engine.script as unknown as Array<Record<string, unknown>>;
74
+ }
75
+ return result as AiEngineConfigWire;
62
76
  }
63
77
 
64
78
  /** Resolve the plugin's explicit-options-over-Vite-env AI convention. */
@@ -66,20 +80,73 @@ export function resolveViteAiConfig(
66
80
  options: PyricAiOptions | undefined,
67
81
  env: Record<string, string | undefined>,
68
82
  ): ResolvedViteAiConfig {
69
- if (options?.model !== undefined && options.engine !== undefined) {
83
+ const explicitModel = options?.model;
84
+ const explicitEngine = options?.engine;
85
+ const hasModelOption = explicitModel !== undefined;
86
+ const hasEngineOption = explicitEngine !== undefined;
87
+ const hasBothModelAndEngine = hasModelOption && hasEngineOption;
88
+ if (hasBothModelAndEngine) {
70
89
  throw new Error('@pyric/cli/vite: Choose either ai.model or ai.engine, not both.');
71
90
  }
72
91
 
73
- const model = options?.model?.trim() || env.PYRIC_AI_MODEL?.trim();
74
- const engineWire = options?.engine
75
- ? engineConfigToWire(options.engine)
76
- : model
77
- ? engineConfigToWire({ kind: 'openai', baseUrl: AI_PROXY_PATH, model })
78
- : undefined;
92
+ let mode: 'sandbox' | 'production' = 'sandbox';
93
+ const explicitMode = options?.mode;
94
+ const hasExplicitMode = explicitMode !== undefined;
95
+ if (hasExplicitMode) {
96
+ mode = explicitMode;
97
+ } else {
98
+ const isEnvProductionMode = env.PYRIC_AI_MODE === 'production';
99
+ const isEnvPassthroughFlag = env.PYRIC_AI_PASSTHROUGH === '1';
100
+ const isProductionEnv = isEnvProductionMode || isEnvPassthroughFlag;
101
+ if (isProductionEnv) {
102
+ mode = 'production';
103
+ }
104
+ }
105
+
106
+ const isProductionMode = mode === 'production';
107
+ const hasAnyEngineConfig = hasModelOption || hasEngineOption;
108
+ const isInvalidProductionConfig = isProductionMode && hasAnyEngineConfig;
109
+ if (isInvalidProductionConfig) {
110
+ throw new Error('@pyric/cli/vite: Cannot configure ai.model or ai.engine when ai.mode is set to "production".');
111
+ }
112
+
113
+ let model: string | undefined = undefined;
114
+ const envModel = env.PYRIC_AI_MODEL;
115
+ if (explicitModel !== undefined) {
116
+ model = explicitModel.trim();
117
+ } else if (envModel !== undefined) {
118
+ model = envModel.trim();
119
+ }
120
+ const hasNonEmptyModel = model !== undefined && model !== '';
121
+ if (!hasNonEmptyModel) {
122
+ model = undefined;
123
+ }
124
+
125
+ let engineWire: AiEngineConfigWire | undefined = undefined;
126
+ if (!isProductionMode) {
127
+ if (explicitEngine !== undefined) {
128
+ engineWire = engineConfigToWire(explicitEngine);
129
+ } else if (model !== undefined) {
130
+ engineWire = engineConfigToWire({ kind: 'openai', baseUrl: AI_PROXY_PATH, model });
131
+ }
132
+ }
133
+
134
+ let proxyUpstream: string | undefined = undefined;
135
+ const explicitProxyUpstream = options?.proxyUpstream;
136
+ const envProxyUpstream = env.PYRIC_AI_PROXY_UPSTREAM;
137
+ if (explicitProxyUpstream !== undefined) {
138
+ proxyUpstream = explicitProxyUpstream.trim();
139
+ } else if (envProxyUpstream !== undefined) {
140
+ proxyUpstream = envProxyUpstream.trim();
141
+ }
142
+ const hasNonEmptyProxyUpstream = proxyUpstream !== undefined && proxyUpstream !== '';
143
+ if (!hasNonEmptyProxyUpstream) {
144
+ proxyUpstream = undefined;
145
+ }
79
146
 
80
147
  return {
148
+ mode,
81
149
  engineWire,
82
- proxyUpstream:
83
- options?.proxyUpstream?.trim() || env.PYRIC_AI_PROXY_UPSTREAM?.trim() || undefined,
150
+ proxyUpstream,
84
151
  };
85
152
  }
@@ -8,30 +8,82 @@ export function watchViteGenerationRules(input: {
8
8
  session: SandboxSession;
9
9
  }): (() => void) | null {
10
10
  const { server, session } = input;
11
- const rulesFile = session.summary.rules.firestore.sourcePath;
12
- if (!rulesFile) return null;
11
+ const firestoreFile = session.summary.rules.firestore.sourcePath;
12
+ const databaseFile = session.summary.rules.database.sourcePath;
13
+ const hasFirestoreFile = firestoreFile !== null;
14
+ const hasDatabaseFile = databaseFile !== null;
15
+ const hasNeitherFile = !hasFirestoreFile && !hasDatabaseFile;
16
+ if (hasNeitherFile) {
17
+ return null;
18
+ }
13
19
 
14
20
  let debounce: ReturnType<typeof setTimeout> | null = null;
15
21
  const onRulesChange = (file: string): void => {
16
- if (path.resolve(file) !== path.resolve(rulesFile)) return;
17
- if (debounce) clearTimeout(debounce);
22
+ const resolvedFile = path.resolve(file);
23
+ let isFirestoreMatch = false;
24
+ if (hasFirestoreFile) {
25
+ const firestoreResolved = path.resolve(firestoreFile);
26
+ isFirestoreMatch = resolvedFile === firestoreResolved;
27
+ }
28
+ let isDatabaseMatch = false;
29
+ if (hasDatabaseFile) {
30
+ const databaseResolved = path.resolve(databaseFile);
31
+ isDatabaseMatch = resolvedFile === databaseResolved;
32
+ }
33
+ const isNeitherMatch = !isFirestoreMatch && !isDatabaseMatch;
34
+ if (isNeitherMatch) {
35
+ return;
36
+ }
37
+ const hasDebounce = debounce !== null;
38
+ if (hasDebounce) {
39
+ clearTimeout(debounce as ReturnType<typeof setTimeout>);
40
+ }
18
41
  debounce = setTimeout(() => {
19
- void session.reloadFirestoreRules().then((result) => {
20
- if (result.kind === 'reloaded') {
21
- server.config.logger.info(` ↻ [pyric] rules reloaded (${result.rulesHash})`);
22
- } else if (result.kind === 'rejected') {
23
- server.config.logger.warn(
24
- ` ⚠ [pyric] rules NOT reloaded (last-good stays live): ${result.error.message}`,
25
- );
26
- }
27
- });
42
+ if (isFirestoreMatch) {
43
+ void session.reloadFirestoreRules().then((result) => {
44
+ const isReloaded = result.kind === 'reloaded';
45
+ if (isReloaded) {
46
+ server.config.logger.info(` ↻ [pyric] rules reloaded (${result.rulesHash})`);
47
+ } else {
48
+ const isRejected = result.kind === 'rejected';
49
+ if (isRejected) {
50
+ server.config.logger.warn(
51
+ ` ⚠ [pyric] rules NOT reloaded (last-good stays live): ${result.error.message}`,
52
+ );
53
+ }
54
+ }
55
+ });
56
+ }
57
+ if (isDatabaseMatch) {
58
+ void session.reloadDatabaseRules().then((result) => {
59
+ const isReloaded = result.kind === 'reloaded';
60
+ if (isReloaded) {
61
+ server.config.logger.info(` ↻ [pyric] rtdb rules reloaded (${result.rulesHash})`);
62
+ } else {
63
+ const isRejected = result.kind === 'rejected';
64
+ if (isRejected) {
65
+ server.config.logger.warn(
66
+ ` ⚠ [pyric] rtdb rules NOT reloaded (last-good stays live): ${result.error.message}`,
67
+ );
68
+ }
69
+ }
70
+ });
71
+ }
28
72
  }, 150);
29
73
  };
30
74
 
31
- server.watcher.add(rulesFile);
75
+ if (hasFirestoreFile) {
76
+ server.watcher.add(firestoreFile);
77
+ }
78
+ if (hasDatabaseFile) {
79
+ server.watcher.add(databaseFile);
80
+ }
32
81
  server.watcher.on('change', onRulesChange);
33
82
  return () => {
34
- if (debounce) clearTimeout(debounce);
83
+ const hasDebounce = debounce !== null;
84
+ if (hasDebounce) {
85
+ clearTimeout(debounce as ReturnType<typeof setTimeout>);
86
+ }
35
87
  server.watcher.off('change', onRulesChange);
36
88
  };
37
89
  }
@@ -45,10 +45,18 @@ export function createViteModuleContext(): ViteModuleContext {
45
45
  return { entries, cliRoot: packageRootOf(entries.init) };
46
46
  }
47
47
 
48
+ export interface ViteModuleSwapOptions {
49
+ getAiMode?: () => 'sandbox' | 'production';
50
+ }
51
+
48
52
  /** Own the Vite and optimizer forms of the Firebase-module swap. */
49
- export function createViteModuleSwap(context: ViteModuleContext): ViteModuleSwap {
53
+ export function createViteModuleSwap(
54
+ context: ViteModuleContext,
55
+ options?: ViteModuleSwapOptions,
56
+ ): ViteModuleSwap {
50
57
  const { entries, cliRoot } = context;
51
58
  const pyricRoot = pyricPackageRoot();
59
+ const aiMode = () => options?.getAiMode?.() ?? 'sandbox';
52
60
 
53
61
  const isPyricImporter = (importer: string | undefined): boolean => {
54
62
  if (!importer) return false;
@@ -68,28 +76,72 @@ export function createViteModuleSwap(context: ViteModuleContext): ViteModuleSwap
68
76
  name: 'pyric-sandbox-optimizer',
69
77
  setup(build) {
70
78
  build.onResolve({ filter: FIREBASE_SPECIFIER }, (args) => {
71
- const subpath = FIREBASE_SPECIFIER.exec(args.path)![1]!;
72
- if (SERVED_FIREBASE_SUBPATHS.has(subpath)) {
73
- return { path: entries[entryKey(subpath)]! };
79
+ const isShadowBridgeImporter = args.importer !== undefined && args.importer !== '' &&
80
+ (args.importer.includes('app-ai-passthrough') || args.importer.includes('app-bridge'));
81
+ const isFirebaseAppSpecifier = args.path === 'firebase/app';
82
+ const isBypassedBridgeImport = isShadowBridgeImporter && isFirebaseAppSpecifier;
83
+ if (isBypassedBridgeImport) {
84
+ return null;
85
+ }
86
+
87
+ const match = FIREBASE_SPECIFIER.exec(args.path);
88
+ const subpath = match !== null && match[1] !== undefined ? match[1] : '';
89
+ const isProductionAiMode = aiMode() === 'production';
90
+ if (isProductionAiMode) {
91
+ const isAiSubpath = subpath === 'ai';
92
+ if (isAiSubpath) {
93
+ return null;
94
+ }
95
+ const isAppSubpath = subpath === 'app';
96
+ const passthroughEntry = entries['app-ai-passthrough'];
97
+ const hasPassthroughEntry = passthroughEntry !== undefined;
98
+ const shouldUsePassthroughBridge = isAppSubpath && hasPassthroughEntry;
99
+ if (shouldUsePassthroughBridge) {
100
+ return { path: passthroughEntry };
101
+ }
102
+ }
103
+
104
+ const isServedSubpath = SERVED_FIREBASE_SUBPATHS.has(subpath);
105
+ if (isServedSubpath) {
106
+ const key = entryKey(subpath);
107
+ const entryPath = entries[key];
108
+ if (entryPath !== undefined) {
109
+ return { path: entryPath };
110
+ }
74
111
  }
75
112
  return null;
76
113
  });
77
114
  build.onResolve({ filter: NODE_BUILTIN_RE }, (args) => {
78
- if (!isOurCode(args.importer)) return null;
79
- return { path: args.path.replace(/^node:/, ''), namespace: 'pyric-node-shim' };
115
+ const isOwnedImporter = isOurCode(args.importer);
116
+ if (!isOwnedImporter) {
117
+ return null;
118
+ }
119
+ const shimPath = args.path.replace(/^node:/, '');
120
+ return { path: shimPath, namespace: 'pyric-node-shim' };
121
+ });
122
+ build.onLoad({ filter: /.*/, namespace: 'pyric-node-shim' }, (args) => {
123
+ const content = NODE_BUILTIN_SHIMS[args.path];
124
+ if (content !== undefined) {
125
+ return { contents: content, loader: 'js' };
126
+ }
127
+ return null;
80
128
  });
81
- build.onLoad({ filter: /.*/, namespace: 'pyric-node-shim' }, (args) => ({
82
- contents: NODE_BUILTIN_SHIMS[args.path]!,
83
- loader: 'js',
84
- }));
85
129
  },
86
130
  };
87
131
 
88
132
  return {
89
133
  config() {
134
+ const excludedModules = [
135
+ ...SDK_MODULES,
136
+ '@firebase/app',
137
+ '@firebase/component',
138
+ '@firebase/ai',
139
+ '@firebase/util',
140
+ '@firebase/logger',
141
+ ];
90
142
  return {
91
143
  optimizeDeps: {
92
- exclude: [...SDK_MODULES],
144
+ exclude: excludedModules,
93
145
  include: ['js-md5', 'js-sha256'],
94
146
  esbuildOptions: { plugins: [optimizerMirror] },
95
147
  },
@@ -97,23 +149,71 @@ export function createViteModuleSwap(context: ViteModuleContext): ViteModuleSwap
97
149
  },
98
150
  configResolved(config) {
99
151
  const allow = config.server?.fs?.allow;
100
- if (!allow) return;
152
+ const hasAllowList = allow !== undefined && Array.isArray(allow);
153
+ if (!hasAllowList) {
154
+ return;
155
+ }
101
156
  for (const dir of [pyricRoot, cliRoot]) {
102
- if (!allow.includes(dir)) allow.push(dir);
157
+ const isAlreadyAllowed = allow.includes(dir);
158
+ if (!isAlreadyAllowed) {
159
+ allow.push(dir);
160
+ }
103
161
  }
104
162
  },
105
163
  resolveId(source, importer) {
106
- const firebase = FIREBASE_SPECIFIER.exec(source);
107
- if (firebase) {
108
- const subpath = firebase[1]!;
109
- return SERVED_FIREBASE_SUBPATHS.has(subpath) ? entries[entryKey(subpath)]! : null;
164
+ const isShadowBridgeImporter = importer !== undefined &&
165
+ (importer.includes('app-ai-passthrough') || importer.includes('app-bridge'));
166
+ const isFirebaseAppSpecifier = source === 'firebase/app';
167
+ const isBypassedBridgeImport = isShadowBridgeImporter && isFirebaseAppSpecifier;
168
+ if (isBypassedBridgeImport) {
169
+ return null;
110
170
  }
111
- const node = NODE_BUILTIN_RE.exec(source);
112
- return node && isOurCode(importer) ? NODE_SHIM_PREFIX + node[2]! : null;
171
+
172
+ const firebaseMatch = FIREBASE_SPECIFIER.exec(source);
173
+ const isFirebaseSpecifier = firebaseMatch !== null;
174
+ if (isFirebaseSpecifier) {
175
+ const subpath = firebaseMatch[1] !== undefined ? firebaseMatch[1] : '';
176
+ const isProductionAiMode = aiMode() === 'production';
177
+ if (isProductionAiMode) {
178
+ const isAiSubpath = subpath === 'ai';
179
+ if (isAiSubpath) {
180
+ return null;
181
+ }
182
+ const isAppSubpath = subpath === 'app';
183
+ const passthroughEntry = entries['app-ai-passthrough'];
184
+ const hasPassthroughEntry = passthroughEntry !== undefined;
185
+ const shouldUsePassthroughBridge = isAppSubpath && hasPassthroughEntry;
186
+ if (shouldUsePassthroughBridge) {
187
+ return passthroughEntry;
188
+ }
189
+ }
190
+ const isServedSubpath = SERVED_FIREBASE_SUBPATHS.has(subpath);
191
+ if (isServedSubpath) {
192
+ const key = entryKey(subpath);
193
+ const entryPath = entries[key];
194
+ if (entryPath !== undefined) {
195
+ return entryPath;
196
+ }
197
+ }
198
+ return null;
199
+ }
200
+
201
+ const nodeMatch = NODE_BUILTIN_RE.exec(source);
202
+ const isNodeBuiltin = nodeMatch !== null && nodeMatch[2] !== undefined;
203
+ const isOwnedImporter = isOurCode(importer);
204
+ const shouldShimNodeBuiltin = isNodeBuiltin && isOwnedImporter;
205
+ if (shouldShimNodeBuiltin) {
206
+ return NODE_SHIM_PREFIX + nodeMatch[2];
207
+ }
208
+ return null;
113
209
  },
114
210
  load(id) {
115
- if (!id.startsWith(NODE_SHIM_PREFIX)) return null;
116
- return shimFor(id.slice(NODE_SHIM_PREFIX.length));
211
+ const isNodeShim = id.startsWith(NODE_SHIM_PREFIX);
212
+ if (!isNodeShim) {
213
+ return null;
214
+ }
215
+ const specifier = id.slice(NODE_SHIM_PREFIX.length);
216
+ return shimFor(specifier);
117
217
  },
118
218
  };
119
219
  }
@@ -39,6 +39,8 @@
39
39
  * to the in-page sandbox (single-tab, ephemeral).
40
40
  */
41
41
  import type { Plugin, UserConfig } from 'vite';
42
+ import { existsSync } from 'node:fs';
43
+ import { dirname, join, resolve } from 'node:path';
42
44
  import { createViteWorkerRuntime } from './vite-worker-runtime.js';
43
45
  import type { PyricAiOptions } from './vite-ai-config.js';
44
46
  import type { PyricRuntimeChipOption } from './runtime/chip-config.js';
@@ -157,6 +159,29 @@ function resolveFunctionsOptions(
157
159
  return {};
158
160
  }
159
161
 
162
+ /**
163
+ * Resolves the Firebase project root directory from Vite's server root. In
164
+ * split-directory or full-stack monorepo layouts where Vite operates inside a
165
+ * subdirectory (e.g. `/web` or `/frontend`) while hosting and security rules
166
+ * configuration (`firebase.json`) resides in an ancestor workspace directory,
167
+ * this ascends to locate the authoritative configuration root.
168
+ */
169
+ function resolveFirebaseProjectDir(defaultRoot: string, explicitRoot?: string): string {
170
+ const hasExplicitRoot = explicitRoot !== undefined && explicitRoot.length > 0;
171
+ if (hasExplicitRoot) return explicitRoot as string;
172
+ let current = resolve(defaultRoot);
173
+ while (true) {
174
+ const candidateConfig = join(current, 'firebase.json');
175
+ const configExists = existsSync(candidateConfig);
176
+ if (configExists) return current;
177
+ const parent = dirname(current);
178
+ const isRootOfFilesystem = parent === current;
179
+ if (isRootOfFilesystem) break;
180
+ current = parent;
181
+ }
182
+ return defaultRoot;
183
+ }
184
+
160
185
  /**
161
186
  * The dev-only Vite plugin. Add to `vite.config`:
162
187
  *
@@ -165,7 +190,6 @@ function resolveFunctionsOptions(
165
190
  */
166
191
  export function pyric(options: PyricOptions = {}): Plugin {
167
192
  const moduleContext = createViteModuleContext();
168
- const moduleSwap = createViteModuleSwap(moduleContext);
169
193
  const { entries, cliRoot } = moduleContext;
170
194
  const workerRuntime = createViteWorkerRuntime();
171
195
  const studioEnabled = options.ui !== false;
@@ -176,6 +200,9 @@ export function pyric(options: PyricOptions = {}): Plugin {
176
200
  workerRuntime,
177
201
  };
178
202
  const pageRuntime = createVitePageRuntime(pageRuntimeInput);
203
+ const moduleSwap = createViteModuleSwap(moduleContext, {
204
+ getAiMode: () => pageRuntime.ai().mode,
205
+ });
179
206
 
180
207
  // Normalize the public bridge shorthand once. The active generation owns the
181
208
  // bridge/session attachment and routes the peer through the SharedWorker.
@@ -197,10 +224,21 @@ export function pyric(options: PyricOptions = {}): Plugin {
197
224
  enforce: 'pre',
198
225
 
199
226
  config(config, env) {
200
- return {
201
- ...moduleSwap.config(),
202
- ...pageRuntime.config(config, env),
203
- } as UserConfig;
227
+ const moduleConfig = moduleSwap.config();
228
+ const pageConfig = pageRuntime.config(config, env);
229
+ const serverWatchConfig: UserConfig = {
230
+ server: {
231
+ watch: {
232
+ ignored: ['**/.pyric/**'],
233
+ },
234
+ },
235
+ };
236
+ const finalizedConfig: UserConfig = {
237
+ ...moduleConfig,
238
+ ...pageConfig,
239
+ ...serverWatchConfig,
240
+ };
241
+ return finalizedConfig;
204
242
  },
205
243
 
206
244
  configResolved(resolved) {
@@ -220,7 +258,7 @@ export function pyric(options: PyricOptions = {}): Plugin {
220
258
  activeGeneration = null;
221
259
  await priorGeneration?.close();
222
260
 
223
- const projectDir = options.root ?? server.config.root;
261
+ const projectDir = resolveFirebaseProjectDir(server.config.root, options.root);
224
262
  const uiEnabled = options.ui ?? true;
225
263
  const functionsOptions = resolveFunctionsOptions(options.functions);
226
264
  const ai = pageRuntime.ai();
@@ -134,7 +134,7 @@ export async function createViteSandboxGeneration(
134
134
  const rulesConfig = dependencies.resolveRulesConfig(cwd, options.rules, firebaseConfig);
135
135
 
136
136
  try {
137
- const epochSalt = viteWorkerEpochSalt(cwd, ai.engineWire);
137
+ const epochSalt = viteWorkerEpochSalt(cwd, ai.engineWire, ai.mode);
138
138
  await dependencies.prepareWorker(workerRuntime, epochSalt);
139
139
  } catch (error) {
140
140
  server.config.logger.warn(