@hraness/ghostget 0.17.2
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/CHANGELOG.md +458 -0
- package/LICENSE +21 -0
- package/README.md +1359 -0
- package/bunfig.toml +2 -0
- package/dist/apple-photos-client.js +704 -0
- package/dist/beeper-client.js +4602 -0
- package/dist/client.js +1605 -0
- package/dist/index-26yq8q16.js +31 -0
- package/dist/index-9t13b4k7.js +508 -0
- package/dist/index-axwm9b3v.js +5 -0
- package/dist/index-gwk7rbyj.js +30 -0
- package/dist/index.js +701 -0
- package/dist/messaging.js +1130 -0
- package/dist/omni-client.js +1406 -0
- package/dist/whatsapp-client.js +355 -0
- package/docs/imessage-direct-provider.md +106 -0
- package/docs/rental-listings.md +94 -0
- package/package.json +600 -0
- package/skills/ghostget/SKILL.md +251 -0
- package/skills/ghostget/agents/openai.yaml +4 -0
- package/skills/ghostget/references/adapter-contract.md +181 -0
- package/skills/ghostget/references/apple-photos.md +115 -0
- package/skills/ghostget/references/article-drafts.md +235 -0
- package/skills/ghostget/references/code-owned-provider-scaffold.md +134 -0
- package/skills/ghostget/references/cross-posting-video.md +139 -0
- package/skills/ghostget/references/cross-posting.md +82 -0
- package/skills/ghostget/references/derivation.md +390 -0
- package/skills/ghostget/references/hraness-social-profile-stats.json +269 -0
- package/skills/ghostget/references/install.md +66 -0
- package/skills/ghostget/references/linkedin-adapter.md +442 -0
- package/skills/ghostget/references/messaging.md +168 -0
- package/skills/ghostget/references/meta-comet-contract.md +153 -0
- package/skills/ghostget/references/platform-patterns.md +122 -0
- package/skills/ghostget/references/provider-plugins.md +496 -0
- package/skills/ghostget/references/reddit-flair.md +78 -0
- package/skills/ghostget/references/safety-and-state.md +214 -0
- package/skills/ghostget/references/settlement-and-duplicate-cleanup.md +79 -0
- package/skills/ghostget/references/social-platform-routing.md +66 -0
- package/skills/ghostget/references/social-profile-stats.md +195 -0
- package/skills/ghostget/references/social-video-platform-routing.md +89 -0
- package/skills/ghostget/references/whatsapp-adapter.md +101 -0
- package/skills/ghostget/references/x-adapter.md +332 -0
- package/skills/ghostget/references/x-ai-disclosure.md +71 -0
- package/src/apple-photos-cli.ts +639 -0
- package/src/apple-photos-client-types.ts +168 -0
- package/src/apple-photos-client.ts +201 -0
- package/src/apple-photos-contact-evidence.ts +838 -0
- package/src/apple-photos-local-source.ts +1131 -0
- package/src/args.ts +2053 -0
- package/src/article-draft-document.ts +417 -0
- package/src/article-draft-embeds.ts +123 -0
- package/src/article-draft-images.ts +214 -0
- package/src/assets/adapter-template/wrench-adapter.json +40 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.json +1500 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v1.0.0.json +129 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v1.1.0.json +207 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.0.0.json +1463 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.1.0.json +1463 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.2.0.json +1475 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.3.0.json +1488 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.json +684 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.0.0.json +581 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.1.0.json +581 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.2.0.json +581 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.3.0.json +615 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.4.0.json +684 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.5.0.json +684 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.6.0.json +684 -0
- package/src/assets/adapters/clasificados/wrench-web-adapter.json +54 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.json +750 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.v1.0.0.json +706 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.v1.1.0.json +703 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.v1.2.0.json +750 -0
- package/src/assets/adapters/facebook-group/wrench-web-adapter.json +682 -0
- package/src/assets/adapters/facebook-group/wrench-web-adapter.v1.0.0.json +583 -0
- package/src/assets/adapters/facebook-group/wrench-web-adapter.v1.1.0.json +682 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.json +437 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.0.0.json +383 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.1.0.json +437 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.1.1.json +437 -0
- package/src/assets/adapters/facebook-page/wrench-web-adapter.json +880 -0
- package/src/assets/adapters/facebook-page/wrench-web-adapter.v1.0.0.json +740 -0
- package/src/assets/adapters/facebook-page/wrench-web-adapter.v1.1.0.json +880 -0
- package/src/assets/adapters/github/wrench-web-adapter.json +69 -0
- package/src/assets/adapters/github/wrench-web-adapter.v1.0.0.json +42 -0
- package/src/assets/adapters/github/wrench-web-adapter.v1.1.0.json +69 -0
- package/src/assets/adapters/gmail/wrench-adapter.json +161 -0
- package/src/assets/adapters/gmail/wrench-adapter.v1.2.0.json +157 -0
- package/src/assets/adapters/hacker-news/wrench-web-adapter.json +315 -0
- package/src/assets/adapters/hacker-news/wrench-web-adapter.v1.0.0.json +315 -0
- package/src/assets/adapters/imessage/wrench-web-adapter.json +236 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.json +719 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.0.0.json +627 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.1.0.json +609 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.2.0.json +640 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.3.0.json +671 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.4.0.json +710 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.5.0.json +710 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.6.0.json +719 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.7.0.json +719 -0
- package/src/assets/adapters/linkedin/wrench-adapter.json +442 -0
- package/src/assets/adapters/linkedin/wrench-adapter.v0.4.0.json +124 -0
- package/src/assets/adapters/linkedin/wrench-adapter.v1.0.0.json +411 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.json +914 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.0.0.json +604 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.1.0.json +604 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.10.0.json +809 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.11.0.json +809 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.12.0.json +820 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.13.0.json +819 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.14.0.json +819 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.15.0.json +819 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.16.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.17.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.18.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.19.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.2.0.json +731 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.3.0.json +768 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.4.0.json +808 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.5.0.json +808 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.6.0.json +808 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.7.0.json +825 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.8.0.json +792 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.9.0.json +809 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.json +855 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.0.0.json +577 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.1.0.json +604 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.10.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.11.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.12.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.2.0.json +653 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.3.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.4.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.5.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.6.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.7.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.8.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.9.0.json +713 -0
- package/src/assets/adapters/substack/wrench-web-adapter.json +936 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.0.0.json +817 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.1.0.json +812 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.2.0.json +812 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.3.0.json +902 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.4.0.json +936 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.5.0.json +936 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.6.0.json +936 -0
- package/src/assets/adapters/threads/wrench-web-adapter.json +692 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.0.0.json +629 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.1.0.json +623 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.2.0.json +622 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.3.0.json +622 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.4.0.json +622 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.5.0.json +699 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.6.0.json +693 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.7.0.json +692 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.json +762 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.0.0.json +681 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.1.0.json +708 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.2.0.json +762 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.3.0.json +762 -0
- package/src/assets/adapters/twitch/wrench-web-adapter.json +42 -0
- package/src/assets/adapters/twitch/wrench-web-adapter.v1.0.0.json +42 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.json +400 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.0.0.json +355 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.1.0.json +386 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.2.0.json +386 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.3.0.json +400 -0
- package/src/assets/adapters/x/wrench-adapter.json +749 -0
- package/src/assets/adapters/x/wrench-adapter.v1.0.0.json +700 -0
- package/src/assets/adapters/x/wrench-adapter.v1.1.0.json +707 -0
- package/src/assets/adapters/x/wrench-web-adapter.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.1.0.json +579 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.10.0.json +685 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.11.0.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.12.0.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.13.0.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.2.0.json +578 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.3.0.json +610 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.4.0.json +617 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.5.0.json +634 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.6.0.json +632 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.7.0.json +649 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.8.0.json +649 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.9.0.json +683 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.json +561 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.0.0.json +465 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.1.0.json +519 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.2.0.json +561 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.3.0.json +561 -0
- package/src/assets/code-owned-provider-template/plugin.test.ts.template +54 -0
- package/src/assets/code-owned-provider-template/plugin.ts.template +102 -0
- package/src/assets/code-owned-provider-template/runtime.internal.test.ts.template +44 -0
- package/src/assets/code-owned-provider-template/runtime.ts.template +59 -0
- package/src/assets/code-owned-provider-template/wrench-adapter.json.template +33 -0
- package/src/assets/fonts/nebula-sans/LICENSE.txt +96 -0
- package/src/assets/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
- package/src/assets/fonts/nebula-sans/PROVENANCE.md +14 -0
- package/src/assets.d.ts +4 -0
- package/src/auth.ts +1157 -0
- package/src/beeper-client-types.ts +169 -0
- package/src/beeper-client.ts +250 -0
- package/src/beeper-contact-interactions-cli.ts +180 -0
- package/src/beeper-contact-interactions.ts +1612 -0
- package/src/beeper-message-bundle-v1.ts +257 -0
- package/src/beeper-message-like-me-cli.ts +84 -0
- package/src/beeper-message-like-me-export.ts +2274 -0
- package/src/beeper-message-like-me-recovery.ts +931 -0
- package/src/beeper-message-like-me-source.ts +4034 -0
- package/src/browser-admission.ts +928 -0
- package/src/browser-snapshots.ts +260 -0
- package/src/browser.ts +3873 -0
- package/src/canonical-json.ts +60 -0
- package/src/catalog-cli.ts +638 -0
- package/src/cli.ts +208 -0
- package/src/client-types.ts +301 -0
- package/src/client.ts +2726 -0
- package/src/confirmed-write-failure.ts +44 -0
- package/src/confirmed-write-model.ts +72 -0
- package/src/confirmed-write-platform.ts +1055 -0
- package/src/confirmed-write-program.ts +224 -0
- package/src/confirmed-write-runtime.ts +16 -0
- package/src/cursor-token.ts +228 -0
- package/src/derivation-dnr-readiness.ts +367 -0
- package/src/derivation-file-chooser.ts +384 -0
- package/src/derivation-network-boundary.ts +835 -0
- package/src/derivation-network-guard.ts +782 -0
- package/src/derivation-network-proxy-helper.ts +440 -0
- package/src/derivation-network-proxy.ts +385 -0
- package/src/derive-command-helper.ts +693 -0
- package/src/derive-fixtures.ts +343 -0
- package/src/derive-review.ts +980 -0
- package/src/derive.ts +4754 -0
- package/src/fixtures/beeper-message-like-me-v1/accounts.ndjson +2 -0
- package/src/fixtures/beeper-message-like-me-v1/conversations.ndjson +1 -0
- package/src/fixtures/beeper-message-like-me-v1/manifest.json +1 -0
- package/src/fixtures/beeper-message-like-me-v1/messages.ndjson +2 -0
- package/src/fixtures/beeper-message-like-me-v1/participants.ndjson +3 -0
- package/src/fixtures/beeper-message-like-me-v1/reactions.ndjson +1 -0
- package/src/fixtures/beeper-message-like-me-v1/tombstones.ndjson +1 -0
- package/src/ghostget.ts +3672 -0
- package/src/gmail-capture.ts +1244 -0
- package/src/har-internal.ts +1242 -0
- package/src/har.ts +743 -0
- package/src/index.ts +218 -0
- package/src/invocation-read-platform.ts +55 -0
- package/src/invocation-read-program.ts +93 -0
- package/src/invocation-read-runtime.ts +11 -0
- package/src/linked-device-lifecycle-admission.ts +450 -0
- package/src/linked-device-lifecycle-journal.ts +1560 -0
- package/src/linked-device-lifecycle-runtime.ts +1602 -0
- package/src/local-cli-admission.ts +135 -0
- package/src/local-cli-contracts.ts +271 -0
- package/src/local-cli-execution.ts +98 -0
- package/src/local-cli-surface-contract.ts +1510 -0
- package/src/local-cli-tool-identity.ts +336 -0
- package/src/media/archive.ts +2325 -0
- package/src/media/args.ts +303 -0
- package/src/media/cli.ts +287 -0
- package/src/media/doctor.ts +475 -0
- package/src/media/ffmpeg.ts +1330 -0
- package/src/media/http-capture.ts +711 -0
- package/src/media/http-probe.ts +593 -0
- package/src/media/http.ts +387 -0
- package/src/media/index.ts +10 -0
- package/src/media/local-transcription.ts +613 -0
- package/src/media/lock.ts +321 -0
- package/src/media/manifest.ts +1712 -0
- package/src/media/metadata.ts +906 -0
- package/src/media/process.ts +723 -0
- package/src/media/revision.ts +166 -0
- package/src/media/runtime-closure.ts +1063 -0
- package/src/media/source-router.ts +187 -0
- package/src/media/transcriber-config.ts +1122 -0
- package/src/media/transcript-persistence-model.ts +15 -0
- package/src/media/transcript-persistence-platform.ts +89 -0
- package/src/media/transcript-persistence-program.ts +39 -0
- package/src/media/transcript-persistence-runtime.ts +24 -0
- package/src/media/transcript.ts +616 -0
- package/src/media/utf8-order.ts +30 -0
- package/src/media/whisper-cpp.ts +464 -0
- package/src/media/whisper-language.ts +58 -0
- package/src/media/yt-dlp.ts +439 -0
- package/src/message-like-me-agentic-messaging.ts +882 -0
- package/src/messaging-action-store.ts +793 -0
- package/src/messaging-runtime.ts +2136 -0
- package/src/messaging-store.ts +539 -0
- package/src/messaging-types.ts +1663 -0
- package/src/messaging.ts +334 -0
- package/src/model.ts +2671 -0
- package/src/oauth-google.ts +888 -0
- package/src/omni-client-types.ts +306 -0
- package/src/omni-client.ts +2225 -0
- package/src/omni-limits.ts +34 -0
- package/src/omni-model.ts +1614 -0
- package/src/omni-request.ts +379 -0
- package/src/omni-runtime.ts +1632 -0
- package/src/operation-deadline.ts +189 -0
- package/src/path-helper.ts +1656 -0
- package/src/pinned-https.ts +194 -0
- package/src/plan-assets.ts +832 -0
- package/src/platform-catalog.ts +1832 -0
- package/src/plugins/beeper-linked-device/plugin.ts +310 -0
- package/src/plugins/bluesky-web/plugin.ts +178 -0
- package/src/plugins/clasificados-web/plugin.ts +66 -0
- package/src/plugins/github-web/plugin.ts +80 -0
- package/src/plugins/gmail-official/plugin.ts +110 -0
- package/src/plugins/hacker-news-web/plugin.ts +52 -0
- package/src/plugins/imessage-direct/plugin.ts +195 -0
- package/src/plugins/imessage-direct/vendor/0001-fix-keep-AppleScript-send-payloads-out-of-child-argv.patch +1430 -0
- package/src/plugins/imessage-direct/vendor/0002-feat-rpc-add-exact-chat-lookup.patch +225 -0
- package/src/plugins/imessage-direct/vendor/provenance.json +80 -0
- package/src/plugins/linkedin-official/plugin.ts +84 -0
- package/src/plugins/linkedin-web/plugin.ts +412 -0
- package/src/plugins/meta-web/plugin.ts +317 -0
- package/src/plugins/reddit-web/flair.ts +492 -0
- package/src/plugins/reddit-web/plugin.ts +477 -0
- package/src/plugins/substack-web/plugin.ts +124 -0
- package/src/plugins/tiktok-web/plugin.ts +67 -0
- package/src/plugins/twitch-web/plugin.ts +54 -0
- package/src/plugins/whatsapp-linked-device/plugin.ts +105 -0
- package/src/plugins/x-official/plugin.ts +64 -0
- package/src/plugins/x-web/plugin.ts +488 -0
- package/src/plugins/youtube-web/plugin.ts +101 -0
- package/src/portable-run-recovery.ts +466 -0
- package/src/process-identity.ts +501 -0
- package/src/profile-clone-helper.ts +104 -0
- package/src/provider-catalog-views.ts +51 -0
- package/src/provider-context.ts +69 -0
- package/src/provider-contract-definitions-x.ts +45 -0
- package/src/provider-contract-definitions.ts +948 -0
- package/src/provider-contract-input-gmail.ts +176 -0
- package/src/provider-contract-input-linkedin.ts +77 -0
- package/src/provider-contract-input-x.ts +304 -0
- package/src/provider-contract-planning.ts +23 -0
- package/src/provider-contract-semantic-identity.ts +54 -0
- package/src/provider-contracts.ts +251 -0
- package/src/provider-http.ts +723 -0
- package/src/provider-plugin-auth.ts +36 -0
- package/src/provider-plugin-builtins.ts +229 -0
- package/src/provider-plugin-cleanup-barrier.ts +229 -0
- package/src/provider-plugin-cleanup-execution.ts +79 -0
- package/src/provider-plugin-cleanup-resource.ts +470 -0
- package/src/provider-plugin-contract-identity.ts +707 -0
- package/src/provider-plugin-host.ts +1972 -0
- package/src/provider-plugin-identifiers.ts +60 -0
- package/src/provider-plugin-invocation-lease.ts +889 -0
- package/src/provider-plugin-lifecycle-kernel.ts +566 -0
- package/src/provider-plugin-lifecycle.ts +1455 -0
- package/src/provider-plugin-module-analysis.ts +336 -0
- package/src/provider-plugin-package.ts +2530 -0
- package/src/provider-plugin-portable-authority.ts +106 -0
- package/src/provider-plugin-portable-catalog.ts +94 -0
- package/src/provider-plugin-portable-identity.ts +315 -0
- package/src/provider-plugin-portable-runtime.ts +2057 -0
- package/src/provider-plugin-protocol.ts +1625 -0
- package/src/provider-plugin-registry.ts +3342 -0
- package/src/provider-plugin-store.ts +2155 -0
- package/src/provider-plugin-test-fixture.ts +5 -0
- package/src/provider-plugin.ts +4907 -0
- package/src/provider-plugins.generated.ts +43 -0
- package/src/provider-plugins.ts +8 -0
- package/src/provider-subject.ts +41 -0
- package/src/provider.ts +315 -0
- package/src/providers/beeper-local-runtime.ts +5426 -0
- package/src/providers/beeper-local.ts +2739 -0
- package/src/providers/beeper-messaging.ts +462 -0
- package/src/providers/beeper-omni.ts +1159 -0
- package/src/providers/bluesky-web-runtime.ts +2895 -0
- package/src/providers/bluesky-web.ts +1614 -0
- package/src/providers/clasificados-web-runtime.ts +255 -0
- package/src/providers/clasificados-web.ts +503 -0
- package/src/providers/contact-projection.ts +301 -0
- package/src/providers/github-read-model.ts +94 -0
- package/src/providers/github-read-platform.ts +165 -0
- package/src/providers/github-read-program.ts +97 -0
- package/src/providers/github-web-runtime.ts +320 -0
- package/src/providers/github-web.ts +403 -0
- package/src/providers/gmail-api.ts +2834 -0
- package/src/providers/gmail-omni.ts +830 -0
- package/src/providers/gmail.ts +1130 -0
- package/src/providers/hacker-news-web-runtime.ts +220 -0
- package/src/providers/hacker-news-web.ts +809 -0
- package/src/providers/imessage-direct-install.ts +354 -0
- package/src/providers/imessage-direct-messaging.ts +532 -0
- package/src/providers/imessage-direct-omni.ts +400 -0
- package/src/providers/imessage-direct-runtime.ts +1498 -0
- package/src/providers/imessage-direct.ts +351 -0
- package/src/providers/instagram-video-foundations.ts +913 -0
- package/src/providers/instagram-web-profile-browser.ts +600 -0
- package/src/providers/iso-bmff.ts +338 -0
- package/src/providers/linkedin-company-platform.ts +42 -0
- package/src/providers/linkedin-company-program.ts +88 -0
- package/src/providers/linkedin-contact-failure.ts +84 -0
- package/src/providers/linkedin-contact-platform.ts +45 -0
- package/src/providers/linkedin-contact-program.ts +91 -0
- package/src/providers/linkedin-profile-activity-failure.ts +76 -0
- package/src/providers/linkedin-profile-activity-platform.ts +41 -0
- package/src/providers/linkedin-profile-activity-program.ts +67 -0
- package/src/providers/linkedin-read-failure.ts +52 -0
- package/src/providers/linkedin-self-platform.ts +53 -0
- package/src/providers/linkedin-self-program.ts +122 -0
- package/src/providers/linkedin-web-article-browser.ts +794 -0
- package/src/providers/linkedin-web-bootstrap.ts +146 -0
- package/src/providers/linkedin-web-contact.ts +830 -0
- package/src/providers/linkedin-web-feed-browser.ts +832 -0
- package/src/providers/linkedin-web-feed.ts +864 -0
- package/src/providers/linkedin-web-post-browser.ts +653 -0
- package/src/providers/linkedin-web-profile-browser.ts +683 -0
- package/src/providers/linkedin-web-runtime.ts +2388 -0
- package/src/providers/linkedin-web.ts +3305 -0
- package/src/providers/linkedin.ts +1885 -0
- package/src/providers/meta-bootstrap.ts +1043 -0
- package/src/providers/meta-facebook-group.ts +690 -0
- package/src/providers/meta-marketplace-relay.ts +747 -0
- package/src/providers/meta-omni.ts +373 -0
- package/src/providers/meta-relay-bundle.ts +1049 -0
- package/src/providers/meta-web-descriptors.ts +1740 -0
- package/src/providers/meta-web-runtime.ts +3388 -0
- package/src/providers/meta-web.ts +2931 -0
- package/src/providers/read-failure.ts +139 -0
- package/src/providers/reddit-omni.ts +462 -0
- package/src/providers/reddit-web-runtime.ts +1929 -0
- package/src/providers/reddit-web.ts +1611 -0
- package/src/providers/rental-listings.ts +460 -0
- package/src/providers/substack-omni.ts +406 -0
- package/src/providers/substack-video-mp4.ts +33 -0
- package/src/providers/substack-web-runtime.ts +2812 -0
- package/src/providers/substack-web.ts +1502 -0
- package/src/providers/tiktok-video-mp4.ts +33 -0
- package/src/providers/tiktok-web-runtime.ts +770 -0
- package/src/providers/tiktok-web.ts +2786 -0
- package/src/providers/twitch-web-runtime.ts +226 -0
- package/src/providers/twitch-web.ts +274 -0
- package/src/providers/whatsapp-account-identity.ts +55 -0
- package/src/providers/whatsapp-contact-projection-helper.ts +874 -0
- package/src/providers/whatsapp-contact-projection-protocol.ts +403 -0
- package/src/providers/whatsapp-interaction-projection-helper.ts +1452 -0
- package/src/providers/whatsapp-interaction-projection-protocol.ts +462 -0
- package/src/providers/whatsapp-message-export-projection-protocol.ts +532 -0
- package/src/providers/whatsapp-messaging.ts +132 -0
- package/src/providers/whatsapp-omni.ts +586 -0
- package/src/providers/whatsapp-web-runtime.ts +3108 -0
- package/src/providers/whatsapp-web.ts +1037 -0
- package/src/providers/x-image-provenance.ts +523 -0
- package/src/providers/x-made-with-ai.ts +106 -0
- package/src/providers/x-transaction-id.ts +413 -0
- package/src/providers/x-web-runtime.ts +3485 -0
- package/src/providers/x-web.ts +2332 -0
- package/src/providers/x.ts +1889 -0
- package/src/providers/youtube-web-runtime.ts +1400 -0
- package/src/providers/youtube-web.ts +1221 -0
- package/src/read-admission-runtime.ts +91 -0
- package/src/read-client.ts +521 -0
- package/src/read-effect-platform.ts +7 -0
- package/src/read-effect-runtime.ts +14 -0
- package/src/read-effect.ts +52 -0
- package/src/read-projection-admission.ts +866 -0
- package/src/read-projections.ts +3151 -0
- package/src/recovery.ts +1492 -0
- package/src/reviewed-template.ts +146 -0
- package/src/run-journal.ts +1272 -0
- package/src/runtime.ts +5116 -0
- package/src/scripts/generate-provider-plugin-catalog.ts +121 -0
- package/src/scripts/install-whatsapp-protocol.sh +232 -0
- package/src/scripts/recover-install-stages.ts +1491 -0
- package/src/scripts/resolve-state-home.ts +30 -0
- package/src/scripts/scaffold-web-provider.ts +973 -0
- package/src/scripts/sync-bundled-adapters.ts +695 -0
- package/src/session-secrets.ts +1183 -0
- package/src/state-helper.bunfig.toml +2 -0
- package/src/state-helper.ts +2914 -0
- package/src/storage.ts +3842 -0
- package/src/transport-policy.ts +2 -0
- package/src/usage.ts +182 -0
- package/src/version.ts +2 -0
- package/src/web-session-authentication-policy.ts +136 -0
- package/src/web-session-cleanup-admission.ts +2344 -0
- package/src/web-session-cleanup-join.ts +99 -0
- package/src/web-session-client.ts +996 -0
- package/src/web-session-contract-definitions.ts +820 -0
- package/src/web-session-contract-planning.ts +42 -0
- package/src/web-session-contracts.ts +228 -0
- package/src/web-session-cookies.ts +500 -0
- package/src/web-session-execution.ts +385 -0
- package/src/web-session-http.ts +373 -0
- package/src/web-session-read-errors.ts +19 -0
- package/src/web-session-read-runtime.ts +124 -0
- package/src/web-session-recovery.ts +818 -0
- package/src/web-session-sites.ts +58 -0
- package/src/web-session-template.ts +994 -0
- package/src/web-session.ts +93 -0
- package/src/whatsapp-client-binding.ts +21 -0
- package/src/whatsapp-client-types.ts +75 -0
- package/src/whatsapp-client.ts +395 -0
- package/src/whatsapp-export-coordinate.ts +17 -0
- package/src/whatsapp-message-bundle-v2.ts +195 -0
- package/src/whatsapp-message-like-me-cli.ts +195 -0
- package/src/whatsapp-message-like-me-export.ts +1072 -0
- package/src/whatsapp-message-like-me-source.ts +1012 -0
- package/tsconfig.json +67 -0
|
@@ -0,0 +1,1632 @@
|
|
|
1
|
+
import { types as nodeTypes } from "node:util";
|
|
2
|
+
|
|
3
|
+
import { canonicalJson, sha256 } from "./canonical-json";
|
|
4
|
+
import { loadAuthSnapshotIfPresent } from "./auth";
|
|
5
|
+
import {
|
|
6
|
+
isProviderOperation,
|
|
7
|
+
isLocalCliOperation,
|
|
8
|
+
isWebSessionOperation,
|
|
9
|
+
} from "./model";
|
|
10
|
+
import {
|
|
11
|
+
markOmniSourceDriftV1,
|
|
12
|
+
OMNI_MAX_SOURCE_PAGES,
|
|
13
|
+
parseMaterializedPageV1,
|
|
14
|
+
parseOmniSourceStateV1,
|
|
15
|
+
queryOmniSourceStatesV1,
|
|
16
|
+
reduceOmniSourceStateV1,
|
|
17
|
+
type OmniEntityV1,
|
|
18
|
+
type OmniJsonValue,
|
|
19
|
+
type OmniNormalizationStatusV1,
|
|
20
|
+
type OmniPageProvenanceV1,
|
|
21
|
+
type OmniSourceIdentityV1,
|
|
22
|
+
type OmniSourceStateV1,
|
|
23
|
+
type OmniStoredPageV1,
|
|
24
|
+
} from "./omni-model";
|
|
25
|
+
import {
|
|
26
|
+
boundedOmniText,
|
|
27
|
+
OMNI_MAX_REASON_BYTES,
|
|
28
|
+
OMNI_MAX_RESPONSE_BYTES,
|
|
29
|
+
} from "./omni-limits";
|
|
30
|
+
import {
|
|
31
|
+
omniRequestDigest,
|
|
32
|
+
openOmniViewCursorV1,
|
|
33
|
+
parseOmniViewRequestV1,
|
|
34
|
+
sealOmniViewCursorV1,
|
|
35
|
+
type OmniViewRequestV1,
|
|
36
|
+
type OmniViewSourceRequestV1,
|
|
37
|
+
} from "./omni-request";
|
|
38
|
+
import type {
|
|
39
|
+
ProviderPluginOmniDefinitionV1,
|
|
40
|
+
} from "./provider-plugin";
|
|
41
|
+
import type {
|
|
42
|
+
ProviderPluginOperationResolutionV1,
|
|
43
|
+
ProviderPluginRegistry,
|
|
44
|
+
} from "./provider-plugin-registry";
|
|
45
|
+
import { providerPluginRegistry } from "./provider-plugins";
|
|
46
|
+
import { revalidatePreparedCapability } from "./read-client";
|
|
47
|
+
import {
|
|
48
|
+
createOmniProjectionQuery,
|
|
49
|
+
readOmniProjection,
|
|
50
|
+
readReadProjectionForMaterialization,
|
|
51
|
+
reduceOmniProjection,
|
|
52
|
+
projectionAuthIdentityHash,
|
|
53
|
+
type OmniProjectionQuery,
|
|
54
|
+
type ReadProjectionExactHeadFence,
|
|
55
|
+
type ReadProjectionMaterializationSnapshot,
|
|
56
|
+
type ReadProjectionQuery,
|
|
57
|
+
} from "./read-projections";
|
|
58
|
+
import {
|
|
59
|
+
createReadProjectionQueryForInvocation,
|
|
60
|
+
prepareInvocation,
|
|
61
|
+
type PreparedInvocation,
|
|
62
|
+
} from "./runtime";
|
|
63
|
+
import type { executeReadInvocation } from "./runtime";
|
|
64
|
+
|
|
65
|
+
type Environment = Readonly<Record<string, string | undefined>>;
|
|
66
|
+
const MAX_MATERIALIZATION_SETTLEMENT_ATTEMPTS = 4;
|
|
67
|
+
|
|
68
|
+
export type OmniExactSourceStatusV1 =
|
|
69
|
+
| {
|
|
70
|
+
readonly state: "miss";
|
|
71
|
+
readonly key: string;
|
|
72
|
+
}
|
|
73
|
+
| {
|
|
74
|
+
readonly state: "hit";
|
|
75
|
+
readonly key: string;
|
|
76
|
+
readonly dataRevision: string;
|
|
77
|
+
readonly validatedAt: string;
|
|
78
|
+
readonly ageMs: number;
|
|
79
|
+
readonly freshness: {
|
|
80
|
+
readonly state: "fresh" | "stale" | "unclassified";
|
|
81
|
+
readonly freshForMs: number | null;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
| {
|
|
85
|
+
readonly state: "error";
|
|
86
|
+
readonly key: string;
|
|
87
|
+
readonly reason: string;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type OmniNormalizationSourceStatusV1 =
|
|
91
|
+
| { readonly state: "missing" }
|
|
92
|
+
| { readonly state: "unsupported"; readonly reason: string }
|
|
93
|
+
| {
|
|
94
|
+
readonly state: "current";
|
|
95
|
+
readonly exactQueryKey: string;
|
|
96
|
+
readonly exactDataRevision: string;
|
|
97
|
+
readonly lastGoodAt: string;
|
|
98
|
+
}
|
|
99
|
+
| {
|
|
100
|
+
readonly state: "retained-after-drift";
|
|
101
|
+
readonly exactQueryKey: string;
|
|
102
|
+
readonly reason: string;
|
|
103
|
+
readonly failedExactDataRevision: string;
|
|
104
|
+
readonly newerExactDataRevision: string | null;
|
|
105
|
+
readonly lastGoodExactDataRevision: string | null;
|
|
106
|
+
readonly lastGoodAt: string | null;
|
|
107
|
+
}
|
|
108
|
+
| {
|
|
109
|
+
readonly state: "stale";
|
|
110
|
+
readonly exactQueryKey: string;
|
|
111
|
+
/** Null when a failed provider attempt produced no new exact revision. */
|
|
112
|
+
readonly exactDataRevision: string | null;
|
|
113
|
+
/** Null when this exact query has never produced a normalized page. */
|
|
114
|
+
readonly normalizedExactDataRevision: string | null;
|
|
115
|
+
readonly lastGoodAt: string | null;
|
|
116
|
+
readonly reason: string;
|
|
117
|
+
}
|
|
118
|
+
| {
|
|
119
|
+
readonly state: "error";
|
|
120
|
+
readonly reason: string;
|
|
121
|
+
readonly lastGoodAt: string | null;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export type OmniSourceCoverageV1 =
|
|
125
|
+
| {
|
|
126
|
+
readonly state: "unavailable";
|
|
127
|
+
readonly reason: string;
|
|
128
|
+
}
|
|
129
|
+
| {
|
|
130
|
+
readonly state: "observed";
|
|
131
|
+
readonly kind: OmniStoredPageV1["completeness"]["kind"];
|
|
132
|
+
readonly continuation: "none" | "pending" | "unavailable";
|
|
133
|
+
readonly reason: string | null;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export type OmniViewSourceStatusV1 = {
|
|
137
|
+
readonly adapterId: string;
|
|
138
|
+
readonly operationId: "messaging.list" | "messaging.read";
|
|
139
|
+
readonly authId: string;
|
|
140
|
+
/** Client-verifiable identity of the exact raw request input. */
|
|
141
|
+
readonly requestInputHash: string;
|
|
142
|
+
/** Provider-parsed/defaulted identity used by the exact projection. */
|
|
143
|
+
readonly projectionInputHash: string;
|
|
144
|
+
/** Opaque keyed revision of the durable normalized source state, if any. */
|
|
145
|
+
readonly normalizationDataRevision: string | null;
|
|
146
|
+
readonly surfaceId: string;
|
|
147
|
+
readonly exact: OmniExactSourceStatusV1;
|
|
148
|
+
readonly normalization: OmniNormalizationSourceStatusV1;
|
|
149
|
+
readonly coverage: OmniSourceCoverageV1;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export type OmniViewV1 = {
|
|
153
|
+
readonly schemaVersion: 1;
|
|
154
|
+
readonly viewRevision: string;
|
|
155
|
+
readonly entities: readonly OmniEntityV1[];
|
|
156
|
+
readonly nextCursor: string | null;
|
|
157
|
+
readonly sources: readonly OmniViewSourceStatusV1[];
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export type OmniViewIdentityV1 = {
|
|
161
|
+
/** Full canonical SDK/CLI invocation identity, including the local cursor. */
|
|
162
|
+
readonly invocationDigest: string;
|
|
163
|
+
/** Cursor-independent logical request identity. */
|
|
164
|
+
readonly requestDigest: string;
|
|
165
|
+
readonly sourceSetDigest: string;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export type OmniReadResultV1 = {
|
|
169
|
+
readonly ok: true;
|
|
170
|
+
readonly schemaVersion: 1;
|
|
171
|
+
readonly source:
|
|
172
|
+
| "omni-cache"
|
|
173
|
+
| "omni-live"
|
|
174
|
+
| "omni-exact-cache"
|
|
175
|
+
| "omni-identity";
|
|
176
|
+
readonly identity: OmniViewIdentityV1;
|
|
177
|
+
readonly view: OmniViewV1 | null;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
type PreparedOmniSource = {
|
|
181
|
+
readonly request: OmniViewSourceRequestV1;
|
|
182
|
+
readonly invocation: PreparedInvocation;
|
|
183
|
+
readonly exactQuery: ReadProjectionQuery;
|
|
184
|
+
readonly resolution: ProviderPluginOperationResolutionV1 | null;
|
|
185
|
+
readonly surfaceId: string;
|
|
186
|
+
readonly omni: ProviderPluginOmniDefinitionV1 | null;
|
|
187
|
+
readonly sourceIdentity: OmniSourceIdentityV1 | null;
|
|
188
|
+
readonly omniQuery: OmniProjectionQuery | null;
|
|
189
|
+
readonly identityDescriptor: unknown;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
type OmniRuntimeOptions = {
|
|
193
|
+
readonly environment?: Environment;
|
|
194
|
+
readonly registry?: ProviderPluginRegistry;
|
|
195
|
+
readonly now?: Date;
|
|
196
|
+
readonly freshForMs?: number;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
type OmniLiveRuntimeOptions = OmniRuntimeOptions & {
|
|
200
|
+
readonly headed?: boolean;
|
|
201
|
+
readonly signal?: AbortSignal;
|
|
202
|
+
readonly executeRead?: typeof executeReadInvocation;
|
|
203
|
+
/** Internal resource budget. The product default remains the schema cap. */
|
|
204
|
+
readonly sourcePageLimit?: number;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
type OmniSourceUpdateError = {
|
|
208
|
+
readonly exactQueryKey: string;
|
|
209
|
+
readonly reason: string;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
type OmniMaterializationResult = ReturnType<typeof materializeCurrentExact>;
|
|
213
|
+
|
|
214
|
+
const EXACT_READ_ERROR_REASON = "exact provider snapshot could not be read";
|
|
215
|
+
const NORMALIZED_STATE_READ_ERROR_REASON = "normalized source state could not be read";
|
|
216
|
+
const NORMALIZED_STATE_PARSE_ERROR_REASON = "normalized source state could not be parsed";
|
|
217
|
+
const NORMALIZED_STATE_OBSERVE_ERROR_REASON = "normalized source state could not be observed";
|
|
218
|
+
const PROVIDER_READ_ERROR_REASON =
|
|
219
|
+
"provider read failed before the normalized source could be refreshed";
|
|
220
|
+
const EXACT_PUBLICATION_ERROR_REASON =
|
|
221
|
+
"exact provider snapshot could not be published during omni revalidation";
|
|
222
|
+
const NORMALIZATION_UPDATE_ERROR_REASON =
|
|
223
|
+
"exact provider snapshot could not be normalized";
|
|
224
|
+
const CONTINUATION_PREPARATION_ERROR_REASON =
|
|
225
|
+
"provider continuation could not be prepared from normalized state";
|
|
226
|
+
|
|
227
|
+
function parseSourcePageLimit(value: number | undefined): number {
|
|
228
|
+
const parsed = value ?? OMNI_MAX_SOURCE_PAGES;
|
|
229
|
+
if (
|
|
230
|
+
!Number.isSafeInteger(parsed)
|
|
231
|
+
|| parsed < 1
|
|
232
|
+
|| parsed > OMNI_MAX_SOURCE_PAGES
|
|
233
|
+
) {
|
|
234
|
+
throw new Error(
|
|
235
|
+
`omni source page limit must be an integer from 1 through ${String(OMNI_MAX_SOURCE_PAGES)}`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
return parsed;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function createOmniContinuationGuard(
|
|
242
|
+
rootExactQueryKey: string,
|
|
243
|
+
pageLimitValue?: number,
|
|
244
|
+
): Readonly<{
|
|
245
|
+
beforeNext(): string | null;
|
|
246
|
+
observe(exactQueryKey: string): string | null;
|
|
247
|
+
}> {
|
|
248
|
+
const pageLimit = parseSourcePageLimit(pageLimitValue);
|
|
249
|
+
let pages = 1;
|
|
250
|
+
const visited = new Set([rootExactQueryKey]);
|
|
251
|
+
return Object.freeze({
|
|
252
|
+
beforeNext(): string | null {
|
|
253
|
+
return pages >= pageLimit
|
|
254
|
+
? `provider continuation exceeds the ${String(pageLimit)}-page normalized capacity`
|
|
255
|
+
: null;
|
|
256
|
+
},
|
|
257
|
+
observe(exactQueryKey: string): string | null {
|
|
258
|
+
if (visited.has(exactQueryKey)) {
|
|
259
|
+
return "provider continuation repeated an exact page query";
|
|
260
|
+
}
|
|
261
|
+
visited.add(exactQueryKey);
|
|
262
|
+
pages += 1;
|
|
263
|
+
return null;
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function boundedError(error: unknown): string {
|
|
269
|
+
const value = error instanceof Error ? error.message : String(error);
|
|
270
|
+
return boundedOmniText(value, OMNI_MAX_REASON_BYTES);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function privateDriftError(error: unknown): Error {
|
|
274
|
+
if (!nodeTypes.isProxy(error) && error instanceof Error) {
|
|
275
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, "message");
|
|
276
|
+
if (
|
|
277
|
+
descriptor !== undefined
|
|
278
|
+
&& "value" in descriptor
|
|
279
|
+
&& typeof descriptor.value === "string"
|
|
280
|
+
) {
|
|
281
|
+
return new Error(boundedOmniText(descriptor.value, OMNI_MAX_REASON_BYTES));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return new Error("provider materializer threw a non-Error diagnostic");
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function internalDriftCode(
|
|
288
|
+
error: unknown,
|
|
289
|
+
): "materializer-drift" | "capacity-exceeded" {
|
|
290
|
+
const message = error instanceof Error ? error.message : "";
|
|
291
|
+
return /(?:must be a plain array of at most \d+ items|exceeds its JSON bound|has too many properties|exceeds its (?:byte|entity, page, complete-coverage, tombstone, or normalization|normalization frontier) capacity)$/u
|
|
292
|
+
.test(message)
|
|
293
|
+
? "capacity-exceeded"
|
|
294
|
+
: "materializer-drift";
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function throwIfAborted(signal: AbortSignal | undefined): void {
|
|
298
|
+
if (signal?.aborted !== true) return;
|
|
299
|
+
throw signal.reason instanceof Error
|
|
300
|
+
? signal.reason
|
|
301
|
+
: new DOMException("omni revalidation was aborted", "AbortError");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function sourceUpdateError(
|
|
305
|
+
source: PreparedOmniSource,
|
|
306
|
+
reason: string,
|
|
307
|
+
): OmniSourceUpdateError {
|
|
308
|
+
return Object.freeze({
|
|
309
|
+
exactQueryKey: source.exactQuery.key,
|
|
310
|
+
reason,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function publicDriftReason(
|
|
315
|
+
source: PreparedOmniSource,
|
|
316
|
+
code: Extract<OmniNormalizationStatusV1, { readonly state: "drift" }>["code"],
|
|
317
|
+
): string {
|
|
318
|
+
if (code === "capacity-exceeded") {
|
|
319
|
+
return `${source.surfaceId} ${source.request.operationId} normalized state exceeded its reviewed capacity`;
|
|
320
|
+
}
|
|
321
|
+
const materializer = source.omni?.state === "supported"
|
|
322
|
+
? `${source.omni.materializerId}@${String(source.omni.materializerVersion)}`
|
|
323
|
+
: "unavailable";
|
|
324
|
+
return `${source.surfaceId} ${source.request.operationId} materializer ${materializer} rejected the exact provider shape`;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function publicCoverageReason(
|
|
328
|
+
kind: OmniStoredPageV1["completeness"]["kind"],
|
|
329
|
+
): string {
|
|
330
|
+
switch (kind) {
|
|
331
|
+
case "complete":
|
|
332
|
+
return "the provider materializer declared complete partition coverage";
|
|
333
|
+
case "page":
|
|
334
|
+
return "the provider materializer declared page-scoped coverage";
|
|
335
|
+
case "unknown":
|
|
336
|
+
return "the provider materializer could not establish coverage completeness";
|
|
337
|
+
case "first-page-only":
|
|
338
|
+
return "the provider contract supports only the first observed page";
|
|
339
|
+
case "bounded-local":
|
|
340
|
+
return "the provider materializer exposed a bounded local projection";
|
|
341
|
+
case "search-window":
|
|
342
|
+
return "the provider materializer exposed a bounded search window";
|
|
343
|
+
case "truncated":
|
|
344
|
+
return "the provider materializer reported truncated coverage";
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function resolvePluginOperation(
|
|
349
|
+
invocation: PreparedInvocation,
|
|
350
|
+
registry: ProviderPluginRegistry,
|
|
351
|
+
): ProviderPluginOperationResolutionV1 | null {
|
|
352
|
+
const operation = invocation.manifest.operations[invocation.operationId];
|
|
353
|
+
if (operation === undefined) throw new Error("omni source operation disappeared");
|
|
354
|
+
if (isProviderOperation(operation)) {
|
|
355
|
+
return registry.requireOperationDefinition(
|
|
356
|
+
"provider-api",
|
|
357
|
+
operation.provider.provider,
|
|
358
|
+
operation.provider.action,
|
|
359
|
+
operation.provider.contractVersion,
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
if (isWebSessionOperation(operation)) {
|
|
363
|
+
const binding = registry.requireSessionRoute(operation.webSession.site);
|
|
364
|
+
return registry.requireOperationDefinition(
|
|
365
|
+
binding.transport,
|
|
366
|
+
operation.webSession.site,
|
|
367
|
+
operation.webSession.action,
|
|
368
|
+
operation.webSession.contractVersion,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
if (isLocalCliOperation(operation)) {
|
|
372
|
+
return registry.requireOperationDefinition(
|
|
373
|
+
"local-cli",
|
|
374
|
+
operation.localCli.surface,
|
|
375
|
+
operation.localCli.action,
|
|
376
|
+
operation.localCli.contractVersion,
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function materializerDescriptors(
|
|
383
|
+
resolution: ProviderPluginOperationResolutionV1,
|
|
384
|
+
): readonly unknown[] {
|
|
385
|
+
return Object.freeze(resolution.binding.operations
|
|
386
|
+
.filter((operation) =>
|
|
387
|
+
operation.name === "messaging.list" || operation.name === "messaging.read")
|
|
388
|
+
.map((operation) => {
|
|
389
|
+
if (operation.omni === undefined) {
|
|
390
|
+
throw new Error(
|
|
391
|
+
`provider plugin ${resolution.plugin.id} ${resolution.binding.surfaceId}/${operation.name} is missing its required omni declaration`,
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
return Object.freeze({
|
|
395
|
+
operation: operation.name,
|
|
396
|
+
contractVersions: operation.contractVersions,
|
|
397
|
+
...(operation.omni.state === "supported"
|
|
398
|
+
? {
|
|
399
|
+
state: "supported" as const,
|
|
400
|
+
schemaVersion: operation.omni.schemaVersion,
|
|
401
|
+
materializerId: operation.omni.materializerId,
|
|
402
|
+
materializerVersion: operation.omni.materializerVersion,
|
|
403
|
+
}
|
|
404
|
+
: {
|
|
405
|
+
state: "unsupported" as const,
|
|
406
|
+
reason: operation.omni.reason,
|
|
407
|
+
}),
|
|
408
|
+
});
|
|
409
|
+
})
|
|
410
|
+
.sort((left, right) => canonicalJson(left).localeCompare(canonicalJson(right))));
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function prepareSource(
|
|
414
|
+
request: OmniViewSourceRequestV1,
|
|
415
|
+
environment: Environment,
|
|
416
|
+
registry: ProviderPluginRegistry,
|
|
417
|
+
): PreparedOmniSource {
|
|
418
|
+
const invocation = prepareInvocation(
|
|
419
|
+
request.adapterId,
|
|
420
|
+
request.operationId,
|
|
421
|
+
request.input,
|
|
422
|
+
request.authId,
|
|
423
|
+
environment,
|
|
424
|
+
registry,
|
|
425
|
+
);
|
|
426
|
+
const exactQuery = createReadProjectionQueryForInvocation(
|
|
427
|
+
invocation,
|
|
428
|
+
environment,
|
|
429
|
+
registry,
|
|
430
|
+
);
|
|
431
|
+
const resolution = resolvePluginOperation(invocation, registry);
|
|
432
|
+
if (resolution === null) {
|
|
433
|
+
return Object.freeze({
|
|
434
|
+
request,
|
|
435
|
+
invocation,
|
|
436
|
+
exactQuery,
|
|
437
|
+
resolution: null,
|
|
438
|
+
surfaceId: invocation.manifest.id,
|
|
439
|
+
omni: null,
|
|
440
|
+
sourceIdentity: null,
|
|
441
|
+
omniQuery: null,
|
|
442
|
+
identityDescriptor: Object.freeze({
|
|
443
|
+
request: Object.freeze({
|
|
444
|
+
adapterId: request.adapterId,
|
|
445
|
+
operationId: request.operationId,
|
|
446
|
+
authId: request.authId,
|
|
447
|
+
inputHash: exactQuery.identity.inputHash,
|
|
448
|
+
}),
|
|
449
|
+
exactQueryKey: exactQuery.key,
|
|
450
|
+
surfaceId: invocation.manifest.id,
|
|
451
|
+
materialization: Object.freeze({
|
|
452
|
+
state: "unsupported",
|
|
453
|
+
reason: "operation is not backed by a reviewed provider plugin materializer",
|
|
454
|
+
}),
|
|
455
|
+
}),
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
const omni = resolution.operation.omni;
|
|
459
|
+
if (omni === undefined) {
|
|
460
|
+
throw new Error(
|
|
461
|
+
`provider plugin ${resolution.plugin.id} ${resolution.binding.surfaceId}/${request.operationId} is missing its required omni declaration`,
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
const closureHash = registry.implementationClosureHash(resolution.binding);
|
|
465
|
+
const sourceIdentity: OmniSourceIdentityV1 = Object.freeze({
|
|
466
|
+
schemaVersion: 1,
|
|
467
|
+
adapter: exactQuery.identity.adapter,
|
|
468
|
+
plugin: Object.freeze({
|
|
469
|
+
id: resolution.plugin.id,
|
|
470
|
+
version: resolution.plugin.version,
|
|
471
|
+
closureHash,
|
|
472
|
+
}),
|
|
473
|
+
surfaceId: resolution.binding.surfaceId,
|
|
474
|
+
auth: exactQuery.identity.auth,
|
|
475
|
+
});
|
|
476
|
+
const descriptors = materializerDescriptors(resolution);
|
|
477
|
+
const aggregateIdentity = Object.freeze({
|
|
478
|
+
schemaVersion: 1,
|
|
479
|
+
surfaceId: resolution.binding.surfaceId,
|
|
480
|
+
plugin: sourceIdentity.plugin,
|
|
481
|
+
materializers: descriptors,
|
|
482
|
+
});
|
|
483
|
+
const omniContract = exactQuery.identity.contract.transport === "local-cli"
|
|
484
|
+
? Object.freeze({
|
|
485
|
+
transport: "local-cli" as const,
|
|
486
|
+
hash: sha256(canonicalJson(aggregateIdentity)),
|
|
487
|
+
tool: exactQuery.identity.contract.tool,
|
|
488
|
+
})
|
|
489
|
+
: Object.freeze({
|
|
490
|
+
transport: exactQuery.identity.contract.transport,
|
|
491
|
+
hash: sha256(canonicalJson(aggregateIdentity)),
|
|
492
|
+
});
|
|
493
|
+
const omniQuery = createOmniProjectionQuery({
|
|
494
|
+
adapter: exactQuery.identity.adapter,
|
|
495
|
+
operation: "omni.source.v1",
|
|
496
|
+
input: aggregateIdentity,
|
|
497
|
+
inputHash: sha256(canonicalJson(aggregateIdentity)),
|
|
498
|
+
auth: exactQuery.identity.auth,
|
|
499
|
+
contract: omniContract,
|
|
500
|
+
}, environment);
|
|
501
|
+
return Object.freeze({
|
|
502
|
+
request,
|
|
503
|
+
invocation,
|
|
504
|
+
exactQuery,
|
|
505
|
+
resolution,
|
|
506
|
+
surfaceId: resolution.binding.surfaceId,
|
|
507
|
+
omni,
|
|
508
|
+
sourceIdentity,
|
|
509
|
+
omniQuery,
|
|
510
|
+
identityDescriptor: Object.freeze({
|
|
511
|
+
request: Object.freeze({
|
|
512
|
+
adapterId: request.adapterId,
|
|
513
|
+
operationId: request.operationId,
|
|
514
|
+
authId: request.authId,
|
|
515
|
+
inputHash: exactQuery.identity.inputHash,
|
|
516
|
+
}),
|
|
517
|
+
exactQueryKey: exactQuery.key,
|
|
518
|
+
omniQueryKey: omniQuery.key,
|
|
519
|
+
source: sourceIdentity,
|
|
520
|
+
materialization: omni.state === "supported"
|
|
521
|
+
? Object.freeze({
|
|
522
|
+
state: "supported",
|
|
523
|
+
schemaVersion: omni.schemaVersion,
|
|
524
|
+
materializerId: omni.materializerId,
|
|
525
|
+
materializerVersion: omni.materializerVersion,
|
|
526
|
+
})
|
|
527
|
+
: Object.freeze({ state: "unsupported", reason: omni.reason }),
|
|
528
|
+
}),
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function prepareSources(
|
|
533
|
+
requestValue: unknown,
|
|
534
|
+
options: OmniRuntimeOptions,
|
|
535
|
+
): {
|
|
536
|
+
readonly request: OmniViewRequestV1;
|
|
537
|
+
readonly sources: readonly PreparedOmniSource[];
|
|
538
|
+
readonly identity: OmniViewIdentityV1;
|
|
539
|
+
readonly environment: Environment;
|
|
540
|
+
readonly registry: ProviderPluginRegistry;
|
|
541
|
+
} {
|
|
542
|
+
const request = parseOmniViewRequestV1(requestValue);
|
|
543
|
+
const environment = options.environment ?? process.env;
|
|
544
|
+
const registry = options.registry ?? providerPluginRegistry;
|
|
545
|
+
const sources = Object.freeze(request.sources.map((source) =>
|
|
546
|
+
prepareSource(source, environment, registry)));
|
|
547
|
+
const sourceSetDigest = sha256(canonicalJson(
|
|
548
|
+
sources.map((source) => source.identityDescriptor),
|
|
549
|
+
));
|
|
550
|
+
return Object.freeze({
|
|
551
|
+
request,
|
|
552
|
+
sources,
|
|
553
|
+
identity: Object.freeze({
|
|
554
|
+
invocationDigest: sha256(canonicalJson(request)),
|
|
555
|
+
requestDigest: omniRequestDigest(request),
|
|
556
|
+
sourceSetDigest,
|
|
557
|
+
}),
|
|
558
|
+
environment,
|
|
559
|
+
registry,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
function exactStatus(
|
|
564
|
+
source: PreparedOmniSource,
|
|
565
|
+
options: OmniRuntimeOptions,
|
|
566
|
+
): {
|
|
567
|
+
readonly snapshot: ReadProjectionMaterializationSnapshot | null;
|
|
568
|
+
readonly status: OmniExactSourceStatusV1;
|
|
569
|
+
} {
|
|
570
|
+
try {
|
|
571
|
+
const snapshot = readReadProjectionForMaterialization(source.exactQuery, {
|
|
572
|
+
environment: options.environment ?? process.env,
|
|
573
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
574
|
+
...(options.freshForMs === undefined ? {} : { freshForMs: options.freshForMs }),
|
|
575
|
+
});
|
|
576
|
+
if (snapshot.status === "miss") {
|
|
577
|
+
return Object.freeze({
|
|
578
|
+
snapshot,
|
|
579
|
+
status: Object.freeze({ state: "miss", key: snapshot.key }),
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
return Object.freeze({
|
|
583
|
+
snapshot,
|
|
584
|
+
status: Object.freeze({
|
|
585
|
+
state: "hit",
|
|
586
|
+
key: snapshot.key,
|
|
587
|
+
dataRevision: snapshot.dataRevision,
|
|
588
|
+
validatedAt: snapshot.validatedAt,
|
|
589
|
+
ageMs: snapshot.ageMs,
|
|
590
|
+
freshness: snapshot.freshness,
|
|
591
|
+
}),
|
|
592
|
+
});
|
|
593
|
+
} catch {
|
|
594
|
+
return Object.freeze({
|
|
595
|
+
snapshot: null,
|
|
596
|
+
status: Object.freeze({
|
|
597
|
+
state: "error",
|
|
598
|
+
key: source.exactQuery.key,
|
|
599
|
+
reason: EXACT_READ_ERROR_REASON,
|
|
600
|
+
}),
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function sameExactHead(
|
|
606
|
+
left: ReadProjectionMaterializationSnapshot,
|
|
607
|
+
right: ReadProjectionMaterializationSnapshot,
|
|
608
|
+
): boolean {
|
|
609
|
+
return left.status === right.status
|
|
610
|
+
&& (
|
|
611
|
+
left.status === "miss"
|
|
612
|
+
|| (
|
|
613
|
+
right.status === "hit"
|
|
614
|
+
&& left.storageRevisionId === right.storageRevisionId
|
|
615
|
+
&& left.dataRevision === right.dataRevision
|
|
616
|
+
&& left.runId === right.runId
|
|
617
|
+
)
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function provenance(
|
|
622
|
+
source: PreparedOmniSource,
|
|
623
|
+
exact: Extract<ReadProjectionMaterializationSnapshot, { readonly status: "hit" }>,
|
|
624
|
+
): OmniPageProvenanceV1 {
|
|
625
|
+
if (source.omni?.state !== "supported") {
|
|
626
|
+
throw new Error("unsupported omni source cannot produce provenance");
|
|
627
|
+
}
|
|
628
|
+
return Object.freeze({
|
|
629
|
+
operation: source.request.operationId,
|
|
630
|
+
inputHash: source.exactQuery.identity.inputHash,
|
|
631
|
+
exactQueryKey: source.exactQuery.key,
|
|
632
|
+
exactDataRevision: exact.dataRevision,
|
|
633
|
+
validatedAt: exact.validatedAt,
|
|
634
|
+
startedAt: exact.startedAt,
|
|
635
|
+
finishedAt: exact.finishedAt,
|
|
636
|
+
runId: exact.runId,
|
|
637
|
+
materializerId: source.omni.materializerId,
|
|
638
|
+
materializerVersion: source.omni.materializerVersion,
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
function exactHeadFence(
|
|
643
|
+
source: PreparedOmniSource,
|
|
644
|
+
exact: Extract<ReadProjectionMaterializationSnapshot, { readonly status: "hit" }>,
|
|
645
|
+
): ReadProjectionExactHeadFence {
|
|
646
|
+
return Object.freeze({
|
|
647
|
+
query: source.exactQuery,
|
|
648
|
+
storageRevisionId: exact.storageRevisionId,
|
|
649
|
+
dataRevision: exact.dataRevision,
|
|
650
|
+
runId: exact.runId,
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
function assertCurrentAuthLifetime(
|
|
655
|
+
source: PreparedOmniSource,
|
|
656
|
+
environment: Environment,
|
|
657
|
+
): void {
|
|
658
|
+
const expected = source.invocation.readProjectionAuthIdentityHash;
|
|
659
|
+
if (expected === undefined) {
|
|
660
|
+
throw new Error("prepared omni source is missing its auth lifetime identity");
|
|
661
|
+
}
|
|
662
|
+
const snapshot = loadAuthSnapshotIfPresent(source.invocation.auth.id, environment);
|
|
663
|
+
if (snapshot === null) {
|
|
664
|
+
throw new Error(`auth locator ${source.invocation.auth.id} was removed`);
|
|
665
|
+
}
|
|
666
|
+
const contentHash = sha256(canonicalJson(snapshot.auth));
|
|
667
|
+
const current = projectionAuthIdentityHash(
|
|
668
|
+
snapshot.auth.id,
|
|
669
|
+
contentHash,
|
|
670
|
+
environment,
|
|
671
|
+
);
|
|
672
|
+
if (
|
|
673
|
+
current !== expected
|
|
674
|
+
|| source.exactQuery.identity.auth.hash !== expected
|
|
675
|
+
|| snapshot.auth.subject !== source.invocation.auth.subject
|
|
676
|
+
) {
|
|
677
|
+
throw new Error(
|
|
678
|
+
`auth locator ${source.invocation.auth.id} changed since this omni source was prepared`,
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
function markDrift(
|
|
684
|
+
source: PreparedOmniSource,
|
|
685
|
+
exact: Extract<ReadProjectionMaterializationSnapshot, { readonly status: "hit" }>,
|
|
686
|
+
error: unknown,
|
|
687
|
+
options: OmniRuntimeOptions,
|
|
688
|
+
code: "materializer-drift" | "capacity-exceeded",
|
|
689
|
+
): void {
|
|
690
|
+
if (source.omniQuery === null || source.sourceIdentity === null) {
|
|
691
|
+
throw new Error("unsupported omni source cannot retain drift state");
|
|
692
|
+
}
|
|
693
|
+
const privateError = privateDriftError(error);
|
|
694
|
+
reduceOmniProjection(source.omniQuery, (current) =>
|
|
695
|
+
markOmniSourceDriftV1(current, {
|
|
696
|
+
source: source.sourceIdentity!,
|
|
697
|
+
exactQueryKey: source.exactQuery.key,
|
|
698
|
+
exactDataRevision: exact.dataRevision,
|
|
699
|
+
failedAt: (options.now ?? new Date()).toISOString(),
|
|
700
|
+
error: privateError,
|
|
701
|
+
code,
|
|
702
|
+
}), {
|
|
703
|
+
environment: options.environment ?? process.env,
|
|
704
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
705
|
+
exactHead: exactHeadFence(source, exact),
|
|
706
|
+
assertCurrent: () => assertCurrentAuthLifetime(
|
|
707
|
+
source,
|
|
708
|
+
options.environment ?? process.env,
|
|
709
|
+
),
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function materializeCurrentExact(
|
|
714
|
+
source: PreparedOmniSource,
|
|
715
|
+
options: OmniRuntimeOptions,
|
|
716
|
+
):
|
|
717
|
+
| { readonly state: "missing" }
|
|
718
|
+
| {
|
|
719
|
+
readonly state: "materialized";
|
|
720
|
+
readonly page: ReturnType<typeof parseMaterializedPageV1>;
|
|
721
|
+
}
|
|
722
|
+
| { readonly state: "drift" } {
|
|
723
|
+
if (
|
|
724
|
+
source.omni?.state !== "supported"
|
|
725
|
+
|| source.omniQuery === null
|
|
726
|
+
|| source.sourceIdentity === null
|
|
727
|
+
) return Object.freeze({ state: "missing" });
|
|
728
|
+
for (let attempt = 0; attempt < MAX_MATERIALIZATION_SETTLEMENT_ATTEMPTS; attempt += 1) {
|
|
729
|
+
const before = readReadProjectionForMaterialization(source.exactQuery, {
|
|
730
|
+
environment: options.environment ?? process.env,
|
|
731
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
732
|
+
...(options.freshForMs === undefined ? {} : { freshForMs: options.freshForMs }),
|
|
733
|
+
});
|
|
734
|
+
if (before.status === "miss") return Object.freeze({ state: "missing" });
|
|
735
|
+
let page: ReturnType<typeof parseMaterializedPageV1> | null = null;
|
|
736
|
+
let materializerError: unknown = null;
|
|
737
|
+
let driftCode: "materializer-drift" | "capacity-exceeded" =
|
|
738
|
+
"materializer-drift";
|
|
739
|
+
let materializedOutput: unknown;
|
|
740
|
+
try {
|
|
741
|
+
materializedOutput = source.omni.materialize(
|
|
742
|
+
source.invocation.input,
|
|
743
|
+
before.output,
|
|
744
|
+
);
|
|
745
|
+
} catch (error) {
|
|
746
|
+
materializerError = error;
|
|
747
|
+
}
|
|
748
|
+
if (materializerError === null) {
|
|
749
|
+
try {
|
|
750
|
+
page = parseMaterializedPageV1(materializedOutput);
|
|
751
|
+
} catch (error) {
|
|
752
|
+
materializerError = error;
|
|
753
|
+
driftCode = internalDriftCode(error);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
const fenced = readReadProjectionForMaterialization(source.exactQuery, {
|
|
757
|
+
environment: options.environment ?? process.env,
|
|
758
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
759
|
+
...(options.freshForMs === undefined ? {} : { freshForMs: options.freshForMs }),
|
|
760
|
+
});
|
|
761
|
+
if (!sameExactHead(before, fenced)) continue;
|
|
762
|
+
if (materializerError !== null || page === null) {
|
|
763
|
+
try {
|
|
764
|
+
markDrift(source, before, materializerError, options, driftCode);
|
|
765
|
+
} catch (error) {
|
|
766
|
+
const changed = readReadProjectionForMaterialization(source.exactQuery, {
|
|
767
|
+
environment: options.environment ?? process.env,
|
|
768
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
769
|
+
...(options.freshForMs === undefined
|
|
770
|
+
? {}
|
|
771
|
+
: { freshForMs: options.freshForMs }),
|
|
772
|
+
});
|
|
773
|
+
if (!sameExactHead(before, changed)) continue;
|
|
774
|
+
throw error;
|
|
775
|
+
}
|
|
776
|
+
} else {
|
|
777
|
+
try {
|
|
778
|
+
const pageProvenance = provenance(source, before);
|
|
779
|
+
reduceOmniProjection(source.omniQuery, (current) =>
|
|
780
|
+
reduceOmniSourceStateV1(current, page, {
|
|
781
|
+
source: source.sourceIdentity!,
|
|
782
|
+
provenance: pageProvenance,
|
|
783
|
+
}), {
|
|
784
|
+
environment: options.environment ?? process.env,
|
|
785
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
786
|
+
exactHead: exactHeadFence(source, before),
|
|
787
|
+
assertCurrent: () => assertCurrentAuthLifetime(
|
|
788
|
+
source,
|
|
789
|
+
options.environment ?? process.env,
|
|
790
|
+
),
|
|
791
|
+
});
|
|
792
|
+
} catch (error) {
|
|
793
|
+
const changed = readReadProjectionForMaterialization(source.exactQuery, {
|
|
794
|
+
environment: options.environment ?? process.env,
|
|
795
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
796
|
+
...(options.freshForMs === undefined
|
|
797
|
+
? {}
|
|
798
|
+
: { freshForMs: options.freshForMs }),
|
|
799
|
+
});
|
|
800
|
+
if (!sameExactHead(before, changed)) continue;
|
|
801
|
+
markDrift(
|
|
802
|
+
source,
|
|
803
|
+
before,
|
|
804
|
+
error,
|
|
805
|
+
options,
|
|
806
|
+
internalDriftCode(error),
|
|
807
|
+
);
|
|
808
|
+
materializerError = error;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
const after = readReadProjectionForMaterialization(source.exactQuery, {
|
|
812
|
+
environment: options.environment ?? process.env,
|
|
813
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
814
|
+
...(options.freshForMs === undefined ? {} : { freshForMs: options.freshForMs }),
|
|
815
|
+
});
|
|
816
|
+
if (!sameExactHead(before, after)) continue;
|
|
817
|
+
return materializerError === null && page !== null
|
|
818
|
+
? Object.freeze({ state: "materialized" as const, page })
|
|
819
|
+
: Object.freeze({ state: "drift" as const });
|
|
820
|
+
}
|
|
821
|
+
throw new Error(
|
|
822
|
+
`exact projection ${source.exactQuery.key} did not settle while its normalized derivative was being updated`,
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
function prepareContinuationSource(
|
|
827
|
+
parent: PreparedOmniSource,
|
|
828
|
+
nextInput: Readonly<Record<string, OmniJsonValue>>,
|
|
829
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
830
|
+
): PreparedOmniSource {
|
|
831
|
+
const continuation = prepareSource(Object.freeze({
|
|
832
|
+
adapterId: parent.request.adapterId,
|
|
833
|
+
operationId: parent.request.operationId,
|
|
834
|
+
authId: parent.request.authId,
|
|
835
|
+
input: nextInput,
|
|
836
|
+
}), prepared.environment, prepared.registry);
|
|
837
|
+
if (
|
|
838
|
+
parent.omni?.state !== "supported"
|
|
839
|
+
|| continuation.omni?.state !== "supported"
|
|
840
|
+
|| parent.omni.materializerId !== continuation.omni.materializerId
|
|
841
|
+
|| parent.omni.materializerVersion !== continuation.omni.materializerVersion
|
|
842
|
+
|| parent.omniQuery === null
|
|
843
|
+
|| continuation.omniQuery === null
|
|
844
|
+
|| parent.omniQuery.key !== continuation.omniQuery.key
|
|
845
|
+
|| parent.sourceIdentity === null
|
|
846
|
+
|| continuation.sourceIdentity === null
|
|
847
|
+
|| canonicalJson(parent.sourceIdentity)
|
|
848
|
+
!== canonicalJson(continuation.sourceIdentity)
|
|
849
|
+
) {
|
|
850
|
+
throw new Error(
|
|
851
|
+
"provider continuation crossed its source, materializer, or auth identity",
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
return continuation;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
function rebuildExactContinuationChain(
|
|
858
|
+
root: PreparedOmniSource,
|
|
859
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
860
|
+
options: OmniRuntimeOptions,
|
|
861
|
+
): OmniSourceUpdateError | undefined {
|
|
862
|
+
let current = root;
|
|
863
|
+
let materialized: OmniMaterializationResult;
|
|
864
|
+
try {
|
|
865
|
+
materialized = materializeCurrentExact(current, options);
|
|
866
|
+
} catch {
|
|
867
|
+
return sourceUpdateError(current, NORMALIZATION_UPDATE_ERROR_REASON);
|
|
868
|
+
}
|
|
869
|
+
const guard = createOmniContinuationGuard(root.exactQuery.key);
|
|
870
|
+
for (; materialized.state === "materialized";) {
|
|
871
|
+
const nextInput = materialized.page.cursor.nextInput;
|
|
872
|
+
if (nextInput === null) return undefined;
|
|
873
|
+
const capacityReason = guard.beforeNext();
|
|
874
|
+
if (capacityReason !== null) return sourceUpdateError(current, capacityReason);
|
|
875
|
+
let continuation: PreparedOmniSource;
|
|
876
|
+
try {
|
|
877
|
+
continuation = prepareContinuationSource(root, nextInput, prepared);
|
|
878
|
+
} catch {
|
|
879
|
+
return sourceUpdateError(current, CONTINUATION_PREPARATION_ERROR_REASON);
|
|
880
|
+
}
|
|
881
|
+
const repeatedReason = guard.observe(continuation.exactQuery.key);
|
|
882
|
+
if (repeatedReason !== null) {
|
|
883
|
+
return sourceUpdateError(continuation, repeatedReason);
|
|
884
|
+
}
|
|
885
|
+
current = continuation;
|
|
886
|
+
try {
|
|
887
|
+
materialized = materializeCurrentExact(current, options);
|
|
888
|
+
} catch {
|
|
889
|
+
return sourceUpdateError(current, NORMALIZATION_UPDATE_ERROR_REASON);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return undefined;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
type OmniSourceRevalidation =
|
|
896
|
+
| {
|
|
897
|
+
readonly state: "observed";
|
|
898
|
+
readonly materialized: OmniMaterializationResult;
|
|
899
|
+
readonly error?: string;
|
|
900
|
+
}
|
|
901
|
+
| {
|
|
902
|
+
readonly state: "failed";
|
|
903
|
+
readonly error: string;
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
async function revalidateOneOmniSource(
|
|
907
|
+
source: PreparedOmniSource,
|
|
908
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
909
|
+
options: OmniLiveRuntimeOptions,
|
|
910
|
+
): Promise<OmniSourceRevalidation> {
|
|
911
|
+
let live;
|
|
912
|
+
try {
|
|
913
|
+
live = await revalidatePreparedCapability(source.invocation, {
|
|
914
|
+
environment: prepared.environment,
|
|
915
|
+
registry: prepared.registry,
|
|
916
|
+
headed: options.headed ?? false,
|
|
917
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
918
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
919
|
+
...(options.freshForMs === undefined
|
|
920
|
+
? {}
|
|
921
|
+
: { freshForMs: options.freshForMs }),
|
|
922
|
+
...(options.executeRead === undefined
|
|
923
|
+
? {}
|
|
924
|
+
: { executeRead: options.executeRead }),
|
|
925
|
+
});
|
|
926
|
+
} catch {
|
|
927
|
+
throwIfAborted(options.signal);
|
|
928
|
+
return Object.freeze({
|
|
929
|
+
state: "failed" as const,
|
|
930
|
+
error: PROVIDER_READ_ERROR_REASON,
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
throwIfAborted(options.signal);
|
|
934
|
+
const error = live.live.receipt.status !== "succeeded"
|
|
935
|
+
? PROVIDER_READ_ERROR_REASON
|
|
936
|
+
: live.cache.status === "error"
|
|
937
|
+
? EXACT_PUBLICATION_ERROR_REASON
|
|
938
|
+
: undefined;
|
|
939
|
+
if (error !== undefined) {
|
|
940
|
+
return Object.freeze({ state: "failed" as const, error });
|
|
941
|
+
}
|
|
942
|
+
let materialized: OmniMaterializationResult;
|
|
943
|
+
try {
|
|
944
|
+
materialized = materializeCurrentExact(source, options);
|
|
945
|
+
} catch {
|
|
946
|
+
throwIfAborted(options.signal);
|
|
947
|
+
return Object.freeze({
|
|
948
|
+
state: "failed" as const,
|
|
949
|
+
error: NORMALIZATION_UPDATE_ERROR_REASON,
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
return Object.freeze({
|
|
953
|
+
state: "observed" as const,
|
|
954
|
+
materialized,
|
|
955
|
+
...(error === undefined ? {} : { error }),
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
async function revalidateOmniSourceChain(
|
|
960
|
+
root: PreparedOmniSource,
|
|
961
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
962
|
+
options: OmniLiveRuntimeOptions,
|
|
963
|
+
): Promise<OmniSourceUpdateError | undefined> {
|
|
964
|
+
const guard = createOmniContinuationGuard(
|
|
965
|
+
root.exactQuery.key,
|
|
966
|
+
options.sourcePageLimit,
|
|
967
|
+
);
|
|
968
|
+
let observed = await revalidateOneOmniSource(root, prepared, options);
|
|
969
|
+
throwIfAborted(options.signal);
|
|
970
|
+
if (observed.state === "failed") {
|
|
971
|
+
return sourceUpdateError(root, observed.error);
|
|
972
|
+
}
|
|
973
|
+
if (observed.error !== undefined) {
|
|
974
|
+
return sourceUpdateError(root, observed.error);
|
|
975
|
+
}
|
|
976
|
+
let current = root;
|
|
977
|
+
for (; observed.materialized.state === "materialized";) {
|
|
978
|
+
throwIfAborted(options.signal);
|
|
979
|
+
const nextInput = observed.materialized.page.cursor.nextInput;
|
|
980
|
+
if (nextInput === null) return undefined;
|
|
981
|
+
const capacityReason = guard.beforeNext();
|
|
982
|
+
if (capacityReason !== null) return sourceUpdateError(current, capacityReason);
|
|
983
|
+
let continuation: PreparedOmniSource;
|
|
984
|
+
try {
|
|
985
|
+
continuation = prepareContinuationSource(root, nextInput, prepared);
|
|
986
|
+
} catch {
|
|
987
|
+
return sourceUpdateError(current, CONTINUATION_PREPARATION_ERROR_REASON);
|
|
988
|
+
}
|
|
989
|
+
const repeatedReason = guard.observe(continuation.exactQuery.key);
|
|
990
|
+
if (repeatedReason !== null) {
|
|
991
|
+
return Object.freeze({
|
|
992
|
+
exactQueryKey: continuation.exactQuery.key,
|
|
993
|
+
reason: repeatedReason,
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
current = continuation;
|
|
997
|
+
observed = await revalidateOneOmniSource(continuation, prepared, options);
|
|
998
|
+
throwIfAborted(options.signal);
|
|
999
|
+
if (observed.state === "failed") {
|
|
1000
|
+
return sourceUpdateError(continuation, observed.error);
|
|
1001
|
+
}
|
|
1002
|
+
if (observed.error !== undefined) {
|
|
1003
|
+
return sourceUpdateError(continuation, observed.error);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
return undefined;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
type StoredOmniChainObservation = {
|
|
1010
|
+
readonly coverage: OmniSourceCoverageV1;
|
|
1011
|
+
readonly frontiers: readonly {
|
|
1012
|
+
readonly exactQueryKey: string;
|
|
1013
|
+
readonly status: OmniNormalizationStatusV1;
|
|
1014
|
+
}[];
|
|
1015
|
+
readonly exact: readonly {
|
|
1016
|
+
readonly exactQueryKey: string;
|
|
1017
|
+
readonly status: OmniExactSourceStatusV1;
|
|
1018
|
+
}[];
|
|
1019
|
+
readonly issue: StoredOmniStaleEvidence | null;
|
|
1020
|
+
};
|
|
1021
|
+
|
|
1022
|
+
type StoredOmniStaleEvidence = {
|
|
1023
|
+
readonly exactQueryKey: string;
|
|
1024
|
+
readonly exactDataRevision: string | null;
|
|
1025
|
+
readonly normalizedExactDataRevision: string | null;
|
|
1026
|
+
readonly lastGoodAt: string | null;
|
|
1027
|
+
readonly reason: string;
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
function normalizationFrontier(
|
|
1031
|
+
state: OmniSourceStateV1,
|
|
1032
|
+
exactQueryKey: string,
|
|
1033
|
+
) {
|
|
1034
|
+
return state.normalization.find((entry) =>
|
|
1035
|
+
entry.exactQueryKey === exactQueryKey) ?? null;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
function pageForExactQuery(
|
|
1039
|
+
state: OmniSourceStateV1,
|
|
1040
|
+
exactQueryKey: string,
|
|
1041
|
+
): OmniStoredPageV1 | null {
|
|
1042
|
+
const pages = state.pages.filter((page) =>
|
|
1043
|
+
page.provenance.exactQueryKey === exactQueryKey);
|
|
1044
|
+
if (pages.length > 1) {
|
|
1045
|
+
throw new Error(
|
|
1046
|
+
"normalized state retained multiple pages for one exact provider query",
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
return pages[0] ?? null;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
function staleEvidence(
|
|
1053
|
+
exactQueryKey: string,
|
|
1054
|
+
frontier: ReturnType<typeof normalizationFrontier>,
|
|
1055
|
+
exact: OmniExactSourceStatusV1,
|
|
1056
|
+
reason: string,
|
|
1057
|
+
options: { readonly omitExactRevision?: boolean } = {},
|
|
1058
|
+
): StoredOmniStaleEvidence {
|
|
1059
|
+
const normalizedExactDataRevision = frontier === null
|
|
1060
|
+
? null
|
|
1061
|
+
: frontier.status.state === "ready"
|
|
1062
|
+
? frontier.status.exactDataRevision
|
|
1063
|
+
: frontier.status.lastGoodExactDataRevision;
|
|
1064
|
+
return Object.freeze({
|
|
1065
|
+
exactQueryKey,
|
|
1066
|
+
exactDataRevision: options.omitExactRevision === true
|
|
1067
|
+
? null
|
|
1068
|
+
: exact.state === "hit"
|
|
1069
|
+
? exact.dataRevision
|
|
1070
|
+
: null,
|
|
1071
|
+
normalizedExactDataRevision,
|
|
1072
|
+
lastGoodAt: frontier?.status.lastGoodAt ?? null,
|
|
1073
|
+
reason: boundedError(reason),
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
function observeStoredOmniChain(
|
|
1078
|
+
root: PreparedOmniSource,
|
|
1079
|
+
state: OmniSourceStateV1,
|
|
1080
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
1081
|
+
options: OmniRuntimeOptions,
|
|
1082
|
+
rootExact: OmniExactSourceStatusV1,
|
|
1083
|
+
): StoredOmniChainObservation {
|
|
1084
|
+
let current = root;
|
|
1085
|
+
const visited = new Set<string>();
|
|
1086
|
+
const frontiers: {
|
|
1087
|
+
readonly exactQueryKey: string;
|
|
1088
|
+
readonly status: OmniNormalizationStatusV1;
|
|
1089
|
+
}[] = [];
|
|
1090
|
+
const exact: {
|
|
1091
|
+
readonly exactQueryKey: string;
|
|
1092
|
+
readonly status: OmniExactSourceStatusV1;
|
|
1093
|
+
}[] = [];
|
|
1094
|
+
let rootPage: OmniStoredPageV1 | null = null;
|
|
1095
|
+
let issue: StoredOmniStaleEvidence | null = null;
|
|
1096
|
+
for (let pages = 0; pages < OMNI_MAX_SOURCE_PAGES; pages += 1) {
|
|
1097
|
+
if (visited.has(current.exactQuery.key)) {
|
|
1098
|
+
const reason = "normalized provider continuation repeats an exact page query";
|
|
1099
|
+
const frontier = normalizationFrontier(state, current.exactQuery.key);
|
|
1100
|
+
const currentExact = exact.find((entry) =>
|
|
1101
|
+
entry.exactQueryKey === current.exactQuery.key)?.status
|
|
1102
|
+
?? exactStatus(current, options).status;
|
|
1103
|
+
return Object.freeze({
|
|
1104
|
+
coverage: Object.freeze({ state: "unavailable" as const, reason }),
|
|
1105
|
+
frontiers: Object.freeze(frontiers),
|
|
1106
|
+
exact: Object.freeze(exact),
|
|
1107
|
+
issue: staleEvidence(
|
|
1108
|
+
current.exactQuery.key,
|
|
1109
|
+
frontier,
|
|
1110
|
+
currentExact,
|
|
1111
|
+
reason,
|
|
1112
|
+
),
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
visited.add(current.exactQuery.key);
|
|
1116
|
+
const frontier = normalizationFrontier(state, current.exactQuery.key);
|
|
1117
|
+
const page = pageForExactQuery(state, current.exactQuery.key);
|
|
1118
|
+
if (frontier !== null) frontiers.push(frontier);
|
|
1119
|
+
const currentExact = current.exactQuery.key === root.exactQuery.key
|
|
1120
|
+
? rootExact
|
|
1121
|
+
: exactStatus(current, options).status;
|
|
1122
|
+
exact.push(Object.freeze({
|
|
1123
|
+
exactQueryKey: current.exactQuery.key,
|
|
1124
|
+
status: currentExact,
|
|
1125
|
+
}));
|
|
1126
|
+
if (frontier?.status.state === "ready") {
|
|
1127
|
+
if (
|
|
1128
|
+
current.exactQuery.key !== root.exactQuery.key
|
|
1129
|
+
&& currentExact.state === "hit"
|
|
1130
|
+
&& currentExact.freshness.state === "stale"
|
|
1131
|
+
) {
|
|
1132
|
+
issue ??= staleEvidence(
|
|
1133
|
+
current.exactQuery.key,
|
|
1134
|
+
frontier,
|
|
1135
|
+
currentExact,
|
|
1136
|
+
"a provider continuation exact snapshot is stale",
|
|
1137
|
+
);
|
|
1138
|
+
} else if (
|
|
1139
|
+
currentExact.state === "hit"
|
|
1140
|
+
&& currentExact.dataRevision !== frontier.status.exactDataRevision
|
|
1141
|
+
) {
|
|
1142
|
+
issue ??= staleEvidence(
|
|
1143
|
+
current.exactQuery.key,
|
|
1144
|
+
frontier,
|
|
1145
|
+
currentExact,
|
|
1146
|
+
current.exactQuery.key === root.exactQuery.key
|
|
1147
|
+
? "the normalized derivative has not observed the current exact revision"
|
|
1148
|
+
: "a provider continuation exact snapshot is newer than its normalized frontier",
|
|
1149
|
+
);
|
|
1150
|
+
} else if (currentExact.state === "miss") {
|
|
1151
|
+
issue ??= staleEvidence(
|
|
1152
|
+
current.exactQuery.key,
|
|
1153
|
+
frontier,
|
|
1154
|
+
currentExact,
|
|
1155
|
+
current.exactQuery.key === root.exactQuery.key
|
|
1156
|
+
? "the exact provider snapshot is unavailable"
|
|
1157
|
+
: "a normalized provider continuation has no exact snapshot",
|
|
1158
|
+
);
|
|
1159
|
+
} else if (currentExact.state === "error") {
|
|
1160
|
+
issue ??= staleEvidence(
|
|
1161
|
+
current.exactQuery.key,
|
|
1162
|
+
frontier,
|
|
1163
|
+
currentExact,
|
|
1164
|
+
currentExact.reason,
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
if (frontier === null || page === null) {
|
|
1169
|
+
if (frontier?.status.state !== "drift") {
|
|
1170
|
+
issue ??= staleEvidence(
|
|
1171
|
+
current.exactQuery.key,
|
|
1172
|
+
frontier,
|
|
1173
|
+
currentExact,
|
|
1174
|
+
frontier === null
|
|
1175
|
+
? "a provider continuation has not reached a normalized frontier"
|
|
1176
|
+
: "a normalized provider continuation has no retained page",
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1179
|
+
if (rootPage === null) {
|
|
1180
|
+
const reason = frontier === null
|
|
1181
|
+
? "the requested exact query has no normalized frontier"
|
|
1182
|
+
: "the requested exact query has no retained normalized page";
|
|
1183
|
+
return Object.freeze({
|
|
1184
|
+
coverage: Object.freeze({ state: "unavailable" as const, reason }),
|
|
1185
|
+
frontiers: Object.freeze(frontiers),
|
|
1186
|
+
exact: Object.freeze(exact),
|
|
1187
|
+
issue,
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
return Object.freeze({
|
|
1191
|
+
coverage: Object.freeze({
|
|
1192
|
+
state: "observed" as const,
|
|
1193
|
+
kind: rootPage.completeness.kind,
|
|
1194
|
+
continuation: "pending" as const,
|
|
1195
|
+
reason: publicCoverageReason(rootPage.completeness.kind),
|
|
1196
|
+
}),
|
|
1197
|
+
frontiers: Object.freeze(frontiers),
|
|
1198
|
+
exact: Object.freeze(exact),
|
|
1199
|
+
issue,
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
rootPage ??= page;
|
|
1203
|
+
if (page.cursor.nextInput === null) {
|
|
1204
|
+
const continuation = page.completeness.kind === "complete"
|
|
1205
|
+
|| page.completeness.kind === "page"
|
|
1206
|
+
? "none" as const
|
|
1207
|
+
: "unavailable" as const;
|
|
1208
|
+
return Object.freeze({
|
|
1209
|
+
coverage: Object.freeze({
|
|
1210
|
+
state: "observed" as const,
|
|
1211
|
+
kind: rootPage.completeness.kind,
|
|
1212
|
+
continuation,
|
|
1213
|
+
reason: publicCoverageReason(rootPage.completeness.kind),
|
|
1214
|
+
}),
|
|
1215
|
+
frontiers: Object.freeze(frontiers),
|
|
1216
|
+
exact: Object.freeze(exact),
|
|
1217
|
+
issue,
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
try {
|
|
1221
|
+
current = prepareContinuationSource(root, page.cursor.nextInput, prepared);
|
|
1222
|
+
} catch {
|
|
1223
|
+
const reason = CONTINUATION_PREPARATION_ERROR_REASON;
|
|
1224
|
+
return Object.freeze({
|
|
1225
|
+
coverage: Object.freeze({ state: "unavailable" as const, reason }),
|
|
1226
|
+
frontiers: Object.freeze(frontiers),
|
|
1227
|
+
exact: Object.freeze(exact),
|
|
1228
|
+
issue: issue ?? staleEvidence(
|
|
1229
|
+
current.exactQuery.key,
|
|
1230
|
+
frontier,
|
|
1231
|
+
currentExact,
|
|
1232
|
+
reason,
|
|
1233
|
+
),
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
const reason = `normalized provider continuation exceeds the ${String(OMNI_MAX_SOURCE_PAGES)}-page capacity`;
|
|
1238
|
+
return Object.freeze({
|
|
1239
|
+
coverage: Object.freeze({ state: "unavailable" as const, reason }),
|
|
1240
|
+
frontiers: Object.freeze(frontiers),
|
|
1241
|
+
exact: Object.freeze(exact),
|
|
1242
|
+
issue: issue ?? staleEvidence(
|
|
1243
|
+
current.exactQuery.key,
|
|
1244
|
+
normalizationFrontier(state, current.exactQuery.key),
|
|
1245
|
+
exactStatus(current, options).status,
|
|
1246
|
+
reason,
|
|
1247
|
+
),
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
function sourceState(
|
|
1252
|
+
source: PreparedOmniSource,
|
|
1253
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
1254
|
+
options: OmniRuntimeOptions,
|
|
1255
|
+
updateError: OmniSourceUpdateError | undefined,
|
|
1256
|
+
): {
|
|
1257
|
+
readonly status: OmniViewSourceStatusV1;
|
|
1258
|
+
readonly state: OmniSourceStateV1 | null;
|
|
1259
|
+
} {
|
|
1260
|
+
const exact = exactStatus(source, options).status;
|
|
1261
|
+
const common = Object.freeze({
|
|
1262
|
+
adapterId: source.request.adapterId,
|
|
1263
|
+
operationId: source.request.operationId,
|
|
1264
|
+
authId: source.request.authId,
|
|
1265
|
+
requestInputHash: sha256(canonicalJson(source.request.input)),
|
|
1266
|
+
projectionInputHash: source.exactQuery.identity.inputHash,
|
|
1267
|
+
normalizationDataRevision: null,
|
|
1268
|
+
surfaceId: source.surfaceId,
|
|
1269
|
+
exact,
|
|
1270
|
+
});
|
|
1271
|
+
if (source.omni === null || source.omni.state === "unsupported") {
|
|
1272
|
+
const reason = source.omni?.state === "unsupported"
|
|
1273
|
+
? source.omni.reason
|
|
1274
|
+
: "operation is not backed by a reviewed provider plugin materializer";
|
|
1275
|
+
return Object.freeze({
|
|
1276
|
+
state: null,
|
|
1277
|
+
status: Object.freeze({
|
|
1278
|
+
...common,
|
|
1279
|
+
normalization: Object.freeze({
|
|
1280
|
+
state: "unsupported",
|
|
1281
|
+
reason,
|
|
1282
|
+
}),
|
|
1283
|
+
coverage: Object.freeze({ state: "unavailable", reason }),
|
|
1284
|
+
}),
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
if (source.omniQuery === null) throw new Error("supported omni source has no private query");
|
|
1288
|
+
let cached;
|
|
1289
|
+
try {
|
|
1290
|
+
cached = readOmniProjection(source.omniQuery, {
|
|
1291
|
+
environment: options.environment ?? process.env,
|
|
1292
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
1293
|
+
...(options.freshForMs === undefined ? {} : { freshForMs: options.freshForMs }),
|
|
1294
|
+
});
|
|
1295
|
+
} catch {
|
|
1296
|
+
const reason = NORMALIZED_STATE_READ_ERROR_REASON;
|
|
1297
|
+
return Object.freeze({
|
|
1298
|
+
state: null,
|
|
1299
|
+
status: Object.freeze({
|
|
1300
|
+
...common,
|
|
1301
|
+
normalization: Object.freeze({
|
|
1302
|
+
state: "error",
|
|
1303
|
+
reason,
|
|
1304
|
+
lastGoodAt: null,
|
|
1305
|
+
}),
|
|
1306
|
+
coverage: Object.freeze({ state: "unavailable", reason }),
|
|
1307
|
+
}),
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
if (cached.status === "miss") {
|
|
1311
|
+
const reason = updateError?.reason
|
|
1312
|
+
?? "the requested source has no normalized state";
|
|
1313
|
+
return Object.freeze({
|
|
1314
|
+
state: null,
|
|
1315
|
+
status: Object.freeze({
|
|
1316
|
+
...common,
|
|
1317
|
+
normalization: updateError === undefined
|
|
1318
|
+
? Object.freeze({ state: "missing" })
|
|
1319
|
+
: Object.freeze({
|
|
1320
|
+
state: "error",
|
|
1321
|
+
reason: updateError.reason,
|
|
1322
|
+
lastGoodAt: null,
|
|
1323
|
+
}),
|
|
1324
|
+
coverage: Object.freeze({ state: "unavailable", reason }),
|
|
1325
|
+
}),
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
const normalizedCommon = Object.freeze({
|
|
1329
|
+
...common,
|
|
1330
|
+
normalizationDataRevision: cached.dataRevision,
|
|
1331
|
+
});
|
|
1332
|
+
let state: OmniSourceStateV1;
|
|
1333
|
+
try {
|
|
1334
|
+
state = parseOmniSourceStateV1(cached.output);
|
|
1335
|
+
} catch {
|
|
1336
|
+
const reason = NORMALIZED_STATE_PARSE_ERROR_REASON;
|
|
1337
|
+
return Object.freeze({
|
|
1338
|
+
state: null,
|
|
1339
|
+
status: Object.freeze({
|
|
1340
|
+
...normalizedCommon,
|
|
1341
|
+
normalization: Object.freeze({
|
|
1342
|
+
state: "error",
|
|
1343
|
+
reason,
|
|
1344
|
+
lastGoodAt: null,
|
|
1345
|
+
}),
|
|
1346
|
+
coverage: Object.freeze({ state: "unavailable", reason }),
|
|
1347
|
+
}),
|
|
1348
|
+
});
|
|
1349
|
+
}
|
|
1350
|
+
let chain: StoredOmniChainObservation;
|
|
1351
|
+
try {
|
|
1352
|
+
chain = observeStoredOmniChain(source, state, prepared, options, exact);
|
|
1353
|
+
} catch {
|
|
1354
|
+
const reason = NORMALIZED_STATE_OBSERVE_ERROR_REASON;
|
|
1355
|
+
return Object.freeze({
|
|
1356
|
+
state: null,
|
|
1357
|
+
status: Object.freeze({
|
|
1358
|
+
...normalizedCommon,
|
|
1359
|
+
normalization: Object.freeze({
|
|
1360
|
+
state: "error",
|
|
1361
|
+
reason,
|
|
1362
|
+
lastGoodAt: null,
|
|
1363
|
+
}),
|
|
1364
|
+
coverage: Object.freeze({ state: "unavailable", reason }),
|
|
1365
|
+
}),
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1368
|
+
const rootFrontier = normalizationFrontier(state, source.exactQuery.key);
|
|
1369
|
+
const exactForQuery = (exactQueryKey: string): OmniExactSourceStatusV1 =>
|
|
1370
|
+
exactQueryKey === source.exactQuery.key
|
|
1371
|
+
? exact
|
|
1372
|
+
: chain.exact.find((entry) =>
|
|
1373
|
+
entry.exactQueryKey === exactQueryKey)?.status
|
|
1374
|
+
?? Object.freeze({ state: "miss", key: exactQueryKey });
|
|
1375
|
+
let normalization: OmniNormalizationSourceStatusV1;
|
|
1376
|
+
const drift = chain.frontiers.find((entry) =>
|
|
1377
|
+
entry.status.state === "drift");
|
|
1378
|
+
const chainPosition = (exactQueryKey: string): number => {
|
|
1379
|
+
const index = chain.exact.findIndex((entry) =>
|
|
1380
|
+
entry.exactQueryKey === exactQueryKey);
|
|
1381
|
+
if (index >= 0) return index;
|
|
1382
|
+
return exactQueryKey === source.exactQuery.key ? 0 : chain.exact.length;
|
|
1383
|
+
};
|
|
1384
|
+
const driftPosition = drift === undefined
|
|
1385
|
+
? Number.POSITIVE_INFINITY
|
|
1386
|
+
: chainPosition(drift.exactQueryKey);
|
|
1387
|
+
const issuePosition = chain.issue === null
|
|
1388
|
+
? Number.POSITIVE_INFINITY
|
|
1389
|
+
: chainPosition(chain.issue.exactQueryKey);
|
|
1390
|
+
const updatePosition = updateError === undefined
|
|
1391
|
+
? Number.POSITIVE_INFINITY
|
|
1392
|
+
: chainPosition(updateError.exactQueryKey);
|
|
1393
|
+
if (
|
|
1394
|
+
drift?.status.state === "drift"
|
|
1395
|
+
&& driftPosition <= issuePosition
|
|
1396
|
+
&& driftPosition < updatePosition
|
|
1397
|
+
) {
|
|
1398
|
+
const driftExact = exactForQuery(drift.exactQueryKey);
|
|
1399
|
+
normalization = Object.freeze({
|
|
1400
|
+
state: "retained-after-drift",
|
|
1401
|
+
exactQueryKey: drift.exactQueryKey,
|
|
1402
|
+
reason: publicDriftReason(source, drift.status.code),
|
|
1403
|
+
failedExactDataRevision: drift.status.exactDataRevision,
|
|
1404
|
+
newerExactDataRevision: driftExact.state === "hit"
|
|
1405
|
+
&& driftExact.dataRevision !== drift.status.exactDataRevision
|
|
1406
|
+
? driftExact.dataRevision
|
|
1407
|
+
: null,
|
|
1408
|
+
lastGoodExactDataRevision: drift.status.lastGoodExactDataRevision,
|
|
1409
|
+
lastGoodAt: drift.status.lastGoodAt,
|
|
1410
|
+
});
|
|
1411
|
+
} else if (
|
|
1412
|
+
chain.issue !== null
|
|
1413
|
+
&& issuePosition < updatePosition
|
|
1414
|
+
) {
|
|
1415
|
+
normalization = Object.freeze({ state: "stale", ...chain.issue });
|
|
1416
|
+
} else if (updateError !== undefined) {
|
|
1417
|
+
const updateFrontier = normalizationFrontier(
|
|
1418
|
+
state,
|
|
1419
|
+
updateError.exactQueryKey,
|
|
1420
|
+
);
|
|
1421
|
+
const updateExact = exactForQuery(updateError.exactQueryKey);
|
|
1422
|
+
const normalizedUpdateRevision = updateFrontier === null
|
|
1423
|
+
? null
|
|
1424
|
+
: updateFrontier.status.state === "ready"
|
|
1425
|
+
? updateFrontier.status.exactDataRevision
|
|
1426
|
+
: updateFrontier.status.lastGoodExactDataRevision;
|
|
1427
|
+
const evidence = staleEvidence(
|
|
1428
|
+
updateError.exactQueryKey,
|
|
1429
|
+
updateFrontier,
|
|
1430
|
+
updateExact,
|
|
1431
|
+
updateError.reason,
|
|
1432
|
+
{
|
|
1433
|
+
omitExactRevision: updateExact.state !== "hit"
|
|
1434
|
+
|| updateExact.dataRevision === normalizedUpdateRevision,
|
|
1435
|
+
},
|
|
1436
|
+
);
|
|
1437
|
+
normalization = Object.freeze({ state: "stale", ...evidence });
|
|
1438
|
+
} else if (rootFrontier === null) {
|
|
1439
|
+
normalization = Object.freeze({ state: "missing" });
|
|
1440
|
+
} else {
|
|
1441
|
+
if (rootFrontier.status.state !== "ready") {
|
|
1442
|
+
throw new Error("normalized root drift was omitted from its observed chain");
|
|
1443
|
+
}
|
|
1444
|
+
normalization = Object.freeze({
|
|
1445
|
+
state: "current",
|
|
1446
|
+
exactQueryKey: source.exactQuery.key,
|
|
1447
|
+
exactDataRevision: rootFrontier.status.exactDataRevision,
|
|
1448
|
+
lastGoodAt: rootFrontier.status.lastGoodAt,
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
return Object.freeze({
|
|
1452
|
+
state,
|
|
1453
|
+
status: Object.freeze({
|
|
1454
|
+
...normalizedCommon,
|
|
1455
|
+
normalization,
|
|
1456
|
+
coverage: chain.coverage,
|
|
1457
|
+
}),
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
function view(
|
|
1462
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
1463
|
+
options: OmniRuntimeOptions,
|
|
1464
|
+
updateErrors: ReadonlyMap<string, OmniSourceUpdateError> = new Map(),
|
|
1465
|
+
): OmniViewV1 {
|
|
1466
|
+
const observed = prepared.sources.map((source) => sourceState(
|
|
1467
|
+
source,
|
|
1468
|
+
prepared,
|
|
1469
|
+
options,
|
|
1470
|
+
updateErrors.get(canonicalJson(source.request)),
|
|
1471
|
+
));
|
|
1472
|
+
const uniqueStates = new Map<string, OmniSourceStateV1>();
|
|
1473
|
+
for (let index = 0; index < observed.length; index += 1) {
|
|
1474
|
+
const state = observed[index]?.state;
|
|
1475
|
+
const query = prepared.sources[index]?.omniQuery;
|
|
1476
|
+
if (state !== null && state !== undefined && query !== null && query !== undefined) {
|
|
1477
|
+
uniqueStates.set(query.key, state);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
const entities = queryOmniSourceStatesV1(
|
|
1481
|
+
[...uniqueStates.values()],
|
|
1482
|
+
prepared.request.filter,
|
|
1483
|
+
);
|
|
1484
|
+
const viewRevision = sha256(canonicalJson({
|
|
1485
|
+
schemaVersion: 1,
|
|
1486
|
+
requestDigest: prepared.identity.requestDigest,
|
|
1487
|
+
sourceSetDigest: prepared.identity.sourceSetDigest,
|
|
1488
|
+
entities: entities.map((entity) => Object.freeze({ id: entity.id, revision: entity.revision })),
|
|
1489
|
+
}));
|
|
1490
|
+
const cursor = prepared.request.page?.cursor;
|
|
1491
|
+
let offset = 0;
|
|
1492
|
+
if (cursor !== undefined) {
|
|
1493
|
+
const anchor = openOmniViewCursorV1(
|
|
1494
|
+
prepared.request,
|
|
1495
|
+
prepared.identity.sourceSetDigest,
|
|
1496
|
+
viewRevision,
|
|
1497
|
+
cursor,
|
|
1498
|
+
prepared.environment,
|
|
1499
|
+
);
|
|
1500
|
+
const index = entities.findIndex((entity) =>
|
|
1501
|
+
entity.id === anchor.id && entity.orderedAt === anchor.orderedAt);
|
|
1502
|
+
if (index < 0) throw new Error("omni cursor anchor is absent from its authenticated view");
|
|
1503
|
+
offset = index + 1;
|
|
1504
|
+
}
|
|
1505
|
+
const limit = prepared.request.page?.limit ?? 100;
|
|
1506
|
+
const pageEntities = Object.freeze(entities.slice(offset, offset + limit));
|
|
1507
|
+
const hasMore = offset + pageEntities.length < entities.length;
|
|
1508
|
+
const last = pageEntities.at(-1);
|
|
1509
|
+
const nextCursor = hasMore && last !== undefined
|
|
1510
|
+
? sealOmniViewCursorV1(
|
|
1511
|
+
prepared.request,
|
|
1512
|
+
prepared.identity.sourceSetDigest,
|
|
1513
|
+
viewRevision,
|
|
1514
|
+
Object.freeze({ orderedAt: last.orderedAt, id: last.id }),
|
|
1515
|
+
prepared.environment,
|
|
1516
|
+
)
|
|
1517
|
+
: null;
|
|
1518
|
+
const currentSet = prepareSources(prepared.request, {
|
|
1519
|
+
environment: prepared.environment,
|
|
1520
|
+
registry: prepared.registry,
|
|
1521
|
+
});
|
|
1522
|
+
if (
|
|
1523
|
+
currentSet.identity.invocationDigest !== prepared.identity.invocationDigest
|
|
1524
|
+
|| currentSet.identity.requestDigest !== prepared.identity.requestDigest
|
|
1525
|
+
|| currentSet.identity.sourceSetDigest !== prepared.identity.sourceSetDigest
|
|
1526
|
+
) {
|
|
1527
|
+
throw new Error(
|
|
1528
|
+
"omni source or auth identity changed while the local view was being observed",
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
return Object.freeze({
|
|
1532
|
+
schemaVersion: 1,
|
|
1533
|
+
viewRevision,
|
|
1534
|
+
entities: pageEntities,
|
|
1535
|
+
nextCursor,
|
|
1536
|
+
sources: Object.freeze(observed.map((entry) => entry.status)),
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
function result(
|
|
1541
|
+
source: OmniReadResultV1["source"],
|
|
1542
|
+
prepared: ReturnType<typeof prepareSources>,
|
|
1543
|
+
selectedView: OmniViewV1 | null,
|
|
1544
|
+
): OmniReadResultV1 {
|
|
1545
|
+
const envelope = Object.freeze({
|
|
1546
|
+
ok: true,
|
|
1547
|
+
schemaVersion: 1,
|
|
1548
|
+
source,
|
|
1549
|
+
identity: prepared.identity,
|
|
1550
|
+
view: selectedView,
|
|
1551
|
+
});
|
|
1552
|
+
// The CLI writes one trailing newline. Keep the complete process envelope
|
|
1553
|
+
// inside the same bound enforced by the public SDK.
|
|
1554
|
+
if (
|
|
1555
|
+
Buffer.byteLength(canonicalJson(envelope), "utf8") + 1
|
|
1556
|
+
> OMNI_MAX_RESPONSE_BYTES
|
|
1557
|
+
) {
|
|
1558
|
+
throw new Error("omni response exceeds its aggregate byte bound");
|
|
1559
|
+
}
|
|
1560
|
+
return envelope;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
export function identifyOmniView(
|
|
1564
|
+
requestValue: unknown,
|
|
1565
|
+
options: OmniRuntimeOptions = {},
|
|
1566
|
+
): OmniReadResultV1 {
|
|
1567
|
+
const prepared = prepareSources(requestValue, options);
|
|
1568
|
+
return result("omni-identity", prepared, null);
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
export function readCachedOmniViewInternal(
|
|
1572
|
+
requestValue: unknown,
|
|
1573
|
+
options: OmniRuntimeOptions = {},
|
|
1574
|
+
): OmniReadResultV1 {
|
|
1575
|
+
const prepared = prepareSources(requestValue, options);
|
|
1576
|
+
return result("omni-cache", prepared, view(prepared, options));
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
export function rebuildOmniViewFromExactCache(
|
|
1580
|
+
requestValue: unknown,
|
|
1581
|
+
options: OmniRuntimeOptions = {},
|
|
1582
|
+
): OmniReadResultV1 {
|
|
1583
|
+
const prepared = prepareSources(requestValue, options);
|
|
1584
|
+
const errors = new Map<string, OmniSourceUpdateError>();
|
|
1585
|
+
for (const source of prepared.sources) {
|
|
1586
|
+
if (source.omni?.state !== "supported") continue;
|
|
1587
|
+
try {
|
|
1588
|
+
const error = rebuildExactContinuationChain(source, prepared, options);
|
|
1589
|
+
if (error !== undefined) {
|
|
1590
|
+
errors.set(canonicalJson(source.request), error);
|
|
1591
|
+
}
|
|
1592
|
+
} catch {
|
|
1593
|
+
errors.set(
|
|
1594
|
+
canonicalJson(source.request),
|
|
1595
|
+
sourceUpdateError(source, NORMALIZATION_UPDATE_ERROR_REASON),
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
return result("omni-exact-cache", prepared, view(prepared, options, errors));
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
export async function revalidateOmniViewInternal(
|
|
1603
|
+
requestValue: unknown,
|
|
1604
|
+
options: OmniLiveRuntimeOptions = {},
|
|
1605
|
+
): Promise<OmniReadResultV1> {
|
|
1606
|
+
parseSourcePageLimit(options.sourcePageLimit);
|
|
1607
|
+
const prepared = prepareSources(requestValue, options);
|
|
1608
|
+
const errors = new Map<string, OmniSourceUpdateError>();
|
|
1609
|
+
for (const source of prepared.sources) {
|
|
1610
|
+
throwIfAborted(options.signal);
|
|
1611
|
+
if (source.omni?.state !== "supported") continue;
|
|
1612
|
+
try {
|
|
1613
|
+
const error = await revalidateOmniSourceChain(source, prepared, options);
|
|
1614
|
+
if (error !== undefined) {
|
|
1615
|
+
errors.set(
|
|
1616
|
+
canonicalJson(source.request),
|
|
1617
|
+
error,
|
|
1618
|
+
);
|
|
1619
|
+
}
|
|
1620
|
+
} catch {
|
|
1621
|
+
throwIfAborted(options.signal);
|
|
1622
|
+
errors.set(
|
|
1623
|
+
canonicalJson(source.request),
|
|
1624
|
+
sourceUpdateError(source, PROVIDER_READ_ERROR_REASON),
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
throwIfAborted(options.signal);
|
|
1629
|
+
const selectedView = view(prepared, options, errors);
|
|
1630
|
+
throwIfAborted(options.signal);
|
|
1631
|
+
return result("omni-live", prepared, selectedView);
|
|
1632
|
+
}
|