@pyric/cli 0.1.0-alpha.19 → 0.1.0-alpha.20
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.
- package/README.md +9 -9
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +48 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-proxy.js +3 -3
- package/dist/cli/mcp-proxy.js.map +1 -1
- package/dist/cli/parse-args.d.ts +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +51 -15
- package/dist/cli/parse-args.js.map +1 -1
- package/dist/cli/pyric-config.d.ts +24 -0
- package/dist/cli/pyric-config.d.ts.map +1 -0
- package/dist/cli/pyric-config.js +28 -0
- package/dist/cli/pyric-config.js.map +1 -0
- package/dist/cli/{dev-runner.d.ts → sandbox-runner.d.ts} +33 -36
- package/dist/cli/sandbox-runner.d.ts.map +1 -0
- package/dist/cli/{dev-runner.js → sandbox-runner.js} +90 -55
- package/dist/cli/sandbox-runner.js.map +1 -0
- package/dist/cli/serve.d.ts +6 -4
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +99 -40
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/snapshot.js +5 -5
- package/dist/cli/snapshot.js.map +1 -1
- package/dist/cli/verify.js +1 -1
- package/dist/cli/verify.js.map +1 -1
- package/dist/functions-rtdb/development-runtime.js +1 -1
- package/dist/functions-rtdb/development-runtime.js.map +1 -1
- package/dist/functions-rtdb/project.js +8 -8
- package/dist/functions-rtdb/project.js.map +1 -1
- package/dist/next/guard.js +1 -1
- package/dist/next/guard.js.map +1 -1
- package/dist/remote/index.d.ts +1 -1
- package/dist/remote/index.js +9 -9
- package/dist/remote/index.js.map +1 -1
- package/dist/serve/bundler.js +10 -10
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/entries/ai.d.ts.map +1 -1
- package/dist/serve/entries/ai.js +27 -1
- package/dist/serve/entries/ai.js.map +1 -1
- package/dist/serve/entries/auth-helper-dom.js +1 -1
- package/dist/serve/entries/auth-helper-dom.js.map +1 -1
- package/dist/serve/entries/auth-helper-runtime.js +1 -1
- package/dist/serve/entries/auth-helper-runtime.js.map +1 -1
- package/dist/serve/entries/firestore.js +3 -3
- package/dist/serve/entries/firestore.js.map +1 -1
- package/dist/serve/entries/keepalive.js +1 -1
- package/dist/serve/entries/keepalive.js.map +1 -1
- package/dist/serve/entries/runtime.js +21 -14
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/entries/storage.js +1 -1
- package/dist/serve/entries/storage.js.map +1 -1
- package/dist/serve/entries/worker-runtime.js +1 -1
- package/dist/serve/entries/worker-runtime.js.map +1 -1
- package/dist/serve/init-payload.d.ts +4 -0
- package/dist/serve/init-payload.d.ts.map +1 -1
- package/dist/serve/namespace.d.ts +6 -0
- package/dist/serve/namespace.d.ts.map +1 -1
- package/dist/serve/namespace.js +36 -5
- package/dist/serve/namespace.js.map +1 -1
- package/dist/serve/rules.d.ts.map +1 -1
- package/dist/serve/rules.js +44 -21
- package/dist/serve/rules.js.map +1 -1
- package/dist/serve/runtime/chip.d.ts.map +1 -1
- package/dist/serve/runtime/chip.js +32 -1
- package/dist/serve/runtime/chip.js.map +1 -1
- package/dist/serve/runtime/manifest.d.ts +1 -1
- package/dist/serve/runtime/manifest.d.ts.map +1 -1
- package/dist/serve/runtime/manifest.js +1 -1
- package/dist/serve/runtime/manifest.js.map +1 -1
- package/dist/serve/runtime/status.d.ts.map +1 -1
- package/dist/serve/runtime/status.js +23 -0
- package/dist/serve/runtime/status.js.map +1 -1
- package/dist/serve/sandbox-session.d.ts +1 -0
- package/dist/serve/sandbox-session.d.ts.map +1 -1
- package/dist/serve/sandbox-session.js +10 -4
- package/dist/serve/sandbox-session.js.map +1 -1
- package/dist/serve/server.d.ts +7 -0
- package/dist/serve/server.d.ts.map +1 -1
- package/dist/serve/server.js +15 -1
- package/dist/serve/server.js.map +1 -1
- package/dist/serve/site-ui/404.html +1 -1
- package/dist/serve/site-ui/_astro/{RulesCodeEditor.Bl-XMkhD.js → RulesCodeEditor.XtDmHOlN.js} +1 -1
- package/dist/serve/site-ui/_astro/_slug_.Da5VLhW1.css +1 -0
- package/dist/serve/site-ui/_astro/_studio_.BnfYCKoI.css +1 -0
- package/dist/serve/site-ui/_astro/app.B52xr-DK.js +1 -0
- package/dist/serve/site-ui/_astro/app.DWBraPUw.js +12 -0
- package/dist/serve/site-ui/_astro/app.pMSnN6Qw.css +1 -0
- package/dist/serve/site-ui/_astro/{chess-showcase.Dh5D8kqe.js → chess-showcase.B72XYeoh.js} +1 -1
- package/dist/serve/site-ui/_astro/{example-runtime.CuyAjjiG.js → example-runtime.C25_lx6Z.js} +1 -1
- package/dist/serve/site-ui/_astro/index.Tb-31efc.css +1 -0
- package/dist/serve/site-ui/_astro/index.UkCBr-_0.css +1 -0
- package/dist/serve/site-ui/_astro/{sandbox-controls.BP4M5f1M.js → sandbox-controls.DEpnKg-O.js} +11 -11
- package/dist/serve/site-ui/_astro/{seed.CSUkloMi.js → seed.Co0yUJY5.js} +1 -1
- package/dist/serve/site-ui/_astro/{writes.C57paAj2.js → writes.rpjrFzmu.js} +7 -4
- package/dist/serve/site-ui/auth/index.html +5 -3
- package/dist/serve/site-ui/david-east.jpg +0 -0
- package/dist/serve/site-ui/docs/_rhythm/index.html +6 -3
- package/dist/serve/site-ui/docs/_rhythm.md +1 -1
- package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +18 -15
- package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +16 -16
- package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +6 -5
- package/dist/serve/site-ui/docs/agent/watch-and-review.md +1 -5
- package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +8 -5
- package/dist/serve/site-ui/docs/agent/work-with-an-agent.md +4 -4
- package/dist/serve/site-ui/docs/ai-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/api-reference/index.html +6 -2
- package/dist/serve/site-ui/docs/api-reference.md +1 -0
- package/dist/serve/site-ui/docs/app-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/auth-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/build/ai-logic/index.html +5 -2
- package/dist/serve/site-ui/docs/build/authentication/index.html +7 -4
- package/dist/serve/site-ui/docs/build/authentication.md +2 -2
- package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +5 -2
- package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +5 -2
- package/dist/serve/site-ui/docs/build/cloud-storage/index.html +6 -3
- package/dist/serve/site-ui/docs/build/cloud-storage.md +1 -1
- package/dist/serve/site-ui/docs/build/realtime-database/index.html +9 -6
- package/dist/serve/site-ui/docs/build/realtime-database.md +4 -4
- package/dist/serve/site-ui/docs/conformance-scores/index.html +5 -2
- package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/create-pyric-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/database-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/examples/chess/index.html +5 -2
- package/dist/serve/site-ui/docs/examples/index.html +5 -2
- package/dist/serve/site-ui/docs/firestore-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +9 -6
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works.md +5 -5
- package/dist/serve/site-ui/docs/get-started/nextjs/index.html +9 -6
- package/dist/serve/site-ui/docs/get-started/nextjs.md +4 -4
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +14 -9
- package/dist/serve/site-ui/docs/get-started/start-building.md +16 -10
- package/dist/serve/site-ui/docs/get-started/vite/index.html +6 -3
- package/dist/serve/site-ui/docs/get-started/vite.md +1 -1
- package/dist/serve/site-ui/docs/index.json +180 -150
- package/dist/serve/site-ui/docs/messaging-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +5 -2
- package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +6 -4
- package/dist/serve/site-ui/docs/observe/see-whats-happening.md +2 -4
- package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +9 -6
- package/dist/serve/site-ui/docs/observe/shape-your-data.md +4 -4
- package/dist/serve/site-ui/docs/overview/index.html +16 -10
- package/dist/serve/site-ui/docs/overview.md +19 -11
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +8 -5
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +3 -3
- package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +501 -0
- package/dist/serve/site-ui/docs/pyric-admin-reference-api.md +587 -0
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +166 -95
- package/dist/serve/site-ui/docs/pyric-database-reference-api.md +107 -1
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +10 -4
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api.md +5 -2
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +10 -4
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api.md +5 -2
- package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api.md +2 -2
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/reference/cli/index.html +153 -0
- package/dist/serve/site-ui/docs/reference/cli.md +114 -0
- package/dist/serve/site-ui/docs/rules-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +6 -3
- package/dist/serve/site-ui/docs/secure/read-a-denial.md +1 -1
- package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +5 -2
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +7 -4
- package/dist/serve/site-ui/docs/ship/ship-to-production.md +2 -2
- package/dist/serve/site-ui/docs/ship/test-in-node/index.html +9 -6
- package/dist/serve/site-ui/docs/ship/test-in-node.md +4 -4
- package/dist/serve/site-ui/docs/storage-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +5 -2
- package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +5 -2
- package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +5 -2
- package/dist/serve/site-ui/docs/tutorial/index.html +10 -7
- package/dist/serve/site-ui/docs/tutorial.md +4 -4
- package/dist/serve/site-ui/examples/chess/index.html +4 -2
- package/dist/serve/site-ui/firestore/index.html +5 -3
- package/dist/serve/site-ui/hero-charcoal.jpg +0 -0
- package/dist/serve/site-ui/index.html +9 -7
- package/dist/serve/site-ui/llms.txt +4 -3
- package/dist/serve/site-ui/pyric-campfire-full.png +0 -0
- package/dist/serve/site-ui/pyric-campfire.png +0 -0
- package/dist/serve/site-ui/rtdb/index.html +5 -3
- package/dist/serve/site-ui/settings/index.html +5 -3
- package/dist/serve/site-ui/storage/index.html +5 -3
- package/dist/serve/site-ui/studio/index.html +13 -0
- package/dist/serve/site-ui/studio-routes.json +1 -1
- package/dist/serve/site-ui/traffic/index.html +5 -3
- package/dist/serve/studio/routes.d.ts +9 -0
- package/dist/serve/studio/routes.d.ts.map +1 -1
- package/dist/serve/studio/routes.js +47 -7
- package/dist/serve/studio/routes.js.map +1 -1
- package/dist/serve/vite-ai-config.d.ts.map +1 -1
- package/dist/serve/vite-ai-config.js +38 -8
- package/dist/serve/vite-ai-config.js.map +1 -1
- package/dist/serve/vite-module-swap.d.ts.map +1 -1
- package/dist/serve/vite-module-swap.js +0 -28
- package/dist/serve/vite-module-swap.js.map +1 -1
- package/dist/serve/vite-sandbox-generation.d.ts +1 -1
- package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
- package/dist/serve/vite-sandbox-generation.js +1 -1
- package/dist/serve/vite-sandbox-generation.js.map +1 -1
- package/dist/serve/worker/client/disconnect.js +1 -1
- package/dist/serve/worker/client/disconnect.js.map +1 -1
- package/dist/serve/worker/client/presence.d.ts.map +1 -1
- package/dist/serve/worker/client/presence.js +18 -5
- package/dist/serve/worker/client/presence.js.map +1 -1
- package/dist/serve/worker/host-ai.d.ts.map +1 -1
- package/dist/serve/worker/host-ai.js +15 -0
- package/dist/serve/worker/host-ai.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +4 -0
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +7 -1
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/package.json +5 -5
- package/src/cli/cli.test.ts +2 -2
- package/src/cli/index.ts +48 -42
- package/src/cli/mcp-proxy.ts +4 -4
- package/src/cli/parse-args.ts +61 -15
- package/src/cli/pyric-config.ts +45 -0
- package/src/cli/{dev-runner.ts → sandbox-runner.ts} +117 -72
- package/src/cli/serve.ts +115 -47
- package/src/cli/snapshot.ts +5 -5
- package/src/cli/verify.ts +1 -1
- package/src/functions-rtdb/development-runtime.ts +1 -1
- package/src/functions-rtdb/project.ts +8 -8
- package/src/next/guard.ts +1 -1
- package/src/remote/index.ts +9 -9
- package/src/serve/bundler.ts +10 -10
- package/src/serve/entries/ai.ts +27 -1
- package/src/serve/entries/auth-helper-dom.ts +1 -1
- package/src/serve/entries/auth-helper-runtime.ts +1 -1
- package/src/serve/entries/firestore.ts +3 -3
- package/src/serve/entries/keepalive.ts +1 -1
- package/src/serve/entries/runtime.ts +19 -14
- package/src/serve/entries/storage.ts +1 -1
- package/src/serve/entries/worker-runtime.ts +1 -1
- package/src/serve/init-payload.ts +4 -0
- package/src/serve/namespace.ts +44 -5
- package/src/serve/rules.ts +47 -22
- package/src/serve/runtime/chip.ts +38 -1
- package/src/serve/runtime/manifest.ts +1 -1
- package/src/serve/runtime/status.ts +24 -0
- package/src/serve/sandbox-session.ts +10 -4
- package/src/serve/server.ts +18 -1
- package/src/serve/studio/routes.ts +63 -7
- package/src/serve/vite-ai-config.ts +37 -7
- package/src/serve/vite-module-swap.ts +0 -28
- package/src/serve/vite-sandbox-generation.ts +1 -1
- package/src/serve/worker/client/disconnect.ts +1 -1
- package/src/serve/worker/client/presence.ts +25 -5
- package/src/serve/worker/host-ai.ts +15 -0
- package/src/serve/worker/protocol.ts +2 -1
- package/src/serve/worker/serve-init.ts +5 -1
- package/README.md.orig +0 -145
- package/dist/cli/dev-runner.d.ts.map +0 -1
- package/dist/cli/dev-runner.js.map +0 -1
- package/dist/serve/site-ui/_astro/_slug_.CXh9yTP1.css +0 -1
- package/dist/serve/site-ui/_astro/_slug_.CupVK4TM.css +0 -1
- package/dist/serve/site-ui/_astro/_studio_.CfxiQWkk.css +0 -1
- package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +0 -1
- package/dist/serve/site-ui/_astro/app.Ce3MTLQm.js +0 -1
- package/dist/serve/site-ui/_astro/app.taqzyjD0.js +0 -11
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +0 -582
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +0 -448
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Stable routes and identity used by the served runtime and its UI. */
|
|
2
2
|
export const PYRIC_WORKER_URL = '/__pyric/sdk/worker.js';
|
|
3
3
|
export const PYRIC_WORKER_NAME = 'pyric-shared-worker';
|
|
4
|
-
export const PYRIC_STUDIO_URL = '/__pyric/ui/';
|
|
4
|
+
export const PYRIC_STUDIO_URL = '/__pyric/ui/studio';
|
|
5
5
|
|
|
6
6
|
export interface PyricRuntimeManifest {
|
|
7
7
|
studioUrl: string;
|
|
@@ -108,6 +108,13 @@ function isListenerPhaseErroredEvent(event: SandboxEvent): boolean {
|
|
|
108
108
|
return isListenerKind && isErroredPhase && hasErrorPayload;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
function isAiRejectedEvent(event: SandboxEvent): boolean {
|
|
112
|
+
const isServiceMutationKind = event.kind === 'service_mutation';
|
|
113
|
+
const isAiService = event.service === 'ai';
|
|
114
|
+
const isRejectedOp = 'op' in event && event.op === 'request_rejected';
|
|
115
|
+
return isServiceMutationKind && isAiService && isRejectedOp;
|
|
116
|
+
}
|
|
117
|
+
|
|
111
118
|
function sandboxError(event: SandboxEvent): PyricRuntimeError | null {
|
|
112
119
|
if (isRuntimeErrorEvent(event)) {
|
|
113
120
|
const hasPathProperty = 'path' in event && typeof event.path === 'string';
|
|
@@ -127,6 +134,23 @@ function sandboxError(event: SandboxEvent): PyricRuntimeError | null {
|
|
|
127
134
|
message: errorPayload?.message ? errorPayload.message : 'Sandbox runtime error',
|
|
128
135
|
};
|
|
129
136
|
}
|
|
137
|
+
if (isAiRejectedEvent(event)) {
|
|
138
|
+
const detail = 'detail' in event ? (event.detail as Record<string, unknown> | undefined) : undefined;
|
|
139
|
+
const code = typeof detail?.code === 'string' ? detail.code : 'AI_ERROR';
|
|
140
|
+
const message = typeof detail?.message === 'string' ? detail.message : 'AI request rejected';
|
|
141
|
+
const hasPathProperty = 'path' in event && typeof event.path === 'string';
|
|
142
|
+
const targetPath = hasPathProperty ? event.path : '(ai)';
|
|
143
|
+
return {
|
|
144
|
+
id: event.id,
|
|
145
|
+
source: 'sandbox',
|
|
146
|
+
at: event.at,
|
|
147
|
+
service: 'ai',
|
|
148
|
+
method: 'generateContent',
|
|
149
|
+
path: targetPath,
|
|
150
|
+
code,
|
|
151
|
+
message: `AI_ERROR: ${message}`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
130
154
|
if (isListenerErroredEvent(event)) {
|
|
131
155
|
const errorPayload = (event as { error: { code?: string; message: string } }).error;
|
|
132
156
|
return {
|
|
@@ -35,6 +35,7 @@ export interface SandboxSessionOptions {
|
|
|
35
35
|
bridgeUrl?: () => string | null;
|
|
36
36
|
ai?: InitPayload['ai'];
|
|
37
37
|
aiProxyUpstream?: string;
|
|
38
|
+
permissive?: boolean;
|
|
38
39
|
logger?: ServeLogger;
|
|
39
40
|
activity?: (incident: ActivityIncident) => void;
|
|
40
41
|
}
|
|
@@ -97,6 +98,13 @@ export async function createSandboxSession(
|
|
|
97
98
|
databaseRules: database.rules,
|
|
98
99
|
databaseRulesHash: database.rulesHash,
|
|
99
100
|
};
|
|
101
|
+
if (!database.sourcePath) {
|
|
102
|
+
if (options.permissive) {
|
|
103
|
+
options.logger?.note(' ⓘ RTDB permissive mode active — client reads/writes are open by default.');
|
|
104
|
+
} else {
|
|
105
|
+
options.logger?.note(' ⚠ no database.rules.json found — client RTDB reads/writes default to DENY (matching production Firebase). Use --permissive for open prototyping.');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
100
108
|
const events = createEventHub();
|
|
101
109
|
const capture: CaptureStore | undefined = (options.capture ?? true)
|
|
102
110
|
? createCaptureStore(options.projectDir)
|
|
@@ -164,6 +172,7 @@ export async function createSandboxSession(
|
|
|
164
172
|
: seedUsers,
|
|
165
173
|
messaging: true,
|
|
166
174
|
ai: options.ai ?? null,
|
|
175
|
+
permissive: Boolean(options.permissive),
|
|
167
176
|
});
|
|
168
177
|
|
|
169
178
|
const summary: SandboxSessionSummary = {
|
|
@@ -221,16 +230,13 @@ export async function createSandboxSession(
|
|
|
221
230
|
}
|
|
222
231
|
};
|
|
223
232
|
const reloadDatabaseRules = async (): Promise<RulesReloadResult> => {
|
|
224
|
-
const isMissingDatabaseRules = database.sourcePath === null;
|
|
225
|
-
if (isMissingDatabaseRules) {
|
|
226
|
-
return { kind: 'not-configured' };
|
|
227
|
-
}
|
|
228
233
|
try {
|
|
229
234
|
const updated = await loadProjectDatabaseRules(options.projectDir, options.firebaseConfig);
|
|
230
235
|
const isMissingUpdatedRules = updated.rules === null || updated.rulesHash === null;
|
|
231
236
|
if (isMissingUpdatedRules) {
|
|
232
237
|
return { kind: 'not-configured' };
|
|
233
238
|
}
|
|
239
|
+
database.sourcePath = updated.sourcePath;
|
|
234
240
|
live.databaseRules = updated.rules;
|
|
235
241
|
live.databaseRulesHash = updated.rulesHash;
|
|
236
242
|
events.broadcast('rtdb-rules-update', { rules: updated.rules, rulesHash: updated.rulesHash });
|
package/src/serve/server.ts
CHANGED
|
@@ -134,6 +134,23 @@ export function isAllowedUpgrade(
|
|
|
134
134
|
);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Extract a header value case-insensitively from either Node's IncomingMessage headers
|
|
139
|
+
* or Fetch API Headers object.
|
|
140
|
+
*/
|
|
141
|
+
export function getHeader(
|
|
142
|
+
req: { headers?: Record<string, string | string[] | undefined> | Headers },
|
|
143
|
+
name: string,
|
|
144
|
+
): string | undefined {
|
|
145
|
+
const headers = req?.headers;
|
|
146
|
+
if (!headers) return undefined;
|
|
147
|
+
if (typeof (headers as Headers).get === 'function') {
|
|
148
|
+
return (headers as Headers).get(name) ?? undefined;
|
|
149
|
+
}
|
|
150
|
+
const val = (headers as Record<string, string | string[] | undefined>)[name.toLowerCase()];
|
|
151
|
+
return Array.isArray(val) ? val.join(', ') : val;
|
|
152
|
+
}
|
|
153
|
+
|
|
137
154
|
export interface ServeHandle {
|
|
138
155
|
port: number;
|
|
139
156
|
host: string;
|
|
@@ -249,7 +266,7 @@ async function handleRequest(
|
|
|
249
266
|
if (!isAllowedHost(req.headers.host, opts.host ?? 'localhost', opts.allowedHosts)) {
|
|
250
267
|
logger.note(` ✖ 403 blocked Host '${req.headers.host}' (DNS-rebinding guard)`);
|
|
251
268
|
res.writeHead(403, { 'content-type': 'text/plain' }).end(
|
|
252
|
-
`pyric
|
|
269
|
+
`pyric sandbox: refused request for Host '${req.headers.host ?? ''}'. ` +
|
|
253
270
|
'Only localhost is allowed; use --allowed-host to add one.',
|
|
254
271
|
);
|
|
255
272
|
return;
|
|
@@ -33,12 +33,22 @@ import type {
|
|
|
33
33
|
WorkspaceChange,
|
|
34
34
|
WorkspaceStore,
|
|
35
35
|
} from './store-types.js';
|
|
36
|
+
import { isAllowedHost, isAllowedOrigin, getHeader } from '../server.js';
|
|
37
|
+
import type { WriterLock } from '../writer-lock.js';
|
|
36
38
|
|
|
37
39
|
export interface StudioRouteOptions {
|
|
38
40
|
/** The single-project file tree served at `/__pyric/workspace`. */
|
|
39
41
|
workspace?: WorkspaceStore;
|
|
40
42
|
/** The project list served at `/__pyric/projects`. */
|
|
41
43
|
projects?: ProjectStore;
|
|
44
|
+
/** Per-boot session capability token required on workspace & project endpoints. */
|
|
45
|
+
sessionToken?: string;
|
|
46
|
+
/** Single-writer lock validator for file mutation & deletion endpoints. */
|
|
47
|
+
writerLock?: WriterLock;
|
|
48
|
+
/** Bound host for DNS rebinding guard. */
|
|
49
|
+
boundHost?: string;
|
|
50
|
+
/** Extra hostnames allowed for DNS rebinding/origin guard. */
|
|
51
|
+
allowedHosts?: string[];
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
/** Collect the raw request body as a UTF-8 string. */
|
|
@@ -207,6 +217,10 @@ async function handleProjects(
|
|
|
207
217
|
.end('method not allowed');
|
|
208
218
|
}
|
|
209
219
|
|
|
220
|
+
function isWorkspaceMutation(method?: string): boolean {
|
|
221
|
+
return method === 'PUT' || method === 'POST' || method === 'PATCH' || method === 'DELETE';
|
|
222
|
+
}
|
|
223
|
+
|
|
210
224
|
/**
|
|
211
225
|
* Build a namespace fragment for the Studio storage routes. Returns a handler
|
|
212
226
|
* shaped like the other `/__pyric/*` fragments: it resolves `true` when it
|
|
@@ -219,13 +233,55 @@ export function createStudioRoutes(opts: StudioRouteOptions) {
|
|
|
219
233
|
url: URL,
|
|
220
234
|
): Promise<boolean> => {
|
|
221
235
|
try {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
236
|
+
const isWorkspaceRoute = opts.workspace && url.pathname.startsWith('/__pyric/workspace');
|
|
237
|
+
const isProjectsRoute = opts.projects && url.pathname.startsWith('/__pyric/projects');
|
|
238
|
+
|
|
239
|
+
if (isWorkspaceRoute || isProjectsRoute) {
|
|
240
|
+
const hostHeader = getHeader(req, 'host');
|
|
241
|
+
const originHeader = getHeader(req, 'origin');
|
|
242
|
+
|
|
243
|
+
// 1. Host and Origin guard (Requirement 1)
|
|
244
|
+
if (!isAllowedHost(hostHeader, opts.boundHost ?? 'localhost', opts.allowedHosts)) {
|
|
245
|
+
res.writeHead(403, { 'content-type': 'text/plain' }).end('Forbidden: host not allowed');
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
if (originHeader && !isAllowedOrigin(originHeader, opts.boundHost ?? 'localhost', opts.allowedHosts)) {
|
|
249
|
+
res.writeHead(403, { 'content-type': 'text/plain' }).end('Forbidden: origin mismatch');
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// 2. Per-boot session capability token guard (Requirement 2)
|
|
254
|
+
if (opts.sessionToken) {
|
|
255
|
+
const reqToken =
|
|
256
|
+
getHeader(req, 'x-pyric-session-token') ??
|
|
257
|
+
url.searchParams.get('token');
|
|
258
|
+
if (!reqToken || reqToken !== opts.sessionToken) {
|
|
259
|
+
res.writeHead(401, { 'content-type': 'text/plain' }).end('Unauthorized: invalid session capability token');
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// 3. Single-writer lock guard for mutation endpoints (Requirement 4)
|
|
265
|
+
if (opts.writerLock && isWorkspaceMutation(req.method)) {
|
|
266
|
+
const writerId = getHeader(req, 'x-pyric-writer');
|
|
267
|
+
if (!writerId) {
|
|
268
|
+
res.writeHead(423, { 'content-type': 'text/plain' }).end('Locked: missing active writer lock header');
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
if (!opts.writerLock.claim(writerId, Date.now())) {
|
|
272
|
+
res.writeHead(423, { 'content-type': 'text/plain' }).end('Locked: another tab holds the writer lock');
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (isWorkspaceRoute) {
|
|
278
|
+
await handleWorkspace(opts.workspace!, req, res, url);
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
if (isProjectsRoute) {
|
|
282
|
+
await handleProjects(opts.projects!, req, res, url);
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
229
285
|
}
|
|
230
286
|
} catch (e) {
|
|
231
287
|
if (!res.headersSent) sendError(res, e);
|
|
@@ -44,7 +44,18 @@ export function loadViteAiEnv(
|
|
|
44
44
|
const resolvedEnvDir = envDir === undefined
|
|
45
45
|
? resolvedRoot
|
|
46
46
|
: path.resolve(resolvedRoot, envDir);
|
|
47
|
-
|
|
47
|
+
const loaded = loadEnv(mode, resolvedEnvDir, '');
|
|
48
|
+
for (const [key, val] of Object.entries(loaded)) {
|
|
49
|
+
const isAuthKey =
|
|
50
|
+
key === 'GEMINI_API_KEY' ||
|
|
51
|
+
key === 'GOOGLE_GENAI_API_KEY' ||
|
|
52
|
+
key === 'VITE_GEMINI_API_KEY' ||
|
|
53
|
+
key === 'PYRIC_API_KEY';
|
|
54
|
+
if (isAuthKey && process.env[key] === undefined) {
|
|
55
|
+
process.env[key] = val;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return loaded;
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
/** Convert a public declarative engine into the JSON-safe worker wire shape. */
|
|
@@ -65,6 +76,21 @@ export function engineConfigToWire(engine: PyricAiEngineConfig): AiEngineConfigW
|
|
|
65
76
|
}
|
|
66
77
|
return result as AiEngineConfigWire;
|
|
67
78
|
}
|
|
79
|
+
const isGeminiEngine = engine.kind === 'gemini';
|
|
80
|
+
if (isGeminiEngine) {
|
|
81
|
+
const result: Record<string, unknown> = {
|
|
82
|
+
kind: 'gemini',
|
|
83
|
+
};
|
|
84
|
+
const hasBaseUrl = engine.baseUrl !== undefined;
|
|
85
|
+
if (hasBaseUrl) {
|
|
86
|
+
result.baseUrl = engine.baseUrl;
|
|
87
|
+
}
|
|
88
|
+
const hasApiKey = engine.apiKey !== undefined;
|
|
89
|
+
if (hasApiKey) {
|
|
90
|
+
result.apiKey = engine.apiKey;
|
|
91
|
+
}
|
|
92
|
+
return result as AiEngineConfigWire;
|
|
93
|
+
}
|
|
68
94
|
const result: Record<string, unknown> = {
|
|
69
95
|
kind: 'scripted',
|
|
70
96
|
};
|
|
@@ -123,12 +149,16 @@ export function resolveViteAiConfig(
|
|
|
123
149
|
}
|
|
124
150
|
|
|
125
151
|
let engineWire: AiEngineConfigWire | undefined = undefined;
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
152
|
+
if (isProductionMode) {
|
|
153
|
+
const apiKey = env.GEMINI_API_KEY ?? env.GOOGLE_GENAI_API_KEY ?? env.VITE_GEMINI_API_KEY;
|
|
154
|
+
engineWire = {
|
|
155
|
+
kind: 'gemini',
|
|
156
|
+
...(apiKey !== undefined && apiKey.trim() !== '' ? { apiKey: apiKey.trim() } : {}),
|
|
157
|
+
};
|
|
158
|
+
} else if (explicitEngine !== undefined) {
|
|
159
|
+
engineWire = engineConfigToWire(explicitEngine);
|
|
160
|
+
} else if (model !== undefined) {
|
|
161
|
+
engineWire = engineConfigToWire({ kind: 'openai', baseUrl: AI_PROXY_PATH, model });
|
|
132
162
|
}
|
|
133
163
|
|
|
134
164
|
let proxyUpstream: string | undefined = undefined;
|
|
@@ -86,20 +86,6 @@ export function createViteModuleSwap(
|
|
|
86
86
|
|
|
87
87
|
const match = FIREBASE_SPECIFIER.exec(args.path);
|
|
88
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
89
|
|
|
104
90
|
const isServedSubpath = SERVED_FIREBASE_SUBPATHS.has(subpath);
|
|
105
91
|
if (isServedSubpath) {
|
|
@@ -173,20 +159,6 @@ export function createViteModuleSwap(
|
|
|
173
159
|
const isFirebaseSpecifier = firebaseMatch !== null;
|
|
174
160
|
if (isFirebaseSpecifier) {
|
|
175
161
|
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
162
|
const isServedSubpath = SERVED_FIREBASE_SUBPATHS.has(subpath);
|
|
191
163
|
if (isServedSubpath) {
|
|
192
164
|
const key = entryKey(subpath);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import type { ViteDevServer } from 'vite';
|
|
3
3
|
import { readFirebaseJson, readFirebaseRc, type FirebaseJson } from '../cli/firebase-json.js';
|
|
4
|
-
import { registerModuleUrl } from '../cli/
|
|
4
|
+
import { registerModuleUrl } from '../cli/sandbox-runner.js';
|
|
5
5
|
import {
|
|
6
6
|
discoverFunctionsRtdbProject,
|
|
7
7
|
type FunctionsRtdbProject,
|
|
@@ -15,7 +15,7 @@ function deleteTimeoutError(): Error & { code: string } {
|
|
|
15
15
|
return Object.assign(
|
|
16
16
|
new Error(
|
|
17
17
|
'Timed out waiting for SharedWorker app cleanup acknowledgment. ' +
|
|
18
|
-
'Close all tabs using this pyric
|
|
18
|
+
'Close all tabs using this pyric sandbox origin so the worker can restart.',
|
|
19
19
|
),
|
|
20
20
|
{ code: 'app/delete-timeout' },
|
|
21
21
|
);
|
|
@@ -25,9 +25,29 @@ import type { ClientDb, Unsubscribe } from './handles.js';
|
|
|
25
25
|
export type { PresenceClientKind, PresenceSnapshot, PresenceVisibility };
|
|
26
26
|
export { PRESENCE_HEARTBEAT_INTERVAL_MS, PRESENCE_STALE_MS };
|
|
27
27
|
|
|
28
|
+
function supportsRandomUUID(): boolean {
|
|
29
|
+
return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function supportsDocumentEventListeners(): boolean {
|
|
33
|
+
return (
|
|
34
|
+
typeof document !== 'undefined' &&
|
|
35
|
+
typeof document.addEventListener === 'function' &&
|
|
36
|
+
typeof document.removeEventListener === 'function'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function supportsWindowEventListeners(): boolean {
|
|
41
|
+
return (
|
|
42
|
+
typeof window !== 'undefined' &&
|
|
43
|
+
typeof window.addEventListener === 'function' &&
|
|
44
|
+
typeof window.removeEventListener === 'function'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
28
48
|
/** Mint a random client id (page-lifetime). */
|
|
29
49
|
export function mintPresenceClientId(): string {
|
|
30
|
-
if (
|
|
50
|
+
if (supportsRandomUUID()) {
|
|
31
51
|
return crypto.randomUUID();
|
|
32
52
|
}
|
|
33
53
|
return `page-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
@@ -114,10 +134,10 @@ export function startPresence(opts: StartPresenceOptions): PresenceSession {
|
|
|
114
134
|
|
|
115
135
|
register();
|
|
116
136
|
|
|
117
|
-
if (
|
|
137
|
+
if (supportsDocumentEventListeners()) {
|
|
118
138
|
document.addEventListener('visibilitychange', update);
|
|
119
139
|
}
|
|
120
|
-
if (
|
|
140
|
+
if (supportsWindowEventListeners()) {
|
|
121
141
|
window.addEventListener('popstate', update);
|
|
122
142
|
window.addEventListener('hashchange', update);
|
|
123
143
|
// Best-effort clean disconnect; lease expiry covers unclean shutdown.
|
|
@@ -139,10 +159,10 @@ export function startPresence(opts: StartPresenceOptions): PresenceSession {
|
|
|
139
159
|
clearInterval(timer);
|
|
140
160
|
timer = null;
|
|
141
161
|
}
|
|
142
|
-
if (
|
|
162
|
+
if (supportsDocumentEventListeners()) {
|
|
143
163
|
document.removeEventListener('visibilitychange', update);
|
|
144
164
|
}
|
|
145
|
-
if (
|
|
165
|
+
if (supportsWindowEventListeners()) {
|
|
146
166
|
window.removeEventListener('popstate', update);
|
|
147
167
|
window.removeEventListener('hashchange', update);
|
|
148
168
|
window.removeEventListener('pagehide', onPageHide);
|
|
@@ -57,6 +57,21 @@ function resolveEngineConfig(wire: AiEngineConfigWire): NonNullable<AIOptions['e
|
|
|
57
57
|
...(wire.modelMap !== undefined ? { modelMap: wire.modelMap } : {}),
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
+
const isGeminiWire = wire.kind === 'gemini';
|
|
61
|
+
if (isGeminiWire) {
|
|
62
|
+
const result: Record<string, unknown> = {
|
|
63
|
+
kind: 'gemini',
|
|
64
|
+
};
|
|
65
|
+
const hasBaseUrl = wire.baseUrl !== undefined;
|
|
66
|
+
if (hasBaseUrl) {
|
|
67
|
+
result.baseUrl = wire.baseUrl;
|
|
68
|
+
}
|
|
69
|
+
const hasApiKey = wire.apiKey !== undefined;
|
|
70
|
+
if (hasApiKey) {
|
|
71
|
+
result.apiKey = wire.apiKey;
|
|
72
|
+
}
|
|
73
|
+
return result as unknown as NonNullable<AIOptions['engine']>;
|
|
74
|
+
}
|
|
60
75
|
return {
|
|
61
76
|
kind: 'scripted',
|
|
62
77
|
...(wire.script !== undefined
|
|
@@ -203,7 +203,8 @@ export type AiEngineConfigWire =
|
|
|
203
203
|
model?: string;
|
|
204
204
|
/** Explicit Gemini-model-id → upstream-model mapping. */
|
|
205
205
|
modelMap?: Record<string, string>;
|
|
206
|
-
}
|
|
206
|
+
}
|
|
207
|
+
| { kind: 'gemini'; baseUrl?: string; apiKey?: string };
|
|
207
208
|
|
|
208
209
|
/**
|
|
209
210
|
* Wire form of the Gemini error envelope an `AiBrokerError` carries
|
|
@@ -221,8 +221,8 @@ export function applyServeInit(
|
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
|
+
const rtdb = ctx.rtdb ??= getDatabase(ctx.sandbox);
|
|
224
225
|
if (payload.databaseRules) {
|
|
225
|
-
const rtdb = ctx.rtdb ??= getDatabase(ctx.sandbox);
|
|
226
226
|
rtdbSandbox.setRules(rtdb, payload.databaseRules);
|
|
227
227
|
ctx.activeRules ??= {};
|
|
228
228
|
ctx.activeRules.database = {
|
|
@@ -231,6 +231,10 @@ export function applyServeInit(
|
|
|
231
231
|
status: 'active',
|
|
232
232
|
messages: [],
|
|
233
233
|
};
|
|
234
|
+
} else if (payload.permissive) {
|
|
235
|
+
rtdbSandbox.setDefaultPolicy(rtdb, 'allow');
|
|
236
|
+
} else {
|
|
237
|
+
rtdbSandbox.setDefaultPolicy(rtdb, 'deny');
|
|
234
238
|
}
|
|
235
239
|
|
|
236
240
|
// 1b. Storage rules — deployed ONCE, here, before any storage op can run.
|
package/README.md.orig
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
# `@pyric/cli`
|
|
2
|
-
|
|
3
|
-
The Pyric CLI and programmatic helpers for local sandbox development,
|
|
4
|
-
verification, artifact generation, and agent bridges.
|
|
5
|
-
|
|
6
|
-
> **Alpha.** This package is an early alpha. Non-mirrored exports (e.g.
|
|
7
|
-
> `@pyric/cli/serve/worker`, `@pyric/cli/verify`, `@pyric/cli/credentials/node`)
|
|
8
|
-
> are experimental public-alpha surfaces that may change without notice. The
|
|
9
|
-
> MCP tool surface (tool names and shapes) will consolidate during early
|
|
10
|
-
> alpha — do not treat tool names as stable.
|
|
11
|
-
|
|
12
|
-
Production project administration (deploy, Identity Toolkit configuration,
|
|
13
|
-
hosted discovery) is **not** part of this package. Use
|
|
14
|
-
[`firebase-tools`](https://firebase.google.com/docs/cli) or the Firebase
|
|
15
|
-
Console to ship rules, indexes, hosting, and functions to a real project.
|
|
16
|
-
|
|
17
|
-
## CLI subcommands
|
|
18
|
-
|
|
19
|
-
| Command | What it does |
|
|
20
|
-
|---|---|
|
|
21
|
-
| `pyric init [dir]` | Scaffold a pyric project — never prompts, idempotent, safe to rerun. `--template web` (default) creates a Vite app with canonical `firebase/*` imports; `--template static` creates a no-bundler app; `--template node` creates a script-style project. Run any template through `pyric dev` for sandbox resolution; inactive production tooling loads Firebase directly. Also `--name`, `--force` (overwrite scaffold-owned files), and `--json` (machine result on stdout). |
|
|
22
|
-
| `pyric bridge` | Stand up an HTTP+WebSocket bridge an MCP client (Claude Code, Cursor) connects to (sandbox mode only) |
|
|
23
|
-
| `pyric dev` | Local dev server with the pyric sandbox standing in for Firebase: serves `hosting.public`, resolves unmodified `firebase/*` imports to a pyric sandbox via a served import map, deploys + hot-reloads `firestore.rules` (SSE), opens an emulator-style sign-in helper for `signInWithPopup`/`signInWithRedirect`. The sandbox runs in a **SharedWorker by default** — one backend shared by every tab of the origin (live cross-tab sync), kept in the browser's IndexedDB so **your sandbox data — Firestore docs, auth users, RTDB, storage objects, and the traffic history — survives a refresh/restart by default** (see the persistence guide's coverage matrix for the exact tiers); a per-tab in-page sandbox is the fallback when SharedWorker is unavailable. Flags + exit codes: [CLI reference](docs/reference/cli.md#pyric-dev); persistence, ephemeral runs, clearing data, and SharedWorker tips: [persistence & multi-tab](docs/how-to/serve-persistence-and-multi-tab.md) |
|
|
24
|
-
| `pyric snapshot` | Promote lived sandbox state (live `dev --persist`, else `.pyric/state/state.json`) to a committable fixture; `pyric dev --seed <fixture>` re-serves it (docs + users). `--out`, `--port`, `--force`, `--json` |
|
|
25
|
-
| `pyric verify` | Replay a captured sandbox session against candidate rules (`--engine sandbox\|rules-test-api\|both`). Hosted Rules Test API needs SA/ADC via `FIREBASE_SA_BASE64` / `GOOGLE_APPLICATION_CREDENTIALS` |
|
|
26
|
-
| `pyric can-i-use <feature>` | Query the canonical conformance model for availability, behaviour fidelity, assurance eligibility, caveats, and evidence. Only an exact canonical feature name exits 0; ambiguous names, spelling suggestions, and missing features exit 1. Accepts `--json`. |
|
|
27
|
-
| `pyric mcp` | Start the stdio MCP server; attach to `pyric dev --bridge` when available or host a headless sandbox |
|
|
28
|
-
| `pyric firestore rules lint <path>` | Lint a Firestore rules file |
|
|
29
|
-
| `pyric firestore rules validate <path>` | Validate Firestore rules structure |
|
|
30
|
-
| `pyric firestore rules simulate` | Run the local Firestore rules simulator |
|
|
31
|
-
| `pyric firestore rules resolve <path>` | Resolve `2+modules` imports into a Firebase rules artifact |
|
|
32
|
-
| `pyric firestore indexes generate <path...>` | Derive composite-index definitions from application source |
|
|
33
|
-
| `pyric storage rules lint <path>` / `simulate` | Run local Storage rules lint or simulation |
|
|
34
|
-
| `pyric storage rules resolve <path> --out storage.rules` | Resolve `storage.modules.rules` into a deployable Storage rules artifact |
|
|
35
|
-
| `pyric database rules lint <path>` | Lint a Realtime Database rules JSON file |
|
|
36
|
-
| `pyric database rules validate <path>` | Validate Realtime Database rules expressions |
|
|
37
|
-
| `pyric database rules simulate` | Run the local Realtime Database rules simulator |
|
|
38
|
-
| `pyric database rules generate` | Compile a constraints module to local `database.rules.json` without contacting production |
|
|
39
|
-
|
|
40
|
-
Every command's full flags, defaults, exit codes, and environment variables are
|
|
41
|
-
in the **[CLI reference](docs/reference/cli.md)**. Task guides and the rest of
|
|
42
|
-
the docs are indexed in **[docs/](docs/README.md)**.
|
|
43
|
-
|
|
44
|
-
### Persistence caveats (documented limits)
|
|
45
|
-
|
|
46
|
-
- **Anonymous users don't persist** (no round-trip key) — but their *documents
|
|
47
|
-
do*. An app that calls `signInAnonymously` on load mints a new uid every
|
|
48
|
-
reload under `--persist`, so docs owned by prior anonymous uids accumulate
|
|
49
|
-
unreachably. Use the sign-in helper (or seeded users) for owner-based data
|
|
50
|
-
you want durable.
|
|
51
|
-
- **The state file is not a point-in-time snapshot** — firestore and auth
|
|
52
|
-
sections flush on independent debounces; a crash between them can persist
|
|
53
|
-
docs whose owner user hasn't flushed yet (or vice versa).
|
|
54
|
-
- **One writer tab at a time (in-page fallback only)** — when several per-tab
|
|
55
|
-
in-page sandboxes share one `.pyric/state` file, the first tab to flush holds
|
|
56
|
-
the writer lock; others run read-only (console warning + `persistReadOnly`
|
|
57
|
-
diagnostic) so they can't erase the writer's data. On the default SharedWorker
|
|
58
|
-
path this can't happen — the single worker is the sole writer.
|
|
59
|
-
- **Loss window** — the final unsaved change can be lost if the tab CLOSES
|
|
60
|
-
within the flush debounce while the state exceeds ~60KB (keepalive cap);
|
|
61
|
-
smaller states flush on unload, and reloads are always safe. A reset (or
|
|
62
|
-
any delete-all) that empties a non-empty state first preserves the prior
|
|
63
|
-
file at `.pyric/state/state.json.bak`.
|
|
64
|
-
|
|
65
|
-
### Agent onboarding (init → dev → MCP)
|
|
66
|
-
|
|
67
|
-
Three parseable steps, no flags to discover:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
pyric init myapp --json # → {..., "nextSteps": [...]}
|
|
71
|
-
cd myapp && bun install
|
|
72
|
-
bun run dev:agent # pyric dev --bridge --seed seed.json
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Readiness probe: `GET <url>/__pyric/init.json` → 200 once serving (body
|
|
76
|
-
carries the live rules hash). MCP endpoint: `<url>/__pyric/mcp`. With
|
|
77
|
-
`pyric dev --json`, stdout's single line carries `{url, port, mcpUrl,
|
|
78
|
-
rulesHash}`.
|
|
79
|
-
|
|
80
|
-
## Programmatic subpaths
|
|
81
|
-
|
|
82
|
-
| Subpath | Surface |
|
|
83
|
-
|---|---|
|
|
84
|
-
| `@pyric/cli/credentials/node` | `fromServiceAccount`, `fromAdc` — build a `ProjectScope` for the Rules Test API (`pyric verify --engine rules-test-api\|both`) |
|
|
85
|
-
| `@pyric/cli/verify` | Captured-session replay for Firestore and RTDB rules |
|
|
86
|
-
| `@pyric/cli/conformance` | Node query surface: `canIUse` returns full claims and evidence; `canIUseImport` resolves a published import to its canonical compatibility page. |
|
|
87
|
-
| `@pyric/cli/conformance/browser` | Compact browser query surface: `canIUse` returns availability, fidelity, assurance, summary, caveats, and the evidence slug without the full claim graph. |
|
|
88
|
-
| `@pyric/cli/assurance` | Assurance campaign types and tools |
|
|
89
|
-
| `@pyric/cli/assurance/browser` | Browser attachment for assurance campaigns |
|
|
90
|
-
| `@pyric/cli/bridge` | `createBridge`, `startServer` (Node) / `connectBridge` (browser via conditional export). Vite integration is `pyric({ bridge })` in `@pyric/cli/vite`. |
|
|
91
|
-
| `@pyric/cli/bridge/client` | Browser bridge client helpers |
|
|
92
|
-
| `@pyric/cli/vite` | `pyric(opts)`, the dev-only firebase→sandbox swap plugin. Opts: `rules`, `persist`/`fresh`, `seed`, `capture`, `bridge` (MCP), `ui` (Pyric Studio at `/__pyric/ui/`, parity with `dev --ui`). |
|
|
93
|
-
| `@pyric/cli/discover` | Credential-free crawl helpers for sandbox discovery (`crawl`, `findCollectionGroup`, `createFirestoreDiscoverTools`). Not registered on the default MCP bridge. |
|
|
94
|
-
| `@pyric/cli/serve/worker` | SharedWorker serve runtime |
|
|
95
|
-
| `@pyric/cli/remote` | Remote / headless helpers |
|
|
96
|
-
| `@pyric/cli/register` | Registration helpers |
|
|
97
|
-
|
|
98
|
-
## MCP tool surface (`pyric bridge`)
|
|
99
|
-
|
|
100
|
-
The bridge composes its toolsets from the same factories used by its browser
|
|
101
|
-
dispatcher so advertised and executable tools cannot drift. The canonical,
|
|
102
|
-
always-current list is the
|
|
103
|
-
[agent tool inventory](../../docs/agent-tools.md).
|
|
104
|
-
|
|
105
|
-
**Sandbox-routed** — dispatched against the connected browser sandbox
|
|
106
|
-
(`createFirestoreDataTools` + `createFirestoreSimulatorTools` +
|
|
107
|
-
`createFirestoreInspectTools` + local RTDB inspection):
|
|
108
|
-
|
|
109
|
-
- data: `firestore_get_document` / `_list_documents` / `_create_document` / `_add_document` / `_update_document` / `_delete_document` / `_batch_write` / `_query_where` / `firestore_create_with_auto_id`
|
|
110
|
-
- stateful simulator session: `firestore_simulator_create` / `_execute` / `_read` / `_batch` / `_undo` / `_redo` / `_events` / `_transaction`
|
|
111
|
-
- diagnostics: `sandbox_inspect` — single-call sandbox state/rules snapshot
|
|
112
|
-
- RTDB authorization: `rtdb_simulate_access` — evaluates one operation against
|
|
113
|
-
the rules and data currently installed in the connected sandbox
|
|
114
|
-
- RTDB structure: `rtdb_crawl_structure` — returns a bounded structural view of
|
|
115
|
-
current sandbox data without leaf values
|
|
116
|
-
|
|
117
|
-
Assurance campaign tools remain available programmatically from
|
|
118
|
-
`@pyric/cli/assurance`, but are not registered on the default MCP bridge.
|
|
119
|
-
|
|
120
|
-
**In-process** — run on the bridge process itself (`createFirestoreRulesTools`
|
|
121
|
-
without a live `ProjectScope`, so no Rules Test API tool):
|
|
122
|
-
|
|
123
|
-
- `firestore_simulate_rules`
|
|
124
|
-
- `rules_stdlib_list` / `_get` (Firestore or Storage), with
|
|
125
|
-
`firestore_rules_stdlib_list` / `_get` retained as compatibility aliases
|
|
126
|
-
- `rules_resolve_modules` (Firestore or Storage), with
|
|
127
|
-
`firestore_resolve_modules` retained as a compatibility alias
|
|
128
|
-
- `firestore_lint_rules`
|
|
129
|
-
- `firestore_resolve_modules`
|
|
130
|
-
|
|
131
|
-
### Gaps from the playground tool surface
|
|
132
|
-
|
|
133
|
-
The `packages/playground/` app ships richer diagnostic tools that
|
|
134
|
-
the `pyric bridge` does NOT register out of the box today. They're
|
|
135
|
-
playground-specific orchestrators built on top of `useRuntimeStore`
|
|
136
|
-
and other browser-only state:
|
|
137
|
-
|
|
138
|
-
- `inspect_firestore_traffic` — structured dump of the sandbox traffic log
|
|
139
|
-
- `seed_firestore_data_as_admin` — admin-bypass bulk writes for fixture setup
|
|
140
|
-
- `generate_fixture_from_session` — snapshot `sandbox.history()` as a replay fixture
|
|
141
|
-
- `try_rules_edit` — replay events under a proposed rules edit
|
|
142
|
-
- `debug_firestore_rules` — orchestrator over simulate + lint + history + state
|
|
143
|
-
|
|
144
|
-
The underlying primitives (`sandbox.history()`, `pyric/sandbox/replay`, and the
|
|
145
|
-
rules simulator) remain available for custom compositions.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev-runner.d.ts","sourceRoot":"","sources":["../../src/cli/dev-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAM9D;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IACJ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,GACL,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAID,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAKhE;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUxD;AAED,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,YAAY,GAAG,IAAI,CAWtB;AAID;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CAAC,UAAU,CAOnB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAc9F;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC5B;IAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,IAAI,IAAI,CAAA;CAAE,CAkB9C;AAID,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB;0EACsE;IACtE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,YAAY,CAAC;CACrB;AAKD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC3D,cAAc,CAiEhB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev-runner.js","sourceRoot":"","sources":["../../src/cli/dev-runner.ts"],"names":[],"mappings":"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"}
|