@pyric/cli 0.1.0-alpha.11 → 0.1.0-alpha.13
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/dist/cli/serve.js +4 -4
- package/dist/cli/serve.js.map +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.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +2 -2
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/serve/bundler.d.ts +13 -8
- package/dist/serve/bundler.d.ts.map +1 -1
- package/dist/serve/bundler.js +31 -36
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/docs-ui/docs/_rhythm/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +1 -1
- package/dist/serve/docs-ui/docs/ai-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/api-reference/index.html +2 -2
- package/dist/serve/docs-ui/docs/api-reference.md +1 -1
- package/dist/serve/docs-ui/docs/app-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/auth-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/ai-logic/index.html +44 -22
- package/dist/serve/docs-ui/docs/build/ai-logic.md +69 -21
- package/dist/serve/docs-ui/docs/build/authentication/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/realtime-database/index.html +1 -1
- package/dist/serve/docs-ui/docs/conformance-scores/index.html +1 -1
- package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/database-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/firestore-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +2 -1
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works.md +2 -0
- package/dist/serve/docs-ui/docs/get-started/start-building/index.html +3 -2
- package/dist/serve/docs-ui/docs/get-started/start-building.md +3 -1
- package/dist/serve/docs-ui/docs/index.json +349 -29
- package/dist/serve/docs-ui/docs/messaging-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +28 -0
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status.md +47 -0
- package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +1 -1
- package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +1 -1
- package/dist/serve/docs-ui/docs/overview/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api/index.html +916 -0
- package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api.md +706 -0
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ai-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api/index.html +168 -76
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +156 -73
- package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +11 -8
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api.md +17 -4
- package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-rules-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api/index.html +37 -14
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api.md +28 -8
- package/dist/serve/docs-ui/docs/pyric-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/rules-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
- package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +1 -1
- package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +1 -1
- package/dist/serve/docs-ui/docs/storage-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
- package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
- package/dist/serve/docs-ui/docs/tutorial/index.html +429 -0
- package/dist/serve/docs-ui/docs/tutorial.md +701 -0
- package/dist/serve/docs-ui/llms.txt +3 -1
- package/dist/serve/entries/init.d.ts.map +1 -1
- package/dist/serve/entries/init.js +3 -0
- 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 +20 -5
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/entries/worker-runtime.d.ts +2 -2
- package/dist/serve/entries/worker-runtime.d.ts.map +1 -1
- package/dist/serve/entries/worker-runtime.js +45 -10
- package/dist/serve/entries/worker-runtime.js.map +1 -1
- package/dist/serve/runtime/chip-config.d.ts +19 -0
- package/dist/serve/runtime/chip-config.d.ts.map +1 -0
- package/dist/serve/runtime/chip-config.js +19 -0
- package/dist/serve/runtime/chip-config.js.map +1 -0
- package/dist/serve/runtime/chip-install.d.ts +10 -0
- package/dist/serve/runtime/chip-install.d.ts.map +1 -0
- package/dist/serve/runtime/chip-install.js +15 -0
- package/dist/serve/runtime/chip-install.js.map +1 -0
- package/dist/serve/runtime/chip.d.ts +17 -0
- package/dist/serve/runtime/chip.d.ts.map +1 -0
- package/dist/serve/runtime/chip.js +257 -0
- package/dist/serve/runtime/chip.js.map +1 -0
- package/dist/serve/runtime/manifest.d.ts +22 -0
- package/dist/serve/runtime/manifest.d.ts.map +1 -0
- package/dist/serve/runtime/manifest.js +20 -0
- package/dist/serve/runtime/manifest.js.map +1 -0
- package/dist/serve/runtime/status.d.ts +49 -0
- package/dist/serve/runtime/status.d.ts.map +1 -0
- package/dist/serve/runtime/status.js +164 -0
- package/dist/serve/runtime/status.js.map +1 -0
- package/dist/serve/runtime/worker-connection.d.ts +4 -0
- package/dist/serve/runtime/worker-connection.d.ts.map +1 -0
- package/dist/serve/runtime/worker-connection.js +11 -0
- package/dist/serve/runtime/worker-connection.js.map +1 -0
- package/dist/serve/runtime/worker-generation.d.ts +14 -0
- package/dist/serve/runtime/worker-generation.d.ts.map +1 -0
- package/dist/serve/runtime/worker-generation.js +56 -0
- package/dist/serve/runtime/worker-generation.js.map +1 -0
- package/dist/serve/runtime/worker-replacement.d.ts +18 -0
- package/dist/serve/runtime/worker-replacement.d.ts.map +1 -0
- package/dist/serve/runtime/worker-replacement.js +29 -0
- package/dist/serve/runtime/worker-replacement.js.map +1 -0
- package/dist/serve/standalone-assets.d.ts +2 -2
- package/dist/serve/standalone-assets.d.ts.map +1 -1
- package/dist/serve/standalone-assets.js +1 -1
- package/dist/serve/standalone-assets.js.map +1 -1
- package/dist/serve/studio-ui/assets/{RulesCodeEditor-CxVYcZXw.js → RulesCodeEditor-BDlH-5lp.js} +1 -1
- package/dist/serve/studio-ui/assets/{index-cpSfgQ7H.js → index-Bf9SSE8L.js} +5 -5
- package/dist/serve/studio-ui/assets/{seed-DeuFKi4J.js → seed-D_UjxfOU.js} +1 -1
- package/dist/serve/studio-ui/index.html +1 -1
- package/dist/serve/vite-ai-config.d.ts +25 -0
- package/dist/serve/vite-ai-config.d.ts.map +1 -0
- package/dist/serve/vite-ai-config.js +45 -0
- package/dist/serve/vite-ai-config.js.map +1 -0
- package/dist/serve/vite-plugin.d.ts +17 -36
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +38 -57
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-rules-source.d.ts +8 -0
- package/dist/serve/vite-rules-source.d.ts.map +1 -0
- package/dist/serve/vite-rules-source.js +23 -0
- package/dist/serve/vite-rules-source.js.map +1 -0
- package/dist/serve/vite-worker-runtime.d.ts +20 -0
- package/dist/serve/vite-worker-runtime.d.ts.map +1 -0
- package/dist/serve/vite-worker-runtime.js +25 -0
- package/dist/serve/vite-worker-runtime.js.map +1 -0
- package/dist/serve/worker/client/connection.d.ts +7 -2
- package/dist/serve/worker/client/connection.d.ts.map +1 -1
- package/dist/serve/worker/client/connection.js +13 -16
- package/dist/serve/worker/client/connection.js.map +1 -1
- package/dist/serve/worker/client/core.d.ts +7 -0
- package/dist/serve/worker/client/core.d.ts.map +1 -1
- package/dist/serve/worker/client/core.js +28 -0
- package/dist/serve/worker/client/core.js.map +1 -1
- package/dist/serve/worker/client/runtime-control.d.ts +8 -0
- package/dist/serve/worker/client/runtime-control.d.ts.map +1 -0
- package/dist/serve/worker/client/runtime-control.js +11 -0
- package/dist/serve/worker/client/runtime-control.js.map +1 -0
- package/dist/serve/worker/entry.js +44 -2
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/core.js +1 -1
- package/dist/serve/worker/host/core.js.map +1 -1
- package/dist/serve/worker/host/firestore-writes.d.ts.map +1 -1
- package/dist/serve/worker/host/firestore-writes.js +3 -2
- package/dist/serve/worker/host/firestore-writes.js.map +1 -1
- package/dist/serve/worker/host/studio.js +1 -1
- package/dist/serve/worker/host/studio.js.map +1 -1
- package/dist/serve/worker/host-context.d.ts +1 -1
- package/dist/serve/worker/host-context.d.ts.map +1 -1
- package/dist/serve/worker/index.d.ts +2 -1
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +2 -1
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +15 -1
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js +2 -2
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/serve/worker/retirement.d.ts +21 -0
- package/dist/serve/worker/retirement.d.ts.map +1 -0
- package/dist/serve/worker/retirement.js +97 -0
- package/dist/serve/worker/retirement.js.map +1 -0
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +5 -6
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/vite.d.ts +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js.map +1 -1
- package/package.json +6 -4
- package/src/assurance/.generated/conformance-verdicts.ts +1090 -0
- package/src/assurance/attachment.ts +211 -0
- package/src/assurance/browser.ts +80 -0
- package/src/assurance/campaign.ts +496 -0
- package/src/assurance/capabilities.ts +446 -0
- package/src/assurance/cases.ts +43 -0
- package/src/assurance/index.ts +75 -0
- package/src/assurance/runner.ts +885 -0
- package/src/assurance/tool-names.ts +15 -0
- package/src/assurance/tools.ts +830 -0
- package/src/assurance/types.ts +352 -0
- package/src/assurance/validation.ts +434 -0
- package/src/bridge/client/bridge.ts +550 -0
- package/src/bridge/client/dispatch.ts +137 -0
- package/src/bridge/client.ts +45 -0
- package/src/bridge/protocol.ts +351 -0
- package/src/bridge/server/audit.ts +53 -0
- package/src/bridge/server/bridge.ts +597 -0
- package/src/bridge/server/headless.ts +160 -0
- package/src/bridge/server/json-schema-to-zod.ts +108 -0
- package/src/bridge/server/local-bridge.ts +66 -0
- package/src/bridge/server/logger.ts +50 -0
- package/src/bridge/server/mcp-contract.ts +93 -0
- package/src/bridge/server/mcp.ts +129 -0
- package/src/bridge/server/peer.ts +232 -0
- package/src/bridge/server/standalone.ts +347 -0
- package/src/bridge/server/tool-metadata.ts +99 -0
- package/src/bridge/server.ts +28 -0
- package/src/cli/can-i-use.ts +50 -0
- package/src/cli/cli.test.ts +493 -0
- package/src/cli/database-rules.ts +329 -0
- package/src/cli/dev-runner.ts +282 -0
- package/src/cli/firebase-json.ts +100 -0
- package/src/cli/firestore-indexes.ts +70 -0
- package/src/cli/index.ts +425 -0
- package/src/cli/init.ts +260 -0
- package/src/cli/mcp-proxy.ts +196 -0
- package/src/cli/parse-args.ts +80 -0
- package/src/cli/rules.ts +259 -0
- package/src/cli/scope.ts +67 -0
- package/src/cli/serve.ts +996 -0
- package/src/cli/service-commands.ts +73 -0
- package/src/cli/snapshot.ts +164 -0
- package/src/cli/storage-rules.ts +172 -0
- package/src/cli/verify.ts +416 -0
- package/src/conformance/.generated/can-i-use-browser.ts +113 -0
- package/src/conformance/.generated/can-i-use.ts +117 -0
- package/src/conformance/.generated/conformance-docs.ts +14 -0
- package/src/conformance/browser.ts +24 -0
- package/src/conformance/can-i-use-tool.ts +51 -0
- package/src/conformance/can-i-use.ts +18 -0
- package/src/conformance/docs.ts +8 -0
- package/src/conformance/index.ts +20 -0
- package/src/conformance/tools.ts +16 -0
- package/src/credentials/core/memoize-ttl.ts +142 -0
- package/src/credentials/core/types.ts +10 -0
- package/src/credentials/node/from-adc.ts +96 -0
- package/src/credentials/node/from-service-account.ts +133 -0
- package/src/credentials/node/index.ts +6 -0
- package/src/discover/concurrency.ts +127 -0
- package/src/discover/crawler-adapter.ts +142 -0
- package/src/discover/crawler.ts +1127 -0
- package/src/discover/credential-free.ts +27 -0
- package/src/discover/findCollectionGroup.ts +131 -0
- package/src/discover/firestore-source.ts +59 -0
- package/src/discover/index.ts +5 -0
- package/src/discover/merge.ts +523 -0
- package/src/discover/session.ts +402 -0
- package/src/discover/tools.ts +201 -0
- package/src/discover/types.ts +187 -0
- package/src/discover/wire.ts +324 -0
- package/src/functions-rtdb/child.ts +382 -0
- package/src/functions-rtdb/delivery.ts +7 -0
- package/src/functions-rtdb/discovery.ts +136 -0
- package/src/functions-rtdb/event.ts +64 -0
- package/src/functions-rtdb/execution.ts +111 -0
- package/src/functions-rtdb/in-memory-delivery.ts +40 -0
- package/src/functions-rtdb/project.ts +74 -0
- package/src/functions-rtdb/projection.ts +104 -0
- package/src/functions-rtdb/reference-pattern.ts +20 -0
- package/src/functions-rtdb/remote-delivery.ts +23 -0
- package/src/pkg-version.ts +49 -0
- package/src/register/esm-exports.ts +63 -0
- package/src/register/hooks.ts +30 -0
- package/src/register/index.ts +150 -0
- package/src/register/mapping.ts +33 -0
- package/src/remote/index.ts +1050 -0
- package/src/rtdb/crawl-snapshot.ts +118 -0
- package/src/rtdb/inspection.ts +137 -0
- package/src/rtdb/load-rules-document.ts +56 -0
- package/src/rtdb/rules-generation-tool.ts +38 -0
- package/src/rtdb/rules-json.ts +29 -0
- package/src/serve/activity-guard.ts +29 -0
- package/src/serve/activity-route.ts +164 -0
- package/src/serve/activity-warning.ts +26 -0
- package/src/serve/bridge-mount.ts +200 -0
- package/src/serve/bundler.ts +519 -0
- package/src/serve/capture-store.ts +65 -0
- package/src/serve/discovery.ts +199 -0
- package/src/serve/entries/ai.ts +292 -0
- package/src/serve/entries/app-backend.ts +4 -0
- package/src/serve/entries/app-client.ts +26 -0
- package/src/serve/entries/app-session-store.ts +47 -0
- package/src/serve/entries/app.ts +11 -0
- package/src/serve/entries/auth-helper-core.ts +181 -0
- package/src/serve/entries/auth-helper-dom.ts +134 -0
- package/src/serve/entries/auth-helper-runtime.ts +20 -0
- package/src/serve/entries/auth.ts +255 -0
- package/src/serve/entries/bridge-url.ts +31 -0
- package/src/serve/entries/database.ts +129 -0
- package/src/serve/entries/firestore.ts +232 -0
- package/src/serve/entries/init.ts +49 -0
- package/src/serve/entries/keepalive.ts +46 -0
- package/src/serve/entries/messaging-sw.ts +75 -0
- package/src/serve/entries/messaging.ts +96 -0
- package/src/serve/entries/runtime.ts +556 -0
- package/src/serve/entries/session-store.ts +97 -0
- package/src/serve/entries/storage.ts +92 -0
- package/src/serve/entries/tab-sync-wiring.ts +274 -0
- package/src/serve/entries/worker-runtime.ts +135 -0
- package/src/serve/init-payload.ts +42 -0
- package/src/serve/namespace.ts +675 -0
- package/src/serve/open-browser.ts +68 -0
- package/src/serve/rules.ts +272 -0
- package/src/serve/runtime/chip-config.ts +30 -0
- package/src/serve/runtime/chip-install.ts +27 -0
- package/src/serve/runtime/chip.ts +282 -0
- package/src/serve/runtime/manifest.ts +37 -0
- package/src/serve/runtime/status.ts +216 -0
- package/src/serve/runtime/worker-connection.ts +14 -0
- package/src/serve/runtime/worker-generation.ts +75 -0
- package/src/serve/runtime/worker-replacement.ts +42 -0
- package/src/serve/sandbox-marker.ts +31 -0
- package/src/serve/server.ts +428 -0
- package/src/serve/standalone-assets.ts +180 -0
- package/src/serve/state-store.ts +166 -0
- package/src/serve/studio/disk-project-store.ts +185 -0
- package/src/serve/studio/disk-workspace.ts +162 -0
- package/src/serve/studio/index.ts +20 -0
- package/src/serve/studio/routes.ts +237 -0
- package/src/serve/studio/store-types.ts +48 -0
- package/src/serve/studio/studio-storage.test.ts +289 -0
- package/src/serve/vite-ai-config.ts +77 -0
- package/src/serve/vite-plugin.ts +1075 -0
- package/src/serve/vite-rules-source.ts +28 -0
- package/src/serve/vite-worker-runtime.ts +51 -0
- package/src/serve/worker/activity-bootstrap.ts +24 -0
- package/src/serve/worker/client/admin-firestore.ts +38 -0
- package/src/serve/worker/client/ai.ts +124 -0
- package/src/serve/worker/client/auth.ts +489 -0
- package/src/serve/worker/client/connection.ts +227 -0
- package/src/serve/worker/client/core.ts +384 -0
- package/src/serve/worker/client/disconnect.ts +45 -0
- package/src/serve/worker/client/firestore-reads.ts +181 -0
- package/src/serve/worker/client/firestore-refs.ts +226 -0
- package/src/serve/worker/client/firestore-writes.ts +232 -0
- package/src/serve/worker/client/handles.ts +91 -0
- package/src/serve/worker/client/messaging.ts +119 -0
- package/src/serve/worker/client/presence.ts +174 -0
- package/src/serve/worker/client/rtdb.ts +311 -0
- package/src/serve/worker/client/rules.ts +63 -0
- package/src/serve/worker/client/runtime-control.ts +22 -0
- package/src/serve/worker/client/service-worker-connection.ts +59 -0
- package/src/serve/worker/client/snapshots.ts +86 -0
- package/src/serve/worker/client/storage.ts +195 -0
- package/src/serve/worker/client/studio.ts +88 -0
- package/src/serve/worker/client.ts +57 -0
- package/src/serve/worker/durable-persistence.ts +137 -0
- package/src/serve/worker/entry.ts +223 -0
- package/src/serve/worker/host/admin-firestore.ts +88 -0
- package/src/serve/worker/host/connection.ts +179 -0
- package/src/serve/worker/host/core.ts +387 -0
- package/src/serve/worker/host/dispatch.ts +316 -0
- package/src/serve/worker/host/firestore-reads.ts +117 -0
- package/src/serve/worker/host/firestore-writes.ts +456 -0
- package/src/serve/worker/host/presence.ts +312 -0
- package/src/serve/worker/host/rtdb.ts +136 -0
- package/src/serve/worker/host/rules.ts +128 -0
- package/src/serve/worker/host/storage.ts +312 -0
- package/src/serve/worker/host/studio.ts +75 -0
- package/src/serve/worker/host/subscriptions.ts +238 -0
- package/src/serve/worker/host-ai.ts +165 -0
- package/src/serve/worker/host-auth.ts +469 -0
- package/src/serve/worker/host-context.ts +273 -0
- package/src/serve/worker/host-events.ts +94 -0
- package/src/serve/worker/host-messaging.ts +240 -0
- package/src/serve/worker/host.ts +47 -0
- package/src/serve/worker/index.ts +196 -0
- package/src/serve/worker/presence-timing.ts +15 -0
- package/src/serve/worker/protocol.ts +1124 -0
- package/src/serve/worker/retirement.ts +125 -0
- package/src/serve/worker/serve-init.ts +605 -0
- package/src/serve/worker/service-worker-channel.ts +33 -0
- package/src/serve/worker/service-worker-relay.ts +86 -0
- package/src/serve/writer-lock.ts +53 -0
- package/src/verify/cases.ts +233 -0
- package/src/verify/fixture.ts +258 -0
- package/src/verify/index.ts +519 -0
- package/src/verify/tools.ts +108 -0
- package/src/version/compat-target.ts +17 -0
- package/src/vite.ts +18 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api/index.html +0 -31
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +0 -29
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, resolve as resolvePath } from 'node:path';
|
|
3
|
+
import {
|
|
4
|
+
ExtractFirestoreIndexesHandler,
|
|
5
|
+
type ExtractIndexesOptions,
|
|
6
|
+
} from 'pyric/rules/internal/extract';
|
|
7
|
+
import type { ParsedArgs } from './parse-args.js';
|
|
8
|
+
import { readFirebaseJson, type FirebaseJson } from './firebase-json.js';
|
|
9
|
+
|
|
10
|
+
type ExtractResult = ReturnType<ExtractFirestoreIndexesHandler['execute']>;
|
|
11
|
+
|
|
12
|
+
export interface FirestoreIndexesDeps {
|
|
13
|
+
extract?: (options: ExtractIndexesOptions) => ExtractResult;
|
|
14
|
+
readFirebaseJson?: (cwd: string) => Promise<FirebaseJson>;
|
|
15
|
+
writeFile?: typeof writeFile;
|
|
16
|
+
mkdir?: typeof mkdir;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
stdout?: { write(s: string): void };
|
|
19
|
+
stderr?: { write(s: string): void };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function runFirestoreIndexesGenerate(
|
|
23
|
+
parsed: ParsedArgs,
|
|
24
|
+
deps: FirestoreIndexesDeps = {},
|
|
25
|
+
): Promise<number> {
|
|
26
|
+
const out = deps.stdout ?? process.stdout;
|
|
27
|
+
const err = deps.stderr ?? process.stderr;
|
|
28
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
29
|
+
if (parsed.positional.length === 0) {
|
|
30
|
+
err.write(
|
|
31
|
+
'pyric firestore indexes generate: missing source path. Usage: pyric firestore indexes generate <path...> [--out <path>]\n',
|
|
32
|
+
);
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const extract =
|
|
37
|
+
deps.extract ??
|
|
38
|
+
((options: ExtractIndexesOptions) => new ExtractFirestoreIndexesHandler().execute(options));
|
|
39
|
+
const result = extract({ paths: parsed.positional.map((path) => resolvePath(cwd, path)) });
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
err.write(`pyric firestore indexes generate: ${result.error.message}\n`);
|
|
42
|
+
return 2;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const outFlag = parsed.flags.get('out');
|
|
46
|
+
let configuredPath: string | undefined;
|
|
47
|
+
if (typeof outFlag !== 'string') {
|
|
48
|
+
try {
|
|
49
|
+
configuredPath = (await (deps.readFirebaseJson ?? readFirebaseJson)(cwd)).firestore?.indexes;
|
|
50
|
+
} catch {
|
|
51
|
+
configuredPath = undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const outputPath = resolvePath(
|
|
55
|
+
cwd,
|
|
56
|
+
typeof outFlag === 'string' ? outFlag : configuredPath ?? 'firestore.indexes.json',
|
|
57
|
+
);
|
|
58
|
+
await (deps.mkdir ?? mkdir)(dirname(outputPath), { recursive: true });
|
|
59
|
+
await (deps.writeFile ?? writeFile)(
|
|
60
|
+
outputPath,
|
|
61
|
+
`${JSON.stringify(result.data.config, null, 2)}\n`,
|
|
62
|
+
'utf-8',
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
out.write(`pyric firestore indexes generate: wrote ${outputPath}\n`);
|
|
66
|
+
for (const warning of result.data.warnings) {
|
|
67
|
+
err.write(`pyric firestore indexes generate: warning: ${warning.file}: ${warning.message}\n`);
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `pyric` CLI — front door to the bridge + project tooling.
|
|
4
|
+
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* pyric bridge [--port N] [--project ID]
|
|
7
|
+
* pyric dev [--port N] [--host H] [--no-cache] [--bridge] [--ui] [--seed FILE] [--no-watch] [--no-open] [--no-capture] [--no-run] [--json] [--persist] [--fresh] [-- <cmd>]
|
|
8
|
+
* pyric init [dir] [--template web|node] [--name N] [--force] [--json]
|
|
9
|
+
* pyric vendor [dir] [--json]
|
|
10
|
+
* pyric snapshot [--out FILE] [--port N] [--force] [--json] [--include-passwords]
|
|
11
|
+
* pyric mcp
|
|
12
|
+
* pyric firestore rules lint <path>
|
|
13
|
+
* pyric firestore rules validate <path>
|
|
14
|
+
* pyric firestore rules simulate [--stdin]
|
|
15
|
+
* pyric firestore rules resolve <path> [--out <path>]
|
|
16
|
+
* pyric firestore indexes generate <path...> [--out <path>]
|
|
17
|
+
* pyric storage rules lint <path>
|
|
18
|
+
* pyric storage rules simulate [--stdin]
|
|
19
|
+
* pyric database rules lint <path>
|
|
20
|
+
* pyric database rules validate <path>
|
|
21
|
+
* pyric database rules simulate [--stdin]
|
|
22
|
+
* pyric database rules generate [--config <path>] [--out <path>]
|
|
23
|
+
* pyric --help
|
|
24
|
+
* pyric --version
|
|
25
|
+
*
|
|
26
|
+
* Env vars:
|
|
27
|
+
* PYRIC_PORT — bridge port (default 5174)
|
|
28
|
+
* PYRIC_PROJECT — project label for bridge health and audit output
|
|
29
|
+
* PYRIC_VERBOSE — set to 1 for per-tool-call logging
|
|
30
|
+
* FIREBASE_SA_BASE64 — base64-encoded service-account JSON (Rules Test API verify)
|
|
31
|
+
* GOOGLE_APPLICATION_CREDENTIALS — path to service-account JSON (Rules Test API verify)
|
|
32
|
+
*
|
|
33
|
+
* Exit codes:
|
|
34
|
+
* 0 success
|
|
35
|
+
* 1 usage error
|
|
36
|
+
* 2 runtime error
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import { realpathSync } from 'node:fs';
|
|
40
|
+
import { fileURLToPath } from 'node:url';
|
|
41
|
+
import { parseArgs, type ParsedArgs } from './parse-args.js';
|
|
42
|
+
import { runInit, runVendor } from './init.js';
|
|
43
|
+
import { runSnapshot } from './snapshot.js';
|
|
44
|
+
import { runVerify } from './verify.js';
|
|
45
|
+
import { runMcpProxy } from './mcp-proxy.js';
|
|
46
|
+
import { pyricVersion } from '../serve/standalone-assets.js';
|
|
47
|
+
import { cliVersion } from '../pkg-version.js';
|
|
48
|
+
import { FIREBASE_TESTED_AGAINST } from '../version/compat-target.js';
|
|
49
|
+
import { dispatchServiceCommand } from './service-commands.js';
|
|
50
|
+
|
|
51
|
+
// The standalone binary bakes the real `pyric` version onto the embedded-assets
|
|
52
|
+
// global; the npm bin has no such global and falls back to '0.0.0'.
|
|
53
|
+
const VERSION = pyricVersion();
|
|
54
|
+
|
|
55
|
+
function printUsage(): void {
|
|
56
|
+
process.stdout.write(`pyric ${VERSION}
|
|
57
|
+
Firebase for agents — bridge an in-browser pyric sandbox to external MCP
|
|
58
|
+
clients (Claude Code, Cursor, ...).
|
|
59
|
+
|
|
60
|
+
USAGE
|
|
61
|
+
pyric bridge [flags]
|
|
62
|
+
pyric dev [flags] [-- <cmd>]
|
|
63
|
+
pyric init [dir] [--template=web|node]
|
|
64
|
+
pyric snapshot [--out=FILE]
|
|
65
|
+
pyric verify [fixture|dir] [--engine sandbox|rules-test-api|both]
|
|
66
|
+
pyric can-i-use <feature> [--json]
|
|
67
|
+
pyric verify cases [fixture] [--service firestore] [--out FILE]
|
|
68
|
+
pyric firestore rules lint <path>
|
|
69
|
+
pyric firestore rules validate <path>
|
|
70
|
+
pyric firestore rules simulate [--stdin]
|
|
71
|
+
pyric firestore rules resolve <path> [--out <path>]
|
|
72
|
+
pyric firestore indexes generate <path...> [--out <path>]
|
|
73
|
+
pyric storage rules lint <path>
|
|
74
|
+
pyric storage rules simulate [--stdin]
|
|
75
|
+
pyric database rules lint <path>
|
|
76
|
+
pyric database rules validate <path>
|
|
77
|
+
pyric database rules simulate [--stdin]
|
|
78
|
+
pyric database rules generate [--config <path>] [--out <path>]
|
|
79
|
+
pyric --help
|
|
80
|
+
pyric --version
|
|
81
|
+
|
|
82
|
+
COMMANDS
|
|
83
|
+
bridge Start the HTTP+WebSocket bridge external MCP clients point at.
|
|
84
|
+
dev Serve the app locally with the pyric sandbox standing in for
|
|
85
|
+
Firebase — unmodified firebase/* imports hit an in-page sandbox
|
|
86
|
+
with your firestore.rules deployed. Also runs your own dev
|
|
87
|
+
command (\`-- <cmd>\`, else the package.json \`dev\` script) with
|
|
88
|
+
unchanged firebase-admin/firebase imports routed to the
|
|
89
|
+
sandbox (PYRIC_SANDBOX + \`--import @pyric/cli/register\`). A
|
|
90
|
+
firebase.json Functions source is discovered automatically;
|
|
91
|
+
supported RTDB onValueCreated exports run in isolated Node.
|
|
92
|
+
init [dir] Scaffold a pyric project. --template=web (default; Vite app
|
|
93
|
+
on \`@pyric/cli/vite\`), static (\`pyric dev\`), or node.
|
|
94
|
+
--name=NAME --force (overwrite scaffold files) --json (machine
|
|
95
|
+
output on stdout). Never prompts; rerunning is safe.
|
|
96
|
+
Greenfield shortcut: \`npm create pyric [dir]\`.
|
|
97
|
+
vendor [dir] Retrofit: vendor pyric + @pyric/cli into an existing
|
|
98
|
+
project (lay file: tarballs into vendor/ + merge their
|
|
99
|
+
deps into package.json). Scaffolds nothing. Then run
|
|
100
|
+
bun install. Standalone binary only.
|
|
101
|
+
mcp Stdio MCP server for editors (Cursor / Claude /
|
|
102
|
+
Antigravity). Hosts a headless in-process sandbox,
|
|
103
|
+
or attaches to a running \`pyric dev --bridge\`
|
|
104
|
+
(found via .pyric/serve.json) for shared-live Studio.
|
|
105
|
+
snapshot [--out=FILE] Promote lived sandbox state (live dev --persist, else
|
|
106
|
+
.pyric/state/state.json) to a committable fixture that
|
|
107
|
+
\`pyric dev --seed FILE\` re-serves. Passwords are redacted
|
|
108
|
+
by default (--include-passwords keeps them). --port, --force, --json.
|
|
109
|
+
verify [fixture|dir] Replay a captured sandbox session against candidate rules
|
|
110
|
+
for the Firestore/RTDB services present in the fixture.
|
|
111
|
+
No arg replays the latest \`pyric dev\` capture
|
|
112
|
+
(.pyric/last-session.json). --service filters services.
|
|
113
|
+
--engine sandbox (default), rules-test-api, or both.
|
|
114
|
+
Hosted Rules Test API verification is Firestore-only
|
|
115
|
+
and uses --project plus the configured Google credentials.
|
|
116
|
+
--rules service=path overrides firebase.json resolution
|
|
117
|
+
(repeat for mixed captures). --json. Exit 1 on divergence.
|
|
118
|
+
can-i-use <feature> Report Pyric availability, behavior fidelity, and assurance
|
|
119
|
+
eligibility from the canonical conformance model. A surface
|
|
120
|
+
prefix such as firestore-rules/getAfter disambiguates names.
|
|
121
|
+
Exact and fuzzy queries use the same model as MCP. --json.
|
|
122
|
+
verify cases [fixture] Derive Firestore Rules Test API cases from a captured
|
|
123
|
+
fixture and print JSON, or write with --out FILE.
|
|
124
|
+
firestore rules lint Run the Firestore rules linter against a file.
|
|
125
|
+
firestore rules validate Validate Firestore rules structure against a file.
|
|
126
|
+
firestore rules simulate Run the local Firestore rules simulator.
|
|
127
|
+
firestore rules resolve Resolve Firestore 2+modules imports to one ruleset.
|
|
128
|
+
firestore indexes generate Generate firestore.indexes.json from application source.
|
|
129
|
+
storage rules lint Check Storage rules syntax locally.
|
|
130
|
+
storage rules simulate Run the local Storage rules evaluator.
|
|
131
|
+
database rules lint Run the Realtime Database rules expression linter.
|
|
132
|
+
database rules validate Validate Realtime Database rules expressions.
|
|
133
|
+
database rules simulate Run the local Realtime Database rules simulator.
|
|
134
|
+
database rules generate Compile a constraints module to database.rules.json.
|
|
135
|
+
CORE FLAGS (dev)
|
|
136
|
+
--port Port to serve on. Default 3473 — "FIRE" on a phone keypad (scans forward when taken;
|
|
137
|
+
macOS AirPlay squats 5000).
|
|
138
|
+
--host Host to bind. Default localhost.
|
|
139
|
+
--no-cache Rebuild the served pyric SDK bundles (skip ~/.pyric/serve-cache).
|
|
140
|
+
--only hosting Accepted for firebase-serve parity (hosting is all v1 serves).
|
|
141
|
+
--bridge Also mount the MCP bridge on the serve origin — agents point
|
|
142
|
+
at http://<host>:<port>/__pyric/mcp and drive the sandbox
|
|
143
|
+
living in the served page. --project labels health/audit.
|
|
144
|
+
--ui Also serve the Pyric Studio app at <url>/__pyric/ui/ (and
|
|
145
|
+
mount its disk-backed workspace + project data routes).
|
|
146
|
+
Auto-opens Studio instead of the served page. Needs a full
|
|
147
|
+
build so the app assets are present.
|
|
148
|
+
--seed FILE JSON map of "collection/doc" → fields, loaded admin-style.
|
|
149
|
+
Also accepts a pyric state file (from \`pyric snapshot\`,
|
|
150
|
+
detected by its version key) — seeds docs + auth users.
|
|
151
|
+
into the page sandbox before app code runs.
|
|
152
|
+
--no-watch Disable firestore.rules hot-reload (on by default).
|
|
153
|
+
--no-open Don't auto-open the browser. dev opens the served page
|
|
154
|
+
by default (the sandbox is browser-resident); auto-open
|
|
155
|
+
is already suppressed under --json, no TTY, and CI.
|
|
156
|
+
--no-capture Don't write the session capture. dev writes
|
|
157
|
+
.pyric/last-session.json by default so \`pyric verify\`
|
|
158
|
+
can replay your session; --no-capture disables it.
|
|
159
|
+
--allowed-host H Allow an extra Host header past the DNS-rebinding guard
|
|
160
|
+
(comma-separated; localhost/127.0.0.1 always allowed).
|
|
161
|
+
--persist Persist sandbox state (docs + auth users) to
|
|
162
|
+
.pyric/state/state.json — survives reloads and dev
|
|
163
|
+
restarts. Once a state file exists it wins; --seed
|
|
164
|
+
applies only on the first (state-less) run. Ephemeral
|
|
165
|
+
is the default.
|
|
166
|
+
--fresh Requires --persist: discard the existing state file and
|
|
167
|
+
re-seed from scratch (escape hatch when you've edited
|
|
168
|
+
seed.json). Without --persist, --fresh errors — there is
|
|
169
|
+
no state file to discard. Half-reset warning: a browser
|
|
170
|
+
tab that already has sandbox data in IndexedDB keeps it
|
|
171
|
+
and writes it back to the new file; also clear the
|
|
172
|
+
browser store (Studio → Settings → Reset, or an
|
|
173
|
+
incognito window) for a full reset.
|
|
174
|
+
-- <cmd> Run <cmd> once the host is up, with PYRIC_SANDBOX set and
|
|
175
|
+
NODE_OPTIONS extended with --import @pyric/cli/register
|
|
176
|
+
so firebase-admin/firebase resolve to the sandbox. When
|
|
177
|
+
omitted, the package.json \`dev\` script runs (via the
|
|
178
|
+
detected package manager); no script → host-only.
|
|
179
|
+
--no-run Don't run the project's dev command (for users with their
|
|
180
|
+
own process manager). A declared Functions source still
|
|
181
|
+
runs. --json skips the dev command unless a \`-- <cmd>\`
|
|
182
|
+
is given explicitly.
|
|
183
|
+
--json One machine-readable line on stdout ({url, port, mcpUrl,
|
|
184
|
+
rulesHash, persist, restoredDocs, restoredUsers}); the
|
|
185
|
+
banner moves to stderr. Readiness probe:
|
|
186
|
+
GET <url>/__pyric/init.json → 200 (live rules hash).
|
|
187
|
+
|
|
188
|
+
CORE FLAGS (bridge)
|
|
189
|
+
--port Port to bind on 127.0.0.1. Default 5174. Env: PYRIC_PORT.
|
|
190
|
+
--project Project label surfaced in /health + audit output.
|
|
191
|
+
Env: PYRIC_PROJECT.
|
|
192
|
+
|
|
193
|
+
CREDENTIALS
|
|
194
|
+
Rules Test API verification resolves existing Google credentials:
|
|
195
|
+
1. FIREBASE_SA_BASE64 base64-encoded service-account JSON (CI)
|
|
196
|
+
2. GOOGLE_APPLICATION_CREDENTIALS path to a service-account JSON file
|
|
197
|
+
3. ADC \`gcloud auth application-default login\` (ambient)
|
|
198
|
+
PYRIC_PROJECT / --project Firebase project id for Rules Test API verification
|
|
199
|
+
`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function printVersion(): void {
|
|
203
|
+
process.stdout.write(
|
|
204
|
+
`@pyric/cli ${cliVersion()}\n` +
|
|
205
|
+
`Firebase ${FIREBASE_TESTED_AGAINST} (conformance-tested against this release)\n`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function runBridge(parsed: ParsedArgs): Promise<number> {
|
|
210
|
+
const removedFlags = [
|
|
211
|
+
'mode',
|
|
212
|
+
'auto-approve',
|
|
213
|
+
'require-confirm',
|
|
214
|
+
'require-confirm-all',
|
|
215
|
+
'confirm-timeout',
|
|
216
|
+
'non-interactive',
|
|
217
|
+
];
|
|
218
|
+
for (const flag of removedFlags) {
|
|
219
|
+
if (parsed.flags.has(flag)) {
|
|
220
|
+
process.stderr.write(`pyric: unknown option '--${flag}' for pyric bridge.\n`);
|
|
221
|
+
return 1;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const flagPort = parsed.flags.get('port');
|
|
226
|
+
const port =
|
|
227
|
+
typeof flagPort === 'string'
|
|
228
|
+
? Number(flagPort)
|
|
229
|
+
: process.env.PYRIC_PORT
|
|
230
|
+
? Number(process.env.PYRIC_PORT)
|
|
231
|
+
: undefined;
|
|
232
|
+
if (port !== undefined && (!Number.isFinite(port) || port < 1 || port > 65535)) {
|
|
233
|
+
process.stderr.write(`pyric: invalid --port '${flagPort ?? process.env.PYRIC_PORT}'.\n`);
|
|
234
|
+
return 1;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const flagProject = parsed.flags.get('project');
|
|
238
|
+
const project =
|
|
239
|
+
typeof flagProject === 'string' ? flagProject : process.env.PYRIC_PROJECT ?? undefined;
|
|
240
|
+
|
|
241
|
+
let handle;
|
|
242
|
+
try {
|
|
243
|
+
const { startServer } = await import('@pyric/cli/bridge');
|
|
244
|
+
handle = await startServer({
|
|
245
|
+
port,
|
|
246
|
+
project,
|
|
247
|
+
});
|
|
248
|
+
} catch (err) {
|
|
249
|
+
process.stderr.write(
|
|
250
|
+
`pyric: failed to start bridge: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
251
|
+
);
|
|
252
|
+
return 2;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Graceful shutdown. Idempotent because:
|
|
256
|
+
// 1. npx forwards SIGINT to its child AND the terminal sends SIGINT
|
|
257
|
+
// to the process group, so one Ctrl-C delivers SIGINT TWICE to
|
|
258
|
+
// this process — without a guard, the handler ran twice and
|
|
259
|
+
// printed everything twice.
|
|
260
|
+
// 2. An impatient user mashing Ctrl-C expects "now I mean it" to
|
|
261
|
+
// force-exit, not enqueue more clean-shutdowns.
|
|
262
|
+
let shuttingDown = false;
|
|
263
|
+
const stop = async (signal: NodeJS.Signals) => {
|
|
264
|
+
if (shuttingDown) {
|
|
265
|
+
process.stderr.write('pyric: force-exiting\n');
|
|
266
|
+
process.exit(130);
|
|
267
|
+
}
|
|
268
|
+
shuttingDown = true;
|
|
269
|
+
process.stdout.write(`\npyric: received ${signal}, stopping bridge...\n`);
|
|
270
|
+
// Hard safety net: clean shutdown is ~instant once sockets are
|
|
271
|
+
// forcibly closed (see handle.stop in standalone.ts). If something
|
|
272
|
+
// hangs anyway — peer pre-handshake, MCP transport in mid-write —
|
|
273
|
+
// don't make the user wait forever.
|
|
274
|
+
const forceExitTimer = setTimeout(() => {
|
|
275
|
+
process.stderr.write('pyric: shutdown taking longer than expected, force-exiting\n');
|
|
276
|
+
process.exit(130);
|
|
277
|
+
}, 2000);
|
|
278
|
+
forceExitTimer.unref();
|
|
279
|
+
try {
|
|
280
|
+
await handle.stop();
|
|
281
|
+
} catch (err) {
|
|
282
|
+
process.stderr.write(
|
|
283
|
+
`pyric: error during shutdown: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
clearTimeout(forceExitTimer);
|
|
287
|
+
process.exit(signal === 'SIGINT' ? 130 : 0);
|
|
288
|
+
};
|
|
289
|
+
process.on('SIGINT', () => void stop('SIGINT'));
|
|
290
|
+
process.on('SIGTERM', () => void stop('SIGTERM'));
|
|
291
|
+
|
|
292
|
+
process.stdout.write(
|
|
293
|
+
`\npyric bridge ${VERSION} ready\n` +
|
|
294
|
+
` target: sandbox\n` +
|
|
295
|
+
` project: ${handle.bridge.project}\n` +
|
|
296
|
+
` health: ${handle.url}/health\n` +
|
|
297
|
+
` mcp: ${handle.url}/mcp\n` +
|
|
298
|
+
` sandbox: ${handle.url.replace('http://', 'ws://')}/sandbox\n` +
|
|
299
|
+
(handle.auditLogPath ? ` audit: ${handle.auditLogPath}\n` : '') +
|
|
300
|
+
`\nRegister with Claude Code:\n` +
|
|
301
|
+
` claude mcp add --transport http pyric ${handle.url}/mcp --scope project\n` +
|
|
302
|
+
`\nBridge will log peer connect/disconnect to stderr. Set PYRIC_VERBOSE=1 for per-tool-call logs.\n` +
|
|
303
|
+
`Press Ctrl-C to stop.\n`,
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
// Keep the event loop alive.
|
|
307
|
+
return await new Promise<number>(() => {});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Dispatch a parsed CLI invocation to its subcommand handler.
|
|
312
|
+
* Exported so the test suite can drive the dispatcher directly
|
|
313
|
+
* without spawning a child process. `process.exit` is not called
|
|
314
|
+
* here — the caller (the top-level `main()` below) does that.
|
|
315
|
+
*/
|
|
316
|
+
export async function dispatch(parsed: ParsedArgs): Promise<number> {
|
|
317
|
+
if (parsed.flags.get('help') || parsed.flags.get('h')) {
|
|
318
|
+
printUsage();
|
|
319
|
+
return 0;
|
|
320
|
+
}
|
|
321
|
+
if (parsed.flags.get('version') || parsed.flags.get('v')) {
|
|
322
|
+
printVersion();
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const serviceCommand = await dispatchServiceCommand(parsed);
|
|
327
|
+
if (serviceCommand !== null) return serviceCommand;
|
|
328
|
+
|
|
329
|
+
switch (parsed.subcommand) {
|
|
330
|
+
case null:
|
|
331
|
+
case undefined:
|
|
332
|
+
printUsage();
|
|
333
|
+
return parsed.subcommand === null ? 0 : 1;
|
|
334
|
+
case 'bridge':
|
|
335
|
+
return await runBridge(parsed);
|
|
336
|
+
case 'dev':
|
|
337
|
+
const { runServe } = await import('./serve.js');
|
|
338
|
+
return runServe(parsed);
|
|
339
|
+
case 'snapshot':
|
|
340
|
+
return await runSnapshot(parsed);
|
|
341
|
+
case 'verify':
|
|
342
|
+
return await runVerify(parsed);
|
|
343
|
+
case 'can-i-use':
|
|
344
|
+
const { runCanIUse } = await import('./can-i-use.js');
|
|
345
|
+
return runCanIUse(parsed);
|
|
346
|
+
case 'mcp':
|
|
347
|
+
return await runMcpProxy(parsed);
|
|
348
|
+
case 'init':
|
|
349
|
+
return await runInit(parsed);
|
|
350
|
+
case 'vendor':
|
|
351
|
+
return await runVendor(parsed);
|
|
352
|
+
default:
|
|
353
|
+
process.stderr.write(`pyric: unknown command '${parsed.subcommand}'.\n\n`);
|
|
354
|
+
printUsage();
|
|
355
|
+
return 1;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function main(): Promise<number> {
|
|
360
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
361
|
+
return dispatch(parsed);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Re-export parseArgs so the bin script + tests can share the parser.
|
|
365
|
+
export { parseArgs } from './parse-args.js';
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* True when this module is the executable entry rather than an import.
|
|
369
|
+
*
|
|
370
|
+
* Bun identifies source and compiled entry points with `import.meta.main`.
|
|
371
|
+
* Node does not, so compare real paths there: resolving both sides preserves
|
|
372
|
+
* npm's `node_modules/.bin/pyric` symlink behavior that a textual path check
|
|
373
|
+
* previously broke.
|
|
374
|
+
*/
|
|
375
|
+
export function isDirectRun(): boolean {
|
|
376
|
+
if (import.meta.main) return true;
|
|
377
|
+
const argvEntry = process.argv[1];
|
|
378
|
+
if (!argvEntry) return false;
|
|
379
|
+
try {
|
|
380
|
+
return realpathSync(argvEntry) === realpathSync(fileURLToPath(import.meta.url));
|
|
381
|
+
} catch {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Explicit executable entry: parse argv, dispatch, flush, exit.
|
|
388
|
+
*
|
|
389
|
+
* The compiled standalone binary calls this from its generated entry
|
|
390
|
+
* (scripts/compile.ts) instead of relying on {@link isDirectRun}: inside a
|
|
391
|
+
* `bun build --compile` binary this module is an import (import.meta.main is
|
|
392
|
+
* false) and `process.argv[1]` is the user's first argument, not a path — so
|
|
393
|
+
* direct-run detection is structurally false there and the binary would
|
|
394
|
+
* otherwise exit 0 silently.
|
|
395
|
+
*/
|
|
396
|
+
export function runDirect(): void {
|
|
397
|
+
main().then(
|
|
398
|
+
(code) => exitAfterFlush(code),
|
|
399
|
+
(err) => {
|
|
400
|
+
process.stderr.write(
|
|
401
|
+
`pyric: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`,
|
|
402
|
+
);
|
|
403
|
+
exitAfterFlush(2);
|
|
404
|
+
},
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (isDirectRun()) runDirect();
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Drain stdout + stderr before exiting. `process.exit()` does NOT wait
|
|
412
|
+
* for pipe-buffered output to flush — `process.stdout.write(text)`
|
|
413
|
+
* against a pipe (which `bash -c '$(pyric --help)'` creates) queues
|
|
414
|
+
* the data, and a bare `process.exit(0)` discards it on Linux Node 20.
|
|
415
|
+
* Symptom: `pyric --help | cat` prints nothing in CI but works in a
|
|
416
|
+
* TTY. The zero-byte write + callback pattern below queues behind any
|
|
417
|
+
* pending writes and only exits once they've been flushed to the
|
|
418
|
+
* underlying fd. See nodejs/node #6379.
|
|
419
|
+
*/
|
|
420
|
+
function exitAfterFlush(code: number): void {
|
|
421
|
+
let pending = 2;
|
|
422
|
+
const done = () => { if (--pending === 0) process.exit(code); };
|
|
423
|
+
process.stdout.write('', done);
|
|
424
|
+
process.stderr.write('', done);
|
|
425
|
+
}
|