@pyric/cli 0.1.0-alpha.20 → 0.1.0-alpha.22
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 +64 -89
- package/dist/assurance/.generated/conformance-verdicts.d.ts +238 -1
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +238 -1
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/bridge/client/dispatch.d.ts +25 -19
- package/dist/bridge/client/dispatch.d.ts.map +1 -1
- package/dist/bridge/client/dispatch.js +41 -48
- package/dist/bridge/client/dispatch.js.map +1 -1
- package/dist/bridge/client/tool-family-factories.d.ts +26 -0
- package/dist/bridge/client/tool-family-factories.d.ts.map +1 -0
- package/dist/bridge/client/tool-family-factories.js +10 -0
- package/dist/bridge/client/tool-family-factories.js.map +1 -0
- package/dist/bridge/server/mcp-contract.d.ts +7 -6
- package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
- package/dist/bridge/server/mcp-contract.js +9 -48
- package/dist/bridge/server/mcp-contract.js.map +1 -1
- package/dist/bridge/server/peer.d.ts +11 -1
- package/dist/bridge/server/peer.d.ts.map +1 -1
- package/dist/bridge/server/peer.js +22 -1
- package/dist/bridge/server/peer.js.map +1 -1
- package/dist/bridge/server/tool-family-factories.d.ts +30 -0
- package/dist/bridge/server/tool-family-factories.d.ts.map +1 -0
- package/dist/bridge/server/tool-family-factories.js +22 -0
- package/dist/bridge/server/tool-family-factories.js.map +1 -0
- package/dist/bridge/server/tool-metadata.d.ts +17 -18
- package/dist/bridge/server/tool-metadata.d.ts.map +1 -1
- package/dist/bridge/server/tool-metadata.js +24 -59
- package/dist/bridge/server/tool-metadata.js.map +1 -1
- package/dist/bridge/tool-families.d.ts +48 -0
- package/dist/bridge/tool-families.d.ts.map +1 -0
- package/dist/bridge/tool-families.generated.d.ts +32 -0
- package/dist/bridge/tool-families.generated.d.ts.map +1 -0
- package/dist/bridge/tool-families.generated.js +15 -0
- package/dist/bridge/tool-families.generated.js.map +1 -0
- package/dist/bridge/tool-families.js +51 -0
- package/dist/bridge/tool-families.js.map +1 -0
- package/dist/bridge/tool-family-records/conformance.d.ts +7 -0
- package/dist/bridge/tool-family-records/conformance.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/conformance.js +6 -0
- package/dist/bridge/tool-family-records/conformance.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-data.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-data.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-data.js +15 -0
- package/dist/bridge/tool-family-records/firestore-data.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-inspect.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-inspect.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-inspect.js +6 -0
- package/dist/bridge/tool-family-records/firestore-inspect.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-rules.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-rules.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-rules.js +15 -0
- package/dist/bridge/tool-family-records/firestore-rules.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-simulator.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-simulator.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-simulator.js +16 -0
- package/dist/bridge/tool-family-records/firestore-simulator.js.map +1 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.d.ts +7 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.js +6 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.js.map +1 -0
- package/dist/bundler/externals.d.ts +37 -0
- package/dist/bundler/externals.d.ts.map +1 -0
- package/dist/bundler/externals.js +52 -0
- package/dist/bundler/externals.js.map +1 -0
- package/dist/bundler/index.d.ts +17 -0
- package/dist/bundler/index.d.ts.map +1 -0
- package/dist/bundler/index.js +17 -0
- package/dist/bundler/index.js.map +1 -0
- package/dist/cli/inlined-sdk-scanner.d.ts +6 -0
- package/dist/cli/inlined-sdk-scanner.d.ts.map +1 -0
- package/dist/cli/inlined-sdk-scanner.js +82 -0
- package/dist/cli/inlined-sdk-scanner.js.map +1 -0
- package/dist/cli/sandbox-interlock.d.ts +97 -0
- package/dist/cli/sandbox-interlock.d.ts.map +1 -0
- package/dist/cli/sandbox-interlock.js +112 -0
- package/dist/cli/sandbox-interlock.js.map +1 -0
- package/dist/cli/sandbox-runner.d.ts +20 -12
- package/dist/cli/sandbox-runner.d.ts.map +1 -1
- package/dist/cli/sandbox-runner.js +24 -21
- package/dist/cli/sandbox-runner.js.map +1 -1
- package/dist/cli/serve.d.ts +6 -10
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +57 -77
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/unsupported-runtime.d.ts +27 -0
- package/dist/cli/unsupported-runtime.d.ts.map +1 -0
- package/dist/cli/unsupported-runtime.js +63 -0
- package/dist/cli/unsupported-runtime.js.map +1 -0
- package/dist/conformance/.generated/can-i-use-browser.d.ts +1 -1
- package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +1 -1
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
- package/dist/conformance/.generated/conformance-docs.js +1 -1
- package/dist/conformance/.generated/conformance-docs.js.map +1 -1
- package/dist/functions-rtdb/child.d.ts +37 -0
- package/dist/functions-rtdb/child.d.ts.map +1 -1
- package/dist/functions-rtdb/child.js +90 -21
- package/dist/functions-rtdb/child.js.map +1 -1
- package/dist/functions-rtdb/development-runtime.d.ts +3 -0
- package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
- package/dist/functions-rtdb/development-runtime.js +1 -0
- package/dist/functions-rtdb/development-runtime.js.map +1 -1
- package/dist/google-endpoints.d.ts +67 -0
- package/dist/google-endpoints.d.ts.map +1 -0
- package/dist/google-endpoints.js +119 -0
- package/dist/google-endpoints.js.map +1 -0
- package/dist/next/runtime-env.d.ts.map +1 -1
- package/dist/next/runtime-env.js +5 -0
- package/dist/next/runtime-env.js.map +1 -1
- package/dist/next/with-pyric.d.ts +1 -1
- package/dist/next/with-pyric.js +1 -1
- package/dist/register/beacon.d.ts +69 -0
- package/dist/register/beacon.d.ts.map +1 -0
- package/dist/register/beacon.js +199 -0
- package/dist/register/beacon.js.map +1 -0
- package/dist/register/index.d.ts.map +1 -1
- package/dist/register/index.js +65 -6
- package/dist/register/index.js.map +1 -1
- package/dist/register/net-guard.d.ts +110 -0
- package/dist/register/net-guard.d.ts.map +1 -0
- package/dist/register/net-guard.js +462 -0
- package/dist/register/net-guard.js.map +1 -0
- package/dist/serve/ai-diagnostics-relay.d.ts +63 -0
- package/dist/serve/ai-diagnostics-relay.d.ts.map +1 -0
- package/dist/serve/ai-diagnostics-relay.js +125 -0
- package/dist/serve/ai-diagnostics-relay.js.map +1 -0
- package/dist/serve/ai-proxy.d.ts +92 -0
- package/dist/serve/ai-proxy.d.ts.map +1 -0
- package/dist/serve/ai-proxy.js +269 -0
- package/dist/serve/ai-proxy.js.map +1 -0
- package/dist/serve/ai-status.d.ts +44 -0
- package/dist/serve/ai-status.d.ts.map +1 -0
- package/dist/serve/ai-status.js +77 -0
- package/dist/serve/ai-status.js.map +1 -0
- package/dist/serve/ai-terminal-blocks.d.ts +97 -0
- package/dist/serve/ai-terminal-blocks.d.ts.map +1 -0
- package/dist/serve/ai-terminal-blocks.js +128 -0
- package/dist/serve/ai-terminal-blocks.js.map +1 -0
- package/dist/serve/ai-terminal-text.d.ts +36 -0
- package/dist/serve/ai-terminal-text.d.ts.map +1 -0
- package/dist/serve/ai-terminal-text.js +48 -0
- package/dist/serve/ai-terminal-text.js.map +1 -0
- package/dist/serve/beacon-route.d.ts +53 -0
- package/dist/serve/beacon-route.d.ts.map +1 -0
- package/dist/serve/beacon-route.js +101 -0
- package/dist/serve/beacon-route.js.map +1 -0
- package/dist/serve/entries/active-auth-registry.d.ts +16 -0
- package/dist/serve/entries/active-auth-registry.d.ts.map +1 -0
- package/dist/serve/entries/active-auth-registry.js +48 -0
- package/dist/serve/entries/active-auth-registry.js.map +1 -0
- package/dist/serve/entries/active-auth.d.ts +18 -0
- package/dist/serve/entries/active-auth.d.ts.map +1 -0
- package/dist/serve/entries/active-auth.js +84 -0
- package/dist/serve/entries/active-auth.js.map +1 -0
- package/dist/serve/entries/auth-helper-core.d.ts +1 -0
- package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
- package/dist/serve/entries/auth-helper-core.js +4 -0
- package/dist/serve/entries/auth-helper-core.js.map +1 -1
- package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -1
- package/dist/serve/entries/auth-helper-dom.js +28 -2
- package/dist/serve/entries/auth-helper-dom.js.map +1 -1
- package/dist/serve/entries/auth.d.ts.map +1 -1
- package/dist/serve/entries/auth.js +8 -0
- package/dist/serve/entries/auth.js.map +1 -1
- package/dist/serve/entries/bridge-url.d.ts +1 -1
- package/dist/serve/entries/bridge-url.js +1 -1
- package/dist/serve/entries/init.d.ts.map +1 -1
- package/dist/serve/entries/init.js +70 -4
- package/dist/serve/entries/init.js.map +1 -1
- package/dist/serve/entries/runtime.d.ts.map +1 -1
- package/dist/serve/entries/runtime.js +9 -0
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/namespace.d.ts +14 -5
- package/dist/serve/namespace.d.ts.map +1 -1
- package/dist/serve/namespace.js +57 -124
- package/dist/serve/namespace.js.map +1 -1
- package/dist/serve/runtime/chip-config.d.ts.map +1 -1
- package/dist/serve/runtime/chip-config.js +16 -2
- package/dist/serve/runtime/chip-config.js.map +1 -1
- package/dist/serve/runtime/chip-dialog.d.ts +18 -0
- package/dist/serve/runtime/chip-dialog.d.ts.map +1 -0
- package/dist/serve/runtime/chip-dialog.js +315 -0
- package/dist/serve/runtime/chip-dialog.js.map +1 -0
- package/dist/serve/runtime/chip-install.d.ts +2 -0
- package/dist/serve/runtime/chip-install.d.ts.map +1 -1
- package/dist/serve/runtime/chip-install.js +9 -4
- package/dist/serve/runtime/chip-install.js.map +1 -1
- package/dist/serve/runtime/chip-user-search.d.ts +16 -0
- package/dist/serve/runtime/chip-user-search.d.ts.map +1 -0
- package/dist/serve/runtime/chip-user-search.js +354 -0
- package/dist/serve/runtime/chip-user-search.js.map +1 -0
- package/dist/serve/runtime/chip.d.ts +10 -0
- package/dist/serve/runtime/chip.d.ts.map +1 -1
- package/dist/serve/runtime/chip.js +118 -15
- package/dist/serve/runtime/chip.js.map +1 -1
- package/dist/serve/runtime/identity.d.ts +17 -0
- package/dist/serve/runtime/identity.d.ts.map +1 -0
- package/dist/serve/runtime/identity.js +10 -0
- package/dist/serve/runtime/identity.js.map +1 -0
- package/dist/serve/sandbox-session.d.ts +7 -0
- package/dist/serve/sandbox-session.d.ts.map +1 -1
- package/dist/serve/sandbox-session.js +2 -0
- package/dist/serve/sandbox-session.js.map +1 -1
- package/dist/serve/site-ui/_astro/{RulesCodeEditor.XtDmHOlN.js → RulesCodeEditor.DsTAsKIa.js} +1 -1
- package/dist/serve/site-ui/_astro/app.CMmTxyhL.js +1 -0
- package/dist/serve/site-ui/_astro/app.DhALsVii.js +115 -0
- package/dist/serve/site-ui/_astro/{chess-showcase.B72XYeoh.js → chess-showcase.Bn_pP6UJ.js} +2 -2
- package/dist/serve/site-ui/_astro/{example-runtime.C25_lx6Z.js → example-runtime.CXopTGv7.js} +1 -1
- package/dist/serve/site-ui/_astro/sandbox-controls.rOuZTOUG.js +510 -0
- package/dist/serve/site-ui/_astro/{seed.Co0yUJY5.js → seed.lywYbXZ0.js} +2 -2
- package/dist/serve/site-ui/_astro/writes.BsPBG3dp.js +653 -0
- package/dist/serve/site-ui/auth/index.html +1 -1
- package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
- package/dist/serve/site-ui/docs/ai-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/api-reference/index.html +8 -1
- package/dist/serve/site-ui/docs/api-reference.md +7 -0
- package/dist/serve/site-ui/docs/app-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/auth-compat/index.html +3 -3
- package/dist/serve/site-ui/docs/auth-compat.md +2 -2
- package/dist/serve/site-ui/docs/build/ai-logic/index.html +6 -1
- package/dist/serve/site-ui/docs/build/ai-logic.md +6 -0
- package/dist/serve/site-ui/docs/build/authentication/index.html +2 -2
- package/dist/serve/site-ui/docs/build/authentication.md +1 -1
- package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +4 -2
- package/dist/serve/site-ui/docs/build/cloud-firestore.md +4 -0
- package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
- package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
- package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
- package/dist/serve/site-ui/docs/conformance-scores/index.html +14 -2
- package/dist/serve/site-ui/docs/conformance-scores.md +13 -1
- package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/database-compat/index.html +44 -44
- package/dist/serve/site-ui/docs/database-compat.md +43 -43
- package/dist/serve/site-ui/docs/examples/chess/index.html +1 -1
- package/dist/serve/site-ui/docs/examples/index.html +1 -1
- package/dist/serve/site-ui/docs/firestore-compat/index.html +4 -4
- package/dist/serve/site-ui/docs/firestore-compat.md +3 -3
- package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +319 -0
- package/dist/serve/site-ui/docs/firestore-flutter-compat.md +344 -0
- package/dist/serve/site-ui/docs/firestore-kotlin-compat/index.html +319 -0
- package/dist/serve/site-ui/docs/firestore-kotlin-compat.md +344 -0
- package/dist/serve/site-ui/docs/firestore-swift-compat/index.html +490 -0
- package/dist/serve/site-ui/docs/firestore-swift-compat.md +517 -0
- package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +105 -0
- package/dist/serve/site-ui/docs/get-started/backend-bundlers.md +165 -0
- package/dist/serve/site-ui/docs/get-started/flutter/index.html +98 -0
- package/dist/serve/site-ui/docs/get-started/flutter.md +105 -0
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/nextjs/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/vite/index.html +1 -1
- package/dist/serve/site-ui/docs/index.json +3211 -1471
- package/dist/serve/site-ui/docs/messaging-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +4 -3
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status.md +3 -1
- package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/switch-and-impersonate-identities/index.html +110 -0
- package/dist/serve/site-ui/docs/observe/switch-and-impersonate-identities.md +134 -0
- package/dist/serve/site-ui/docs/overview/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +124 -0
- package/dist/serve/site-ui/docs/pyric-analytics-reference-api.md +287 -0
- package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +87 -0
- package/dist/serve/site-ui/docs/pyric-app-check-reference-api.md +199 -0
- package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +6 -2
- package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +2 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +56 -0
- package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api.md +72 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +4 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api.md +3 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +4 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api.md +3 -0
- package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +34 -9
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +16 -8
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +133 -93
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +61 -1
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +2 -2
- package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-database-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +559 -0
- package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api.md +1240 -0
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +40 -11
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +18 -8
- package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +67 -0
- package/dist/serve/site-ui/docs/pyric-functions-reference-api.md +149 -0
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +35 -0
- package/dist/serve/site-ui/docs/pyric-performance-reference-api.md +69 -0
- package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +132 -0
- package/dist/serve/site-ui/docs/pyric-remote-config-reference-api.md +307 -0
- package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +52 -17
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +48 -9
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +239 -49
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +148 -31
- package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +22 -4
- package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +25 -3
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +26 -96
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api.md +20 -51
- package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +124 -26
- package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api.md +58 -5
- package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +4 -5
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +3 -4
- package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/reference/cli/index.html +6 -3
- package/dist/serve/site-ui/docs/reference/cli.md +8 -2
- package/dist/serve/site-ui/docs/rules-compat/index.html +10 -2
- package/dist/serve/site-ui/docs/rules-compat.md +9 -1
- package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
- package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
- package/dist/serve/site-ui/docs/storage-compat/index.html +13 -13
- package/dist/serve/site-ui/docs/storage-compat.md +12 -12
- package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
- package/dist/serve/site-ui/docs/tutorial/index.html +1 -1
- package/dist/serve/site-ui/examples/chess/index.html +1 -1
- package/dist/serve/site-ui/firestore/index.html +1 -1
- package/dist/serve/site-ui/llms.txt +13 -0
- package/dist/serve/site-ui/rtdb/index.html +1 -1
- package/dist/serve/site-ui/settings/index.html +1 -1
- package/dist/serve/site-ui/storage/index.html +1 -1
- package/dist/serve/site-ui/studio/index.html +1 -1
- package/dist/serve/site-ui/traffic/index.html +1 -1
- package/dist/serve/studio/disk-workspace.d.ts.map +1 -1
- package/dist/serve/studio/disk-workspace.js +64 -2
- package/dist/serve/studio/disk-workspace.js.map +1 -1
- package/dist/serve/vite-plugin.d.ts +7 -7
- package/dist/serve/vite-plugin.js +1 -1
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
- package/dist/serve/vite-sandbox-generation.js +12 -0
- package/dist/serve/vite-sandbox-generation.js.map +1 -1
- package/dist/serve/worker/client/auth.js +1 -2
- package/dist/serve/worker/client/auth.js.map +1 -1
- package/dist/serve/worker/client/core.d.ts +21 -1
- package/dist/serve/worker/client/core.d.ts.map +1 -1
- package/dist/serve/worker/client/core.js +79 -3
- package/dist/serve/worker/client/core.js.map +1 -1
- package/dist/serve/worker/client.d.ts +1 -1
- package/dist/serve/worker/client.d.ts.map +1 -1
- package/dist/serve/worker/client.js +1 -1
- package/dist/serve/worker/client.js.map +1 -1
- package/dist/serve/worker/context-resolver.d.ts +30 -0
- package/dist/serve/worker/context-resolver.d.ts.map +1 -0
- package/dist/serve/worker/context-resolver.js +44 -0
- package/dist/serve/worker/context-resolver.js.map +1 -0
- package/dist/serve/worker/entry.js +23 -19
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/core.d.ts +1 -0
- package/dist/serve/worker/host/core.d.ts.map +1 -1
- package/dist/serve/worker/host/core.js +12 -6
- package/dist/serve/worker/host/core.js.map +1 -1
- package/dist/serve/worker/host/storage.js +2 -2
- package/dist/serve/worker/host-auth.js +1 -2
- package/dist/serve/worker/host-auth.js.map +1 -1
- package/dist/serve/worker/index.d.ts +1 -1
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +2 -2
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/port-lifecycle.d.ts +18 -0
- package/dist/serve/worker/port-lifecycle.d.ts.map +1 -0
- package/dist/serve/worker/port-lifecycle.js +28 -0
- package/dist/serve/worker/port-lifecycle.js.map +1 -0
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +8 -2
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/verify/fixture.d.ts +1 -1
- package/package.json +16 -5
- package/src/assurance/.generated/conformance-verdicts.ts +238 -1
- package/src/bridge/client/dispatch.ts +52 -56
- package/src/bridge/client/tool-family-factories.ts +34 -0
- package/src/bridge/server/mcp-contract.ts +15 -59
- package/src/bridge/server/peer.ts +24 -1
- package/src/bridge/server/tool-family-factories.ts +40 -0
- package/src/bridge/server/tool-metadata.ts +29 -61
- package/src/bridge/tool-families.generated.ts +17 -0
- package/src/bridge/tool-families.ts +87 -0
- package/src/bridge/tool-family-records/conformance.ts +6 -0
- package/src/bridge/tool-family-records/firestore-data.ts +15 -0
- package/src/bridge/tool-family-records/firestore-inspect.ts +6 -0
- package/src/bridge/tool-family-records/firestore-rules.ts +15 -0
- package/src/bridge/tool-family-records/firestore-simulator.ts +16 -0
- package/src/bridge/tool-family-records/rtdb-inspection.ts +6 -0
- package/src/bundler/externals.ts +55 -0
- package/src/bundler/index.ts +21 -0
- package/src/cli/cli.test.ts +0 -44
- package/src/cli/inlined-sdk-scanner.ts +77 -0
- package/src/cli/sandbox-interlock.ts +167 -0
- package/src/cli/sandbox-runner.ts +37 -26
- package/src/cli/serve.ts +68 -69
- package/src/cli/unsupported-runtime.ts +68 -0
- package/src/conformance/.generated/can-i-use-browser.ts +2 -2
- package/src/conformance/.generated/can-i-use.ts +2 -2
- package/src/conformance/.generated/conformance-docs.ts +1 -1
- package/src/functions-rtdb/child.ts +115 -21
- package/src/functions-rtdb/development-runtime.ts +4 -0
- package/src/google-endpoints.ts +155 -0
- package/src/next/runtime-env.ts +5 -0
- package/src/next/with-pyric.ts +1 -1
- package/src/register/beacon.ts +232 -0
- package/src/register/index.ts +68 -6
- package/src/register/net-guard.ts +567 -0
- package/src/serve/ai-diagnostics-relay.ts +243 -0
- package/src/serve/ai-proxy.ts +327 -0
- package/src/serve/ai-status.ts +109 -0
- package/src/serve/ai-terminal-blocks.ts +210 -0
- package/src/serve/ai-terminal-text.ts +52 -0
- package/src/serve/beacon-route.ts +141 -0
- package/src/serve/entries/active-auth-registry.ts +56 -0
- package/src/serve/entries/active-auth.ts +100 -0
- package/src/serve/entries/auth-helper-core.ts +5 -0
- package/src/serve/entries/auth-helper-dom.ts +26 -2
- package/src/serve/entries/auth.ts +8 -0
- package/src/serve/entries/bridge-url.ts +1 -1
- package/src/serve/entries/init.ts +78 -3
- package/src/serve/entries/runtime.ts +10 -0
- package/src/serve/namespace.ts +73 -140
- package/src/serve/runtime/chip-config.ts +16 -2
- package/src/serve/runtime/chip-dialog.ts +366 -0
- package/src/serve/runtime/chip-install.ts +10 -4
- package/src/serve/runtime/chip-user-search.ts +391 -0
- package/src/serve/runtime/chip.ts +140 -15
- package/src/serve/runtime/identity.ts +26 -0
- package/src/serve/sandbox-session.ts +9 -0
- package/src/serve/studio/disk-workspace.ts +76 -2
- package/src/serve/vite-plugin.ts +8 -8
- package/src/serve/vite-sandbox-generation.ts +15 -0
- package/src/serve/worker/client/auth.ts +1 -1
- package/src/serve/worker/client/core.ts +80 -3
- package/src/serve/worker/client.ts +1 -1
- package/src/serve/worker/context-resolver.ts +60 -0
- package/src/serve/worker/entry.ts +22 -18
- package/src/serve/worker/host/core.ts +9 -7
- package/src/serve/worker/host/storage.ts +2 -2
- package/src/serve/worker/host-auth.ts +1 -1
- package/src/serve/worker/index.ts +4 -1
- package/src/serve/worker/port-lifecycle.ts +45 -0
- package/src/serve/worker/serve-init.ts +9 -2
- package/src/verify/fixture.ts +1 -1
- package/dist/serve/site-ui/_astro/app.B52xr-DK.js +0 -1
- package/dist/serve/site-ui/_astro/app.DWBraPUw.js +0 -12
- package/dist/serve/site-ui/_astro/sandbox-controls.DEpnKg-O.js +0 -1169
- package/dist/serve/site-ui/_astro/writes.rpjrFzmu.js +0 -102
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AuthUserRecord } from 'pyric/auth';
|
|
2
|
+
|
|
3
|
+
export interface RuntimeIdentity {
|
|
4
|
+
uid: string;
|
|
5
|
+
email?: string | null;
|
|
6
|
+
displayName?: string | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** The chip's complete identity integration seam, passed intact through mounting. */
|
|
10
|
+
export interface RuntimeIdentityBindings {
|
|
11
|
+
listUsers(): Promise<AuthUserRecord[]> | AuthUserRecord[];
|
|
12
|
+
switchUser(uid: string): Promise<void> | void;
|
|
13
|
+
signOut(): Promise<void> | void;
|
|
14
|
+
openCreateUser(): void;
|
|
15
|
+
getCurrentUser(): RuntimeIdentity | null;
|
|
16
|
+
subscribeAuth(listener: (user: RuntimeIdentity | null) => void): () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function projectRuntimeIdentity(user: RuntimeIdentity | null | undefined): RuntimeIdentity | null {
|
|
20
|
+
if (!user) return null;
|
|
21
|
+
return {
|
|
22
|
+
uid: user.uid,
|
|
23
|
+
email: user.email,
|
|
24
|
+
displayName: user.displayName,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
rulesHashOf,
|
|
15
15
|
} from './rules.js';
|
|
16
16
|
import { createEventHub, createPyricNamespace } from './namespace.js';
|
|
17
|
+
import type { BeaconReport } from '../register/beacon.js';
|
|
17
18
|
import { diskProjectStore, diskWorkspace } from './studio/index.js';
|
|
18
19
|
import type { ServeLogger } from './server.js';
|
|
19
20
|
import {
|
|
@@ -38,6 +39,12 @@ export interface SandboxSessionOptions {
|
|
|
38
39
|
permissive?: boolean;
|
|
39
40
|
logger?: ServeLogger;
|
|
40
41
|
activity?: (incident: ActivityIncident) => void;
|
|
42
|
+
/** Receives one handshake beacon per pyric-launched child, the dev
|
|
43
|
+
* server's only positive proof that the register module reached it. */
|
|
44
|
+
beacon?: (report: BeaconReport) => void;
|
|
45
|
+
/** The per-launch secret a beacon must present, also placed in the child's
|
|
46
|
+
* `PYRIC_BEACON_TOKEN`. */
|
|
47
|
+
beaconToken?: string;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
export interface SandboxSessionSummary {
|
|
@@ -212,6 +219,8 @@ export async function createSandboxSession(
|
|
|
212
219
|
workerVersion: options.sdk.workerVersion,
|
|
213
220
|
aiProxyUpstream: options.aiProxyUpstream,
|
|
214
221
|
activity: options.activity,
|
|
222
|
+
beacon: options.beacon,
|
|
223
|
+
beaconToken: options.beaconToken,
|
|
215
224
|
logger: options.logger,
|
|
216
225
|
});
|
|
217
226
|
|
|
@@ -17,8 +17,16 @@ import {
|
|
|
17
17
|
stat,
|
|
18
18
|
writeFile,
|
|
19
19
|
} from 'node:fs/promises';
|
|
20
|
-
import {
|
|
21
|
-
|
|
20
|
+
import {
|
|
21
|
+
existsSync,
|
|
22
|
+
lstatSync,
|
|
23
|
+
mkdirSync,
|
|
24
|
+
readlinkSync,
|
|
25
|
+
realpathSync,
|
|
26
|
+
watch as fsWatch,
|
|
27
|
+
type FSWatcher,
|
|
28
|
+
} from 'node:fs';
|
|
29
|
+
import { basename, dirname, join, posix, relative, resolve, sep } from 'node:path';
|
|
22
30
|
|
|
23
31
|
import type {
|
|
24
32
|
WorkspaceChange,
|
|
@@ -34,6 +42,54 @@ export class WorkspacePathError extends Error {
|
|
|
34
42
|
}
|
|
35
43
|
}
|
|
36
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Resolves the canonical realpath of a path, handling symlinks and non-existent
|
|
47
|
+
* terminal segments by resolving the nearest existing ancestor.
|
|
48
|
+
*/
|
|
49
|
+
function getCanonicalPath(targetPath: string, seen = new Set<string>()): string {
|
|
50
|
+
const abs = resolve(targetPath);
|
|
51
|
+
if (seen.has(abs)) {
|
|
52
|
+
throw new WorkspacePathError(targetPath);
|
|
53
|
+
}
|
|
54
|
+
seen.add(abs);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
return realpathSync(abs);
|
|
58
|
+
} catch (err: any) {
|
|
59
|
+
if (err?.code === 'ELOOP') {
|
|
60
|
+
throw new WorkspacePathError(targetPath);
|
|
61
|
+
}
|
|
62
|
+
if (err?.code !== 'ENOENT' && err?.code !== 'ENOTDIR') {
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const st = lstatSync(abs);
|
|
69
|
+
if (st.isSymbolicLink()) {
|
|
70
|
+
const linkTarget = readlinkSync(abs);
|
|
71
|
+
const nextTarget = resolve(dirname(abs), linkTarget);
|
|
72
|
+
return getCanonicalPath(nextTarget, seen);
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
// abs does not exist as a directory entry
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const parent = dirname(abs);
|
|
79
|
+
if (parent === abs) {
|
|
80
|
+
return abs;
|
|
81
|
+
}
|
|
82
|
+
const canonicalParent = getCanonicalPath(parent, seen);
|
|
83
|
+
return join(canonicalParent, basename(abs));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Check whether canonical target is contained within canonical root. */
|
|
87
|
+
function isContained(root: string, target: string): boolean {
|
|
88
|
+
if (target === root) return true;
|
|
89
|
+
const prefix = root.endsWith(sep) ? root : root + sep;
|
|
90
|
+
return target.startsWith(prefix);
|
|
91
|
+
}
|
|
92
|
+
|
|
37
93
|
/**
|
|
38
94
|
* Resolve a project-relative POSIX path to an absolute OS path inside `root`,
|
|
39
95
|
* or throw {@link WorkspacePathError} if it would escape. Leading slashes are
|
|
@@ -52,6 +108,24 @@ export function resolveWorkspacePath(root: string, rel: string): string {
|
|
|
52
108
|
if (abs !== root && !abs.startsWith(root + sep)) {
|
|
53
109
|
throw new WorkspacePathError(rel);
|
|
54
110
|
}
|
|
111
|
+
|
|
112
|
+
// Canonical realpath containment check:
|
|
113
|
+
// Reject symlinks that escape the workspace root.
|
|
114
|
+
const canonicalRoot = getCanonicalPath(root);
|
|
115
|
+
let canonicalTarget: string;
|
|
116
|
+
try {
|
|
117
|
+
canonicalTarget = getCanonicalPath(abs);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (err instanceof WorkspacePathError) {
|
|
120
|
+
throw new WorkspacePathError(rel);
|
|
121
|
+
}
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!isContained(canonicalRoot, canonicalTarget)) {
|
|
126
|
+
throw new WorkspacePathError(rel);
|
|
127
|
+
}
|
|
128
|
+
|
|
55
129
|
return abs;
|
|
56
130
|
}
|
|
57
131
|
|
package/src/serve/vite-plugin.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@pyric/cli/vite` — the firebase→pyric-sandbox swap as a Vite plugin.
|
|
3
3
|
*
|
|
4
|
-
* The serve analog for SOURCE-driven apps: instead of `vite build && pyric
|
|
4
|
+
* The serve analog for SOURCE-driven apps: instead of `vite build && pyric sandbox
|
|
5
5
|
* dist`, a team keeps `vite dev` (HMR, source maps) with the in-process sandbox
|
|
6
6
|
* standing in for Firebase. The app's `firebase/*` imports are UNCHANGED — the
|
|
7
7
|
* plugin swaps them at the module-resolution layer (`resolveId`), the same way
|
|
8
|
-
* `pyric
|
|
8
|
+
* `pyric sandbox` swaps via a runtime import map. (Design: `plans/pyric-vite-plugin.md`.)
|
|
9
9
|
*
|
|
10
10
|
* Two flavors, one `apply` function. Under `vite dev` the swap is ALWAYS on.
|
|
11
11
|
* For `vite build` the swap is MODE-gated: a plain `vite build` (mode
|
|
12
12
|
* `production`) ships the real `firebase` package — the swap never reaches the
|
|
13
13
|
* prod artifact — while `vite build --mode development` (any NON-production
|
|
14
14
|
* mode) produces a SANDBOX build that bundles pyric's in-page adapters instead
|
|
15
|
-
* of the real SDK: self-contained, meant to be previewed under `pyric
|
|
15
|
+
* of the real SDK: self-contained, meant to be previewed under `pyric sandbox`, and
|
|
16
16
|
* stamped with the sandbox-build marker so it can never be deployed (`pyric
|
|
17
17
|
* deploy hosting` refuses it). `pyric({ swapInBuild })` forces the build
|
|
18
18
|
* behavior on/off regardless of mode. See `sandbox-marker.ts`.
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
* - the host-neutral sandbox session — rules, fixtures, stores, live payload,
|
|
25
25
|
* Studio routes, `/__pyric/*` namespace, and owned cleanup;
|
|
26
26
|
* - the SharedWorker host — `bundleWorker` served at `/__pyric/sdk/worker.js`;
|
|
27
|
-
* - the bridge mount shared with `pyric
|
|
27
|
+
* - the bridge mount shared with `pyric sandbox --bridge`.
|
|
28
28
|
*
|
|
29
29
|
* Scope = M1 (swap + rules) + M2 (SharedWorker multi-tab + persist/capture/seed)
|
|
30
30
|
* + M3 (the MCP bridge fold — `{ bridge }`). M3 reuses `createBridgeMount` (the
|
|
31
|
-
* proven serve-flavored bridge behind `pyric
|
|
31
|
+
* proven serve-flavored bridge behind `pyric sandbox --bridge`), composing it into
|
|
32
32
|
* the same `/__pyric` middleware; on the worker path the bridge peer routes
|
|
33
33
|
* agent tool-calls THROUGH the SharedWorker (`connectBridgePeer`), so the agent
|
|
34
34
|
* and the app share one backend without forcing the page in-page.
|
|
@@ -82,7 +82,7 @@ export interface PyricOptions {
|
|
|
82
82
|
* only when the worker bundle itself fails, bridge or not. */
|
|
83
83
|
bridge?: boolean | { project?: string; disableAuditLog?: boolean };
|
|
84
84
|
/** Serve the **Pyric Studio** app at `/__pyric/ui/` on Vite's dev origin (the
|
|
85
|
-
* `pyric
|
|
85
|
+
* `pyric sandbox --ui` equivalent). Mounts the disk-backed workspace/project
|
|
86
86
|
* routes Studio's `local` mode talks to AND serves the unified Astro site
|
|
87
87
|
* (vendored in this package at `dist/serve/site-ui`). **On by default**,
|
|
88
88
|
* including under `bridge` (the bridge peer routes through the SharedWorker,
|
|
@@ -93,7 +93,7 @@ export interface PyricOptions {
|
|
|
93
93
|
* dev/builds. On by default. Pass `false` to hide it, or
|
|
94
94
|
* `{ initiallyOpen: true }` when actively debugging runtime errors. */
|
|
95
95
|
runtimeChip?: PyricRuntimeChipOption;
|
|
96
|
-
/** RTDB-triggered Cloud Functions under this dev server (the `pyric
|
|
96
|
+
/** RTDB-triggered Cloud Functions under this dev server (the `pyric sandbox`
|
|
97
97
|
* parity fold). By default a `functions` block in `firebase.json` is
|
|
98
98
|
* discovered automatically: its `onValueCreated` triggers run in an isolated
|
|
99
99
|
* node child against the shared sandbox (other trigger kinds warn and are
|
|
@@ -216,7 +216,7 @@ export function pyric(options: PyricOptions = {}): Plugin {
|
|
|
216
216
|
// `vite build` keeps the real firebase package — the swap never reaches
|
|
217
217
|
// production output. A sandbox build applies the same swap so the output
|
|
218
218
|
// bundles pyric's in-page adapters (self-contained; preview it under
|
|
219
|
-
// `pyric
|
|
219
|
+
// `pyric sandbox`, never deploy it).
|
|
220
220
|
apply(config, env) {
|
|
221
221
|
void config;
|
|
222
222
|
return pageRuntime.applies(env);
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type FunctionsRtdbProject,
|
|
8
8
|
} from '../functions-rtdb/project.js';
|
|
9
9
|
import { formatActivityWarning } from './activity-warning.js';
|
|
10
|
+
import { formatAiStatusNote } from './ai-status.js';
|
|
10
11
|
import {
|
|
11
12
|
createBridgeMount,
|
|
12
13
|
type BridgeHostAttachment,
|
|
@@ -217,6 +218,20 @@ export async function createViteSandboxGeneration(
|
|
|
217
218
|
server.config.logger.info(' ⓘ [pyric] fresh: discarded the existing state file; re-seeding');
|
|
218
219
|
}
|
|
219
220
|
|
|
221
|
+
// Say what AI resolved to. This is the one front door where the engine and
|
|
222
|
+
// its model binding ARE known at boot (`ai.engine` / `ai.model` reduced to
|
|
223
|
+
// the wire shape above); the broker itself is still built lazily, in the
|
|
224
|
+
// page or the worker, on the first `ai.*` op. Every generation prints it,
|
|
225
|
+
// so a Vite restart on an `.env`/config edit re-announces the new binding
|
|
226
|
+
// through the same formatter instead of swapping engines in silence.
|
|
227
|
+
server.config.logger.info(
|
|
228
|
+
formatAiStatusNote({
|
|
229
|
+
engine: ai.engineWire,
|
|
230
|
+
mode: ai.mode,
|
|
231
|
+
proxyUpstream: ai.proxyUpstream,
|
|
232
|
+
}),
|
|
233
|
+
);
|
|
234
|
+
|
|
220
235
|
const middlewareInput = { server, bridge, session };
|
|
221
236
|
const disposeMiddleware = attachViteGenerationMiddleware(middlewareInput);
|
|
222
237
|
listenerDisposers.push(disposeMiddleware);
|
|
@@ -312,7 +312,7 @@ export async function restorePortSession(
|
|
|
312
312
|
t: 'op', id: nextId(), method: 'auth.restorePortSession', uid,
|
|
313
313
|
})) as SerializedUser | null;
|
|
314
314
|
const user = toClientUser(auth.port, raw);
|
|
315
|
-
|
|
315
|
+
auth.currentUser = user;
|
|
316
316
|
return user;
|
|
317
317
|
}
|
|
318
318
|
|
|
@@ -259,26 +259,103 @@ export function wirePort(port: ClientPort): void {
|
|
|
259
259
|
// ops (`auth.*`) and `getVersion` are NEVER lensed — they operate the worker's
|
|
260
260
|
// session, not data — so the lens is stamped only on the data-op path.
|
|
261
261
|
|
|
262
|
+
export const AUTH_LENS_STORAGE_KEY = 'pyric:auth-lens';
|
|
263
|
+
|
|
264
|
+
type PersistedAuthLens =
|
|
265
|
+
| Extract<AuthLens, { mode: 'admin' }>
|
|
266
|
+
| Extract<AuthLens, { mode: 'as' }>;
|
|
267
|
+
|
|
268
|
+
export function isPersistedAuthLens(value: unknown): value is PersistedAuthLens {
|
|
269
|
+
if (!value || typeof value !== 'object') return false;
|
|
270
|
+
const candidate = value as { mode?: unknown; uid?: unknown };
|
|
271
|
+
if (candidate.mode === 'admin') return true;
|
|
272
|
+
return candidate.mode === 'as' && typeof candidate.uid === 'string';
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function normalizePersistedAuthLens(value: unknown): PersistedAuthLens | undefined {
|
|
276
|
+
if (isPersistedAuthLens(value)) return value;
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Read persisted auth lens from sessionStorage safely. */
|
|
281
|
+
export function hydrateLensFromStorage(): AuthLens | undefined {
|
|
282
|
+
if (typeof sessionStorage === 'undefined') return undefined;
|
|
283
|
+
try {
|
|
284
|
+
const raw = sessionStorage.getItem(AUTH_LENS_STORAGE_KEY);
|
|
285
|
+
if (!raw) return undefined;
|
|
286
|
+
const parsed: unknown = JSON.parse(raw);
|
|
287
|
+
const persistedLens = normalizePersistedAuthLens(parsed);
|
|
288
|
+
if (persistedLens) return persistedLens;
|
|
289
|
+
sessionStorage.removeItem(AUTH_LENS_STORAGE_KEY);
|
|
290
|
+
return undefined;
|
|
291
|
+
} catch {
|
|
292
|
+
try {
|
|
293
|
+
sessionStorage.removeItem(AUTH_LENS_STORAGE_KEY);
|
|
294
|
+
} catch {
|
|
295
|
+
// Ignore storage restrictions
|
|
296
|
+
}
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
262
301
|
/** Module-level default lens. `undefined` ⇒ the worker treats the op as the
|
|
263
302
|
* app's session (the additive default — existing senders omit `actAs`).
|
|
264
303
|
*
|
|
265
304
|
* Exported as a LIVE binding: family modules read it to stamp the lens onto
|
|
266
305
|
* subscriptions (`onSnapshot`, `rtdbOnValue`), and see `setLens(...)` updates
|
|
267
306
|
* through this one singleton. */
|
|
268
|
-
export let _defaultLens: AuthLens | undefined;
|
|
307
|
+
export let _defaultLens: AuthLens | undefined = hydrateLensFromStorage();
|
|
308
|
+
|
|
309
|
+
const lensListeners = new Set<(lens: AuthLens | undefined) => void>();
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Register a listener for auth lens mutations.
|
|
313
|
+
* Returns an unsubscribe function that removes the listener.
|
|
314
|
+
*/
|
|
315
|
+
export function subscribeLens(listener: (lens: AuthLens | undefined) => void): () => void {
|
|
316
|
+
lensListeners.add(listener);
|
|
317
|
+
return () => {
|
|
318
|
+
lensListeners.delete(listener);
|
|
319
|
+
};
|
|
320
|
+
}
|
|
269
321
|
|
|
270
322
|
/**
|
|
271
323
|
* Set the default auth lens applied to subsequent Firestore DATA ops from this
|
|
272
|
-
* client (Pyric Studio). Pass `{ mode: 'as', uid }` to read/write AS a user
|
|
324
|
+
* client (Pyric Studio & Runtime Chip). Pass `{ mode: 'as', uid }` to read/write AS a user
|
|
273
325
|
* (rules apply), `{ mode: 'admin' }` for the admin lens, or
|
|
274
326
|
* `{ mode: 'app-session' }` / `undefined` to revert to the app's own session.
|
|
275
327
|
*
|
|
276
328
|
* The lens is process-wide for this client module (one served page = one
|
|
277
329
|
* worker port), mirroring how Studio drives a single active identity at a time.
|
|
278
330
|
* Auth ops are unaffected — they always operate the real session.
|
|
331
|
+
*
|
|
332
|
+
* Persists active admin and impersonation lenses to sessionStorage under
|
|
333
|
+
* AUTH_LENS_STORAGE_KEY, and removes the key when cleared or reverted to the
|
|
334
|
+
* app session.
|
|
335
|
+
* Notifies all registered subscribeLens listeners.
|
|
279
336
|
*/
|
|
280
337
|
export function setLens(lens: AuthLens | undefined): void {
|
|
281
|
-
_defaultLens = lens
|
|
338
|
+
_defaultLens = normalizePersistedAuthLens(lens);
|
|
339
|
+
|
|
340
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
341
|
+
try {
|
|
342
|
+
if (_defaultLens) {
|
|
343
|
+
sessionStorage.setItem(AUTH_LENS_STORAGE_KEY, JSON.stringify(_defaultLens));
|
|
344
|
+
} else {
|
|
345
|
+
sessionStorage.removeItem(AUTH_LENS_STORAGE_KEY);
|
|
346
|
+
}
|
|
347
|
+
} catch {
|
|
348
|
+
// Ignore quota or disabled storage restrictions
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
for (const listener of [...lensListeners]) {
|
|
353
|
+
try {
|
|
354
|
+
listener(_defaultLens);
|
|
355
|
+
} catch (err) {
|
|
356
|
+
console.error('Error in subscribeLens listener:', err);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
282
359
|
}
|
|
283
360
|
|
|
284
361
|
/** The active default lens (read-only view), for Studio UI to reflect state. */
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
// Shared core: lens/issuer controls + the handle and snapshot types.
|
|
29
|
-
export { setLens, getLens, setOpIssuer } from './client/core.js';
|
|
29
|
+
export { setLens, getLens, subscribeLens, AUTH_LENS_STORAGE_KEY, hydrateLensFromStorage, setOpIssuer } from './client/core.js';
|
|
30
30
|
export type {
|
|
31
31
|
ClientDb,
|
|
32
32
|
ClientRtdb,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SharedWorker context resolver.
|
|
3
|
+
*
|
|
4
|
+
* Coordinates asynchronous initialization of a singleton resource across
|
|
5
|
+
* concurrent inbound connection requests or burst messages.
|
|
6
|
+
*
|
|
7
|
+
* Invariants:
|
|
8
|
+
* 1. Single In-Flight Attempt: When multiple callers request the context
|
|
9
|
+
* concurrently while initialization is in flight, all callers share the
|
|
10
|
+
* single in-flight promise rather than starting parallel initializations.
|
|
11
|
+
* 2. Unpoisoned on Rejection: If initialization rejects, the memoized promise
|
|
12
|
+
* is cleared immediately, allowing subsequent requests to retry initialization
|
|
13
|
+
* rather than permanently caching the rejection.
|
|
14
|
+
* 3. Synchronous Retrieval: Once successfully resolved, the resource is
|
|
15
|
+
* available synchronously for shutdown and cleanup handlers.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface ContextResolver<T> {
|
|
19
|
+
/**
|
|
20
|
+
* Return the resolved resource or the in-flight initialization promise.
|
|
21
|
+
* If a previous attempt rejected, starts a new attempt.
|
|
22
|
+
*/
|
|
23
|
+
get(): Promise<T>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Return the successfully resolved resource, or null if not yet resolved
|
|
27
|
+
* or currently in-flight.
|
|
28
|
+
*/
|
|
29
|
+
current(): T | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function createContextResolver<T>(factory: () => Promise<T>): ContextResolver<T> {
|
|
33
|
+
let value: T | null = null;
|
|
34
|
+
let inFlight: Promise<T> | null = null;
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
async get(): Promise<T> {
|
|
38
|
+
if (value !== null) {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
if (inFlight === null) {
|
|
42
|
+
inFlight = factory()
|
|
43
|
+
.then((resolved) => {
|
|
44
|
+
value = resolved;
|
|
45
|
+
return resolved;
|
|
46
|
+
})
|
|
47
|
+
.catch((error: unknown) => {
|
|
48
|
+
inFlight = null;
|
|
49
|
+
value = null;
|
|
50
|
+
throw error;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return inFlight;
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
current(): T | null {
|
|
57
|
+
return value;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -67,36 +67,33 @@ import {
|
|
|
67
67
|
} from './service-worker-channel.js';
|
|
68
68
|
import { createServiceWorkerRelay } from './service-worker-relay.js';
|
|
69
69
|
import { createWorkerRetirement } from './retirement.js';
|
|
70
|
+
import { createContextResolver } from './context-resolver.js';
|
|
71
|
+
import { createPortLifecycleManager } from './port-lifecycle.js';
|
|
70
72
|
|
|
71
73
|
declare const __PYRIC_WORKER_VERSION__: string;
|
|
72
74
|
const workerEpoch = typeof __PYRIC_WORKER_VERSION__ !== 'undefined'
|
|
73
75
|
? __PYRIC_WORKER_VERSION__
|
|
74
76
|
: 'dev';
|
|
75
77
|
const workerScope = self as unknown as SharedWorkerGlobalScope;
|
|
78
|
+
const contextResolver = createContextResolver(buildCtx);
|
|
79
|
+
const portLifecycle = createPortLifecycleManager();
|
|
76
80
|
const retirement = createWorkerRetirement({
|
|
77
81
|
closeWorker: () => workerScope.close(),
|
|
78
|
-
beforeAnnounce: async () => { await
|
|
82
|
+
beforeAnnounce: async () => { await contextResolver.current()?.captureFlush?.(); },
|
|
79
83
|
});
|
|
80
84
|
|
|
81
85
|
// ─── Singleton context ────────────────────────────────────────────────────
|
|
82
86
|
|
|
83
|
-
// `_ctx` is the RESOLVED context, kept for the synchronous `close` handler.
|
|
84
|
-
// The build is memoized as a PROMISE (`_ctxPromise`) — NOT as the resolved
|
|
85
|
-
// value — because init is async (it awaits `/__pyric/init.json` + persistence
|
|
86
|
-
// restore). The first messages arrive in a BURST (the authState sub, the first
|
|
87
|
-
// firestore sub, an op — possibly across two tabs at once); if each re-checked
|
|
88
|
-
// only the resolved `_ctx` they would every one start a fresh init and build a
|
|
89
|
-
// SEPARATE sandbox, so a listener and a write could bind to different
|
|
90
|
-
// instances and never see each other. The promise memo guarantees ONE init.
|
|
91
|
-
let _ctx: HostCtx | null = null;
|
|
92
|
-
let _ctxPromise: Promise<HostCtx> | null = null;
|
|
93
|
-
|
|
94
87
|
/**
|
|
95
88
|
* Return the shared context, memoizing the in-flight init promise so
|
|
96
|
-
* concurrent first messages await ONE build
|
|
89
|
+
* concurrent first messages await ONE build. If initialization rejects,
|
|
90
|
+
* the rejection is cleared so subsequent connection attempts can retry.
|
|
91
|
+
* Any ports that closed while initialization was in flight are drained immediately.
|
|
97
92
|
*/
|
|
98
|
-
function getCtx(): Promise<HostCtx> {
|
|
99
|
-
|
|
93
|
+
async function getCtx(): Promise<HostCtx> {
|
|
94
|
+
const ctx = await contextResolver.get();
|
|
95
|
+
portLifecycle.drainClosedPorts(ctx);
|
|
96
|
+
return ctx;
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
/**
|
|
@@ -125,7 +122,6 @@ async function buildCtx(): Promise<HostCtx> {
|
|
|
125
122
|
? (url) => new EventSource(url) as unknown as EventSourceLike
|
|
126
123
|
: null,
|
|
127
124
|
});
|
|
128
|
-
_ctx = ctx; // publish the resolved ctx for the synchronous close handler
|
|
129
125
|
return ctx;
|
|
130
126
|
}
|
|
131
127
|
|
|
@@ -141,6 +137,7 @@ workerScope.onconnect = (e: MessageEvent) => {
|
|
|
141
137
|
const port = e.ports[0];
|
|
142
138
|
port.start();
|
|
143
139
|
retirement.connect(port);
|
|
140
|
+
void getCtx().catch(() => undefined);
|
|
144
141
|
|
|
145
142
|
let messageQueue = Promise.resolve();
|
|
146
143
|
port.onmessage = (ev: MessageEvent<InboundMessage>) => {
|
|
@@ -172,9 +169,16 @@ workerScope.onconnect = (e: MessageEvent) => {
|
|
|
172
169
|
// cannot overtake an already-posted mutation, and later frames see the
|
|
173
170
|
// disconnected-port tombstone instead of touching the shared backend.
|
|
174
171
|
messageQueue = messageQueue.then(async () => {
|
|
172
|
+
const portLike = port as unknown as PortLike;
|
|
173
|
+
if (portLifecycle.isPortClosed(portLike)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
175
176
|
try {
|
|
176
177
|
const ctx = await getCtx();
|
|
177
|
-
|
|
178
|
+
if (portLifecycle.isPortClosed(portLike)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
await handleMessage(ctx, portLike, ev.data);
|
|
178
182
|
} catch (e) {
|
|
179
183
|
// eslint-disable-next-line no-console
|
|
180
184
|
console.error('[pyric worker] message handler error:', (e as Error)?.stack ?? e, 'msg:', ev.data);
|
|
@@ -188,7 +192,7 @@ workerScope.onconnect = (e: MessageEvent) => {
|
|
|
188
192
|
// best-effort; subscriptions also GC when the worker itself dies.
|
|
189
193
|
port.addEventListener('close', () => {
|
|
190
194
|
retirement.disconnect(port);
|
|
191
|
-
|
|
195
|
+
portLifecycle.onPortClosed(port as unknown as PortLike, contextResolver.current());
|
|
192
196
|
});
|
|
193
197
|
};
|
|
194
198
|
|
|
@@ -220,16 +220,18 @@ export function lensDb(ctx: HostCtx, actAs?: AuthLens): Firestore {
|
|
|
220
220
|
return handle;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
export function authStateForLens(actAs: Extract<AuthLens, { mode: 'as' }>): { uid: string; token?: Record<string, unknown
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
223
|
+
export function authStateForLens(actAs: Extract<AuthLens, { mode: 'as' }>): { uid: string; token?: Record<string, unknown>; tenant?: string } {
|
|
224
|
+
const state: { uid: string; token?: Record<string, unknown>; tenant?: string } = { uid: actAs.uid };
|
|
225
|
+
if (actAs.token !== undefined) state.token = actAs.token;
|
|
226
|
+
if (actAs.tenant !== undefined) state.tenant = actAs.tenant;
|
|
227
|
+
return state;
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
export function lensCacheKey(actAs: Extract<AuthLens, { mode: 'as' }>): string {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
const parts = [actAs.uid];
|
|
232
|
+
if (actAs.tenant !== undefined) parts.push(`tenant:${actAs.tenant}`);
|
|
233
|
+
if (actAs.token !== undefined) parts.push(JSON.stringify(actAs.token));
|
|
234
|
+
return parts.join(':');
|
|
233
235
|
}
|
|
234
236
|
|
|
235
237
|
/** Cache key for a real port session; claims are part of authorization identity. */
|
|
@@ -68,8 +68,8 @@ function ensureStorage(ctx: HostCtx): FirebaseStorage {
|
|
|
68
68
|
* `applyServeInit` (`serve-init.ts`), which opens the storage service
|
|
69
69
|
* with `payload.storageRules` BEFORE any op can reach `ensureStorage`/
|
|
70
70
|
* `lensStorage`, so every lens on a served worker enforces the
|
|
71
|
-
* project's storage.rules (or
|
|
72
|
-
* matching
|
|
71
|
+
* project's storage.rules (or fails closed when the project has none,
|
|
72
|
+
* matching Firebase production's no-rules posture). The lens split still
|
|
73
73
|
* matters for embedding/test hosts that open the service directly.
|
|
74
74
|
* - `{ mode: 'admin' }` → the rules-BYPASS handle from
|
|
75
75
|
* `pyric/storage/internal`'s admin plane — same per-sandbox store +
|
|
@@ -213,7 +213,7 @@ export async function handleAuthOp(ctx: HostCtx, port: PortLike, msg: OpMessage)
|
|
|
213
213
|
} catch {
|
|
214
214
|
session = null;
|
|
215
215
|
}
|
|
216
|
-
|
|
216
|
+
setPortSession(ctx, port, session);
|
|
217
217
|
ok(port, msg.id, session ? serializeUser(session.user) : null);
|
|
218
218
|
} catch (e) { fail(port, msg.id, e); }
|
|
219
219
|
break;
|
|
@@ -155,9 +155,12 @@ export {
|
|
|
155
155
|
inMemoryPersistence,
|
|
156
156
|
browserSessionPersistence,
|
|
157
157
|
browserLocalPersistence,
|
|
158
|
-
// Auth lens (Pyric Studio — admin / impersonation / app-session)
|
|
158
|
+
// Auth lens (Pyric Studio & Runtime Chip — admin / impersonation / app-session)
|
|
159
159
|
setLens,
|
|
160
160
|
getLens,
|
|
161
|
+
subscribeLens,
|
|
162
|
+
AUTH_LENS_STORAGE_KEY,
|
|
163
|
+
hydrateLensFromStorage,
|
|
161
164
|
// Storage (Pyric Studio data browse): worker-backed FirebaseStorage mirror
|
|
162
165
|
getStorage,
|
|
163
166
|
ref,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { cleanupPortWithDisconnect, type HostCtx, type PortLike } from './host.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SharedWorker port lifecycle manager.
|
|
5
|
+
*
|
|
6
|
+
* Tracks ports that close before asynchronous worker context initialization
|
|
7
|
+
* finishes, preventing dead-port leaks and ensuring that port cleanup / disconnect
|
|
8
|
+
* operations are drained as soon as the context becomes available.
|
|
9
|
+
*/
|
|
10
|
+
export interface PortLifecycleManager {
|
|
11
|
+
/** Record port closure. Cleans up immediately if context is ready, or defers until resolution. */
|
|
12
|
+
onPortClosed(port: PortLike, currentCtx: HostCtx | null): void;
|
|
13
|
+
/** Drain all deferred closed ports against the newly resolved context. */
|
|
14
|
+
drainClosedPorts(ctx: HostCtx): void;
|
|
15
|
+
/** Check whether a port has already closed before processing queued messages. */
|
|
16
|
+
isPortClosed(port: PortLike): boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createPortLifecycleManager(): PortLifecycleManager {
|
|
20
|
+
const closedPorts = new WeakSet<PortLike>();
|
|
21
|
+
const pendingClosedPorts = new Set<PortLike>();
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
onPortClosed(port: PortLike, currentCtx: HostCtx | null): void {
|
|
25
|
+
closedPorts.add(port);
|
|
26
|
+
if (currentCtx !== null) {
|
|
27
|
+
void cleanupPortWithDisconnect(currentCtx, port).catch(() => undefined);
|
|
28
|
+
} else {
|
|
29
|
+
pendingClosedPorts.add(port);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
drainClosedPorts(ctx: HostCtx): void {
|
|
34
|
+
if (pendingClosedPorts.size === 0) return;
|
|
35
|
+
for (const port of pendingClosedPorts) {
|
|
36
|
+
void cleanupPortWithDisconnect(ctx, port).catch(() => undefined);
|
|
37
|
+
}
|
|
38
|
+
pendingClosedPorts.clear();
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
isPortClosed(port: PortLike): boolean {
|
|
42
|
+
return closedPorts.has(port);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
} from 'pyric/sandbox/internal';
|
|
40
40
|
import type { InitPayload } from '../namespace.js';
|
|
41
41
|
import { setupFirebaseActivityGuard } from './activity-bootstrap.js';
|
|
42
|
+
import { setupAiDiagnosticsRelay } from '../ai-diagnostics-relay.js';
|
|
42
43
|
import { createWorkerDurableBackend, setupServerAuthFlush } from './durable-persistence.js';
|
|
43
44
|
import { ensureAuth, getOrCreateInstanceId, type HostCtx } from './host.js';
|
|
44
45
|
import { buildVerifyFixture, type PyricVerifyFixture } from '../../verify/fixture.js';
|
|
@@ -245,8 +246,7 @@ export function applyServeInit(
|
|
|
245
246
|
// always open storage with no `rules` option, so whichever call opens
|
|
246
247
|
// the service first wins — making this the sanctioned place to
|
|
247
248
|
// configure it. `payload.storageRules` is null when the project has no
|
|
248
|
-
// storage.rules,
|
|
249
|
-
// firestore.rules / no database.rules.
|
|
249
|
+
// storage.rules, so the storage sandbox retains its fail-closed default.
|
|
250
250
|
// The open ALSO claims the project-scoped IDB name
|
|
251
251
|
// (`pyric-storage:<projectKey>`, issue #359) — which is why it now runs
|
|
252
252
|
// unconditionally: a lazy first open from `ensureStorage`/`lensStorage`
|
|
@@ -604,6 +604,13 @@ export async function buildWorkerCtx(bootEnv: WorkerBootEnv): Promise<HostCtx> {
|
|
|
604
604
|
// populate a report without replaying an old warning into a fresh terminal.
|
|
605
605
|
setupFirebaseActivityGuard(ctx, env, payload?.activityToken);
|
|
606
606
|
|
|
607
|
+
// Same seam, AI's diagnostics: relay every broker `request_rejected`,
|
|
608
|
+
// `response_blocked`, and `model_substituted` event to the dev server's
|
|
609
|
+
// denial relay so a headless developer sees why the broker said no, why an
|
|
610
|
+
// answer came back empty, or which model actually answered. Live events
|
|
611
|
+
// only, so it is safe on either side of hydration.
|
|
612
|
+
setupAiDiagnosticsRelay({ subscribe: (listener) => ctx.sandbox.onEvent(listener) }, env.fetch);
|
|
613
|
+
|
|
607
614
|
// Apply rules / seed / authUsers / capture BEFORE any port op runs (so
|
|
608
615
|
// seeded users exist and project rules govern the first write), then mirror
|
|
609
616
|
// auth to the committable server file (`--persist` only).
|