@mostra/protocol 0.0.0-stage → 0.1.0
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/LICENSE +202 -0
- package/README.md +38 -2
- package/dist/actions.d.ts +273 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +154 -0
- package/dist/actions.js.map +1 -0
- package/dist/artifact.d.ts +113 -0
- package/dist/artifact.d.ts.map +1 -0
- package/dist/artifact.js +79 -0
- package/dist/artifact.js.map +1 -0
- package/dist/bridge.d.ts +295 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +343 -0
- package/dist/bridge.js.map +1 -0
- package/dist/browser.d.ts +195 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +156 -0
- package/dist/browser.js.map +1 -0
- package/dist/bundle.d.ts +155 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +130 -0
- package/dist/bundle.js.map +1 -0
- package/dist/canonical.d.ts +23 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +45 -0
- package/dist/canonical.js.map +1 -0
- package/dist/capability.d.ts +38 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +61 -0
- package/dist/capability.js.map +1 -0
- package/dist/diagnostics/codes/a11y.d.ts +8 -0
- package/dist/diagnostics/codes/a11y.d.ts.map +1 -0
- package/dist/diagnostics/codes/a11y.js +30 -0
- package/dist/diagnostics/codes/a11y.js.map +1 -0
- package/dist/diagnostics/codes/action.d.ts +8 -0
- package/dist/diagnostics/codes/action.d.ts.map +1 -0
- package/dist/diagnostics/codes/action.js +110 -0
- package/dist/diagnostics/codes/action.js.map +1 -0
- package/dist/diagnostics/codes/artifact.d.ts +8 -0
- package/dist/diagnostics/codes/artifact.d.ts.map +1 -0
- package/dist/diagnostics/codes/artifact.js +121 -0
- package/dist/diagnostics/codes/artifact.js.map +1 -0
- package/dist/diagnostics/codes/build.d.ts +8 -0
- package/dist/diagnostics/codes/build.d.ts.map +1 -0
- package/dist/diagnostics/codes/build.js +55 -0
- package/dist/diagnostics/codes/build.js.map +1 -0
- package/dist/diagnostics/codes/cli.d.ts +8 -0
- package/dist/diagnostics/codes/cli.d.ts.map +1 -0
- package/dist/diagnostics/codes/cli.js +44 -0
- package/dist/diagnostics/codes/cli.js.map +1 -0
- package/dist/diagnostics/codes/console.d.ts +8 -0
- package/dist/diagnostics/codes/console.d.ts.map +1 -0
- package/dist/diagnostics/codes/console.js +30 -0
- package/dist/diagnostics/codes/console.js.map +1 -0
- package/dist/diagnostics/codes/dep.d.ts +8 -0
- package/dist/diagnostics/codes/dep.d.ts.map +1 -0
- package/dist/diagnostics/codes/dep.js +88 -0
- package/dist/diagnostics/codes/dep.js.map +1 -0
- package/dist/diagnostics/codes/env.d.ts +8 -0
- package/dist/diagnostics/codes/env.d.ts.map +1 -0
- package/dist/diagnostics/codes/env.js +132 -0
- package/dist/diagnostics/codes/env.js.map +1 -0
- package/dist/diagnostics/codes/field.d.ts +8 -0
- package/dist/diagnostics/codes/field.d.ts.map +1 -0
- package/dist/diagnostics/codes/field.js +99 -0
- package/dist/diagnostics/codes/field.js.map +1 -0
- package/dist/diagnostics/codes/home.d.ts +8 -0
- package/dist/diagnostics/codes/home.d.ts.map +1 -0
- package/dist/diagnostics/codes/home.js +132 -0
- package/dist/diagnostics/codes/home.js.map +1 -0
- package/dist/diagnostics/codes/host.d.ts +8 -0
- package/dist/diagnostics/codes/host.d.ts.map +1 -0
- package/dist/diagnostics/codes/host.js +176 -0
- package/dist/diagnostics/codes/host.js.map +1 -0
- package/dist/diagnostics/codes/hygiene.d.ts +8 -0
- package/dist/diagnostics/codes/hygiene.d.ts.map +1 -0
- package/dist/diagnostics/codes/hygiene.js +154 -0
- package/dist/diagnostics/codes/hygiene.js.map +1 -0
- package/dist/diagnostics/codes/index.d.ts +51 -0
- package/dist/diagnostics/codes/index.d.ts.map +1 -0
- package/dist/diagnostics/codes/index.js +72 -0
- package/dist/diagnostics/codes/index.js.map +1 -0
- package/dist/diagnostics/codes/live.d.ts +8 -0
- package/dist/diagnostics/codes/live.d.ts.map +1 -0
- package/dist/diagnostics/codes/live.js +30 -0
- package/dist/diagnostics/codes/live.js.map +1 -0
- package/dist/diagnostics/codes/manifest.d.ts +8 -0
- package/dist/diagnostics/codes/manifest.d.ts.map +1 -0
- package/dist/diagnostics/codes/manifest.js +44 -0
- package/dist/diagnostics/codes/manifest.js.map +1 -0
- package/dist/diagnostics/codes/network.d.ts +8 -0
- package/dist/diagnostics/codes/network.d.ts.map +1 -0
- package/dist/diagnostics/codes/network.js +30 -0
- package/dist/diagnostics/codes/network.js.map +1 -0
- package/dist/diagnostics/codes/platform.d.ts +8 -0
- package/dist/diagnostics/codes/platform.d.ts.map +1 -0
- package/dist/diagnostics/codes/platform.js +18 -0
- package/dist/diagnostics/codes/platform.js.map +1 -0
- package/dist/diagnostics/codes/publish.d.ts +8 -0
- package/dist/diagnostics/codes/publish.d.ts.map +1 -0
- package/dist/diagnostics/codes/publish.js +44 -0
- package/dist/diagnostics/codes/publish.js.map +1 -0
- package/dist/diagnostics/codes/regression.d.ts +8 -0
- package/dist/diagnostics/codes/regression.d.ts.map +1 -0
- package/dist/diagnostics/codes/regression.js +77 -0
- package/dist/diagnostics/codes/regression.js.map +1 -0
- package/dist/diagnostics/codes/runtime.d.ts +8 -0
- package/dist/diagnostics/codes/runtime.d.ts.map +1 -0
- package/dist/diagnostics/codes/runtime.js +66 -0
- package/dist/diagnostics/codes/runtime.js.map +1 -0
- package/dist/diagnostics/codes/secret.d.ts +8 -0
- package/dist/diagnostics/codes/secret.d.ts.map +1 -0
- package/dist/diagnostics/codes/secret.js +18 -0
- package/dist/diagnostics/codes/secret.js.map +1 -0
- package/dist/diagnostics/codes/smoke.d.ts +8 -0
- package/dist/diagnostics/codes/smoke.d.ts.map +1 -0
- package/dist/diagnostics/codes/smoke.js +30 -0
- package/dist/diagnostics/codes/smoke.js.map +1 -0
- package/dist/diagnostics/codes/submit.d.ts +8 -0
- package/dist/diagnostics/codes/submit.d.ts.map +1 -0
- package/dist/diagnostics/codes/submit.js +99 -0
- package/dist/diagnostics/codes/submit.js.map +1 -0
- package/dist/diagnostics/codes/target.d.ts +8 -0
- package/dist/diagnostics/codes/target.d.ts.map +1 -0
- package/dist/diagnostics/codes/target.js +18 -0
- package/dist/diagnostics/codes/target.js.map +1 -0
- package/dist/diagnostics/codes/type.d.ts +8 -0
- package/dist/diagnostics/codes/type.d.ts.map +1 -0
- package/dist/diagnostics/codes/type.js +30 -0
- package/dist/diagnostics/codes/type.js.map +1 -0
- package/dist/diagnostics/codes/verify.d.ts +8 -0
- package/dist/diagnostics/codes/verify.d.ts.map +1 -0
- package/dist/diagnostics/codes/verify.js +99 -0
- package/dist/diagnostics/codes/verify.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +79 -0
- package/dist/diagnostics/diagnostic.d.ts.map +1 -0
- package/dist/diagnostics/diagnostic.js +131 -0
- package/dist/diagnostics/diagnostic.js.map +1 -0
- package/dist/diagnostics/spec.d.ts +49 -0
- package/dist/diagnostics/spec.d.ts.map +1 -0
- package/dist/diagnostics/spec.js +31 -0
- package/dist/diagnostics/spec.js.map +1 -0
- package/dist/hygiene.d.ts +66 -0
- package/dist/hygiene.d.ts.map +1 -0
- package/dist/hygiene.js +134 -0
- package/dist/hygiene.js.map +1 -0
- package/dist/ids.d.ts +119 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +135 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +86 -0
- package/dist/interaction.d.ts +391 -0
- package/dist/interaction.d.ts.map +1 -0
- package/dist/interaction.js +306 -0
- package/dist/interaction.js.map +1 -0
- package/dist/manifest.d.ts +97 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +101 -0
- package/dist/manifest.js.map +1 -0
- package/dist/method.d.ts +26 -0
- package/dist/method.d.ts.map +1 -0
- package/dist/method.js +10 -0
- package/dist/method.js.map +1 -0
- package/dist/methods/artifact/create.d.ts +29 -0
- package/dist/methods/artifact/create.d.ts.map +1 -0
- package/dist/methods/artifact/create.js +31 -0
- package/dist/methods/artifact/create.js.map +1 -0
- package/dist/methods/artifact/get.d.ts +17 -0
- package/dist/methods/artifact/get.d.ts.map +1 -0
- package/dist/methods/artifact/get.js +21 -0
- package/dist/methods/artifact/get.js.map +1 -0
- package/dist/methods/artifact/list.d.ts +22 -0
- package/dist/methods/artifact/list.d.ts.map +1 -0
- package/dist/methods/artifact/list.js +19 -0
- package/dist/methods/artifact/list.js.map +1 -0
- package/dist/methods/artifact/publish.d.ts +28 -0
- package/dist/methods/artifact/publish.d.ts.map +1 -0
- package/dist/methods/artifact/publish.js +28 -0
- package/dist/methods/artifact/publish.js.map +1 -0
- package/dist/methods/artifact/verify.d.ts +29 -0
- package/dist/methods/artifact/verify.d.ts.map +1 -0
- package/dist/methods/artifact/verify.js +27 -0
- package/dist/methods/artifact/verify.js.map +1 -0
- package/dist/methods/deps/add.d.ts +43 -0
- package/dist/methods/deps/add.d.ts.map +1 -0
- package/dist/methods/deps/add.js +40 -0
- package/dist/methods/deps/add.js.map +1 -0
- package/dist/methods/dev/start.d.ts +52 -0
- package/dist/methods/dev/start.d.ts.map +1 -0
- package/dist/methods/dev/start.js +56 -0
- package/dist/methods/dev/start.js.map +1 -0
- package/dist/methods/dev/stop.d.ts +16 -0
- package/dist/methods/dev/stop.d.ts.map +1 -0
- package/dist/methods/dev/stop.js +21 -0
- package/dist/methods/dev/stop.js.map +1 -0
- package/dist/methods/events/ack.d.ts +20 -0
- package/dist/methods/events/ack.d.ts.map +1 -0
- package/dist/methods/events/ack.js +26 -0
- package/dist/methods/events/ack.js.map +1 -0
- package/dist/methods/events/read.d.ts +40 -0
- package/dist/methods/events/read.d.ts.map +1 -0
- package/dist/methods/events/read.js +35 -0
- package/dist/methods/events/read.js.map +1 -0
- package/dist/methods/events/subscribe.d.ts +54 -0
- package/dist/methods/events/subscribe.d.ts.map +1 -0
- package/dist/methods/events/subscribe.js +44 -0
- package/dist/methods/events/subscribe.js.map +1 -0
- package/dist/methods/events/unsubscribe.d.ts +16 -0
- package/dist/methods/events/unsubscribe.d.ts.map +1 -0
- package/dist/methods/events/unsubscribe.js +21 -0
- package/dist/methods/events/unsubscribe.js.map +1 -0
- package/dist/methods/gc/run.d.ts +76 -0
- package/dist/methods/gc/run.d.ts.map +1 -0
- package/dist/methods/gc/run.js +56 -0
- package/dist/methods/gc/run.js.map +1 -0
- package/dist/methods/index.d.ts +6 -0
- package/dist/methods/index.d.ts.map +1 -0
- package/dist/methods/index.js +78 -0
- package/dist/methods/index.js.map +1 -0
- package/dist/methods/instance/check.d.ts +30 -0
- package/dist/methods/instance/check.d.ts.map +1 -0
- package/dist/methods/instance/check.js +34 -0
- package/dist/methods/instance/check.js.map +1 -0
- package/dist/methods/instance/status.d.ts +102 -0
- package/dist/methods/instance/status.d.ts.map +1 -0
- package/dist/methods/instance/status.js +83 -0
- package/dist/methods/instance/status.js.map +1 -0
- package/dist/methods/live/push.d.ts +28 -0
- package/dist/methods/live/push.d.ts.map +1 -0
- package/dist/methods/live/push.js +35 -0
- package/dist/methods/live/push.js.map +1 -0
- package/dist/methods/mostra/initialize.d.ts +143 -0
- package/dist/methods/mostra/initialize.d.ts.map +1 -0
- package/dist/methods/mostra/initialize.js +97 -0
- package/dist/methods/mostra/initialize.js.map +1 -0
- package/dist/methods/mostra/shutdown.d.ts +14 -0
- package/dist/methods/mostra/shutdown.d.ts.map +1 -0
- package/dist/methods/mostra/shutdown.js +22 -0
- package/dist/methods/mostra/shutdown.js.map +1 -0
- package/dist/methods/port/drafts-mirror.d.ts +30 -0
- package/dist/methods/port/drafts-mirror.d.ts.map +1 -0
- package/dist/methods/port/drafts-mirror.js +33 -0
- package/dist/methods/port/drafts-mirror.js.map +1 -0
- package/dist/methods/port/secrets-get.d.ts +19 -0
- package/dist/methods/port/secrets-get.d.ts.map +1 -0
- package/dist/methods/port/secrets-get.js +31 -0
- package/dist/methods/port/secrets-get.js.map +1 -0
- package/dist/methods/port/submissions-deliver.d.ts +38 -0
- package/dist/methods/port/submissions-deliver.d.ts.map +1 -0
- package/dist/methods/port/submissions-deliver.js +38 -0
- package/dist/methods/port/submissions-deliver.js.map +1 -0
- package/dist/methods/port/trusted-controls-activated.d.ts +27 -0
- package/dist/methods/port/trusted-controls-activated.d.ts.map +1 -0
- package/dist/methods/port/trusted-controls-activated.js +33 -0
- package/dist/methods/port/trusted-controls-activated.js.map +1 -0
- package/dist/methods/port/trusted-controls-policy.d.ts +21 -0
- package/dist/methods/port/trusted-controls-policy.d.ts.map +1 -0
- package/dist/methods/port/trusted-controls-policy.js +27 -0
- package/dist/methods/port/trusted-controls-policy.js.map +1 -0
- package/dist/methods/results/get.d.ts +32 -0
- package/dist/methods/results/get.d.ts.map +1 -0
- package/dist/methods/results/get.js +36 -0
- package/dist/methods/results/get.js.map +1 -0
- package/dist/methods/secret/delete.d.ts +22 -0
- package/dist/methods/secret/delete.d.ts.map +1 -0
- package/dist/methods/secret/delete.js +32 -0
- package/dist/methods/secret/delete.js.map +1 -0
- package/dist/methods/secret/list.d.ts +21 -0
- package/dist/methods/secret/list.d.ts.map +1 -0
- package/dist/methods/secret/list.js +29 -0
- package/dist/methods/secret/list.js.map +1 -0
- package/dist/methods/secret/set.d.ts +37 -0
- package/dist/methods/secret/set.d.ts.map +1 -0
- package/dist/methods/secret/set.js +41 -0
- package/dist/methods/secret/set.js.map +1 -0
- package/dist/methods/state/get.d.ts +25 -0
- package/dist/methods/state/get.d.ts.map +1 -0
- package/dist/methods/state/get.js +29 -0
- package/dist/methods/state/get.js.map +1 -0
- package/dist/methods/state/patch.d.ts +32 -0
- package/dist/methods/state/patch.d.ts.map +1 -0
- package/dist/methods/state/patch.js +29 -0
- package/dist/methods/state/patch.js.map +1 -0
- package/dist/methods/view/default.d.ts +19 -0
- package/dist/methods/view/default.d.ts.map +1 -0
- package/dist/methods/view/default.js +23 -0
- package/dist/methods/view/default.js.map +1 -0
- package/dist/methods/view/launch.d.ts +27 -0
- package/dist/methods/view/launch.d.ts.map +1 -0
- package/dist/methods/view/launch.js +30 -0
- package/dist/methods/view/launch.js.map +1 -0
- package/dist/methods/view/revoke.d.ts +19 -0
- package/dist/methods/view/revoke.d.ts.map +1 -0
- package/dist/methods/view/revoke.js +26 -0
- package/dist/methods/view/revoke.js.map +1 -0
- package/dist/methods/view/rotate.d.ts +21 -0
- package/dist/methods/view/rotate.d.ts.map +1 -0
- package/dist/methods/view/rotate.js +27 -0
- package/dist/methods/view/rotate.js.map +1 -0
- package/dist/methods/view/url.d.ts +52 -0
- package/dist/methods/view/url.d.ts.map +1 -0
- package/dist/methods/view/url.js +43 -0
- package/dist/methods/view/url.js.map +1 -0
- package/dist/methods/wait/wait.d.ts +37 -0
- package/dist/methods/wait/wait.d.ts.map +1 -0
- package/dist/methods/wait/wait.js +39 -0
- package/dist/methods/wait/wait.js.map +1 -0
- package/dist/revision.d.ts +43 -0
- package/dist/revision.d.ts.map +1 -0
- package/dist/revision.js +69 -0
- package/dist/revision.js.map +1 -0
- package/dist/rpc/error.d.ts +47 -0
- package/dist/rpc/error.d.ts.map +1 -0
- package/dist/rpc/error.js +77 -0
- package/dist/rpc/error.js.map +1 -0
- package/dist/rpc/lines.d.ts +30 -0
- package/dist/rpc/lines.d.ts.map +1 -0
- package/dist/rpc/lines.js +63 -0
- package/dist/rpc/lines.js.map +1 -0
- package/dist/rpc/messages.d.ts +92 -0
- package/dist/rpc/messages.d.ts.map +1 -0
- package/dist/rpc/messages.js +133 -0
- package/dist/rpc/messages.js.map +1 -0
- package/dist/rpc/peer.d.ts +81 -0
- package/dist/rpc/peer.d.ts.map +1 -0
- package/dist/rpc/peer.js +208 -0
- package/dist/rpc/peer.js.map +1 -0
- package/dist/serializer.d.ts +178 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +929 -0
- package/dist/serializer.js.map +1 -0
- package/dist/verify.d.ts +254 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +243 -0
- package/dist/verify.js.map +1 -0
- package/dist/view.d.ts +103 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +110 -0
- package/dist/view.js.map +1 -0
- package/dist/wire-registry.js +11 -0
- package/dist/wire-registry.js.map +1 -0
- package/dist/worker.d.ts +249 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +158 -0
- package/dist/worker.js.map +1 -0
- package/package.json +114 -3
- package/schemas/protocol.draft-07.json +5120 -0
- package/schemas/protocol.schema.json +4964 -0
- package/src/actions.ts +418 -0
- package/src/artifact.ts +187 -0
- package/src/bridge.ts +618 -0
- package/src/browser.ts +374 -0
- package/src/bundle.ts +264 -0
- package/src/canonical.ts +49 -0
- package/src/capability.ts +92 -0
- package/src/diagnostics/codes/a11y.ts +41 -0
- package/src/diagnostics/codes/action.ts +125 -0
- package/src/diagnostics/codes/artifact.ts +137 -0
- package/src/diagnostics/codes/build.ts +65 -0
- package/src/diagnostics/codes/cli.ts +53 -0
- package/src/diagnostics/codes/console.ts +41 -0
- package/src/diagnostics/codes/dep.ts +101 -0
- package/src/diagnostics/codes/env.ts +149 -0
- package/src/diagnostics/codes/field.ts +113 -0
- package/src/diagnostics/codes/home.ts +150 -0
- package/src/diagnostics/codes/host.ts +197 -0
- package/src/diagnostics/codes/hygiene.ts +175 -0
- package/src/diagnostics/codes/index.ts +142 -0
- package/src/diagnostics/codes/live.ts +41 -0
- package/src/diagnostics/codes/manifest.ts +53 -0
- package/src/diagnostics/codes/network.ts +41 -0
- package/src/diagnostics/codes/platform.ts +30 -0
- package/src/diagnostics/codes/publish.ts +53 -0
- package/src/diagnostics/codes/regression.ts +89 -0
- package/src/diagnostics/codes/runtime.ts +77 -0
- package/src/diagnostics/codes/secret.ts +29 -0
- package/src/diagnostics/codes/smoke.ts +41 -0
- package/src/diagnostics/codes/submit.ts +113 -0
- package/src/diagnostics/codes/target.ts +29 -0
- package/src/diagnostics/codes/type.ts +41 -0
- package/src/diagnostics/codes/verify.ts +113 -0
- package/src/diagnostics/diagnostic.ts +240 -0
- package/src/diagnostics/spec.ts +90 -0
- package/src/hygiene.ts +224 -0
- package/src/ids.ts +279 -0
- package/src/index.ts +576 -0
- package/src/interaction.ts +728 -0
- package/src/manifest.ts +206 -0
- package/src/method.ts +42 -0
- package/src/methods/artifact/create.ts +56 -0
- package/src/methods/artifact/get.ts +30 -0
- package/src/methods/artifact/list.ts +42 -0
- package/src/methods/artifact/publish.ts +46 -0
- package/src/methods/artifact/verify.ts +46 -0
- package/src/methods/deps/add.ts +72 -0
- package/src/methods/dev/start.ts +84 -0
- package/src/methods/dev/stop.ts +32 -0
- package/src/methods/events/ack.ts +41 -0
- package/src/methods/events/read.ts +67 -0
- package/src/methods/events/subscribe.ts +91 -0
- package/src/methods/events/unsubscribe.ts +35 -0
- package/src/methods/gc/run.ts +125 -0
- package/src/methods/index.ts +81 -0
- package/src/methods/instance/check.ts +61 -0
- package/src/methods/instance/status.ts +172 -0
- package/src/methods/live/push.ts +54 -0
- package/src/methods/mostra/initialize.ts +249 -0
- package/src/methods/mostra/shutdown.ts +31 -0
- package/src/methods/port/drafts-mirror.ts +52 -0
- package/src/methods/port/secrets-get.ts +40 -0
- package/src/methods/port/submissions-deliver.ts +70 -0
- package/src/methods/port/trusted-controls-activated.ts +51 -0
- package/src/methods/port/trusted-controls-policy.ts +38 -0
- package/src/methods/results/get.ts +59 -0
- package/src/methods/secret/delete.ts +43 -0
- package/src/methods/secret/list.ts +40 -0
- package/src/methods/secret/set.ts +69 -0
- package/src/methods/state/get.ts +44 -0
- package/src/methods/state/patch.ts +51 -0
- package/src/methods/view/default.ts +32 -0
- package/src/methods/view/launch.ts +47 -0
- package/src/methods/view/revoke.ts +39 -0
- package/src/methods/view/rotate.ts +37 -0
- package/src/methods/view/url.ts +84 -0
- package/src/methods/wait/wait.ts +58 -0
- package/src/revision.ts +101 -0
- package/src/rpc/error.ts +107 -0
- package/src/rpc/lines.ts +70 -0
- package/src/rpc/messages.ts +188 -0
- package/src/rpc/peer.ts +341 -0
- package/src/serializer.ts +1217 -0
- package/src/timers.d.ts +8 -0
- package/src/verify.ts +458 -0
- package/src/view.ts +200 -0
- package/src/web-crypto.d.ts +9 -0
- package/src/web-platform.d.ts +35 -0
- package/src/wire-registry.ts +14 -0
- package/src/worker.ts +374 -0
package/src/timers.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// The timer functions the JSON-RPC peer uses for request timeouts, present in browsers, workers and
|
|
2
|
+
// Node.js. Declared here so the package compiles without DOM or Node types.
|
|
3
|
+
declare global {
|
|
4
|
+
function setTimeout(callback: () => void, ms?: number): unknown;
|
|
5
|
+
function clearTimeout(handle: unknown): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export {};
|
package/src/verify.ts
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `verify` (D29, D41, D55, D72, D138; INTERFACES §13): the verdict it returns, the viewports it
|
|
3
|
+
* renders, and the image-token estimates every screenshot carries. Pure and free of I/O, so the
|
|
4
|
+
* runtime, the verify runner, the CLI and the MCP server share one definition.
|
|
5
|
+
*/
|
|
6
|
+
import * as z from "zod";
|
|
7
|
+
import { Diagnostic } from "./diagnostics/diagnostic.ts";
|
|
8
|
+
import { wireRegistry } from "./wire-registry.ts";
|
|
9
|
+
|
|
10
|
+
/** When a verdict's screenshots are handed to the caller (AX-05): images cost tokens. */
|
|
11
|
+
export type ScreenshotPolicy = "on-failure" | "always" | "never";
|
|
12
|
+
|
|
13
|
+
/** The Zod schema of the `ScreenshotPolicy` type. */
|
|
14
|
+
export const ScreenshotPolicy: z.ZodType<ScreenshotPolicy, string> = z
|
|
15
|
+
.enum(["on-failure", "always", "never"])
|
|
16
|
+
.register(wireRegistry, {
|
|
17
|
+
id: "ScreenshotPolicy",
|
|
18
|
+
description: "When screenshots are returned: on failure (the default), always or never.",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/** One viewport verify renders at device pixel ratio 1. */
|
|
22
|
+
export interface VerifyViewport {
|
|
23
|
+
/** Its name in the verdict: `desktop`, `mobile`, `tablet`, or `<width>x<height>`. */
|
|
24
|
+
readonly name: string;
|
|
25
|
+
/** Its width in CSS pixels, which at DPR 1 are the screenshot's pixels. */
|
|
26
|
+
readonly width: number;
|
|
27
|
+
/** Its height in CSS pixels. */
|
|
28
|
+
readonly height: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** The viewports verify renders when the manifest names none (ROUND-3 §9): desktop and mobile. */
|
|
32
|
+
export const DEFAULT_VIEWPORTS: readonly VerifyViewport[] = [
|
|
33
|
+
{ name: "desktop", width: 1280, height: 800 },
|
|
34
|
+
{ name: "mobile", width: 390, height: 844 },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const NAMED_VIEWPORTS: Readonly<Record<string, VerifyViewport>> = {
|
|
38
|
+
desktop: { name: "desktop", width: 1280, height: 800 },
|
|
39
|
+
mobile: { name: "mobile", width: 390, height: 844 },
|
|
40
|
+
tablet: { name: "tablet", width: 768, height: 1024 },
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The viewports a manifest's `verify.viewports` names (`desktop`, `mobile`, `tablet`, or
|
|
45
|
+
* `<width>x<height>` from 200 to 4000 px), in its order and without repeats; the defaults when it
|
|
46
|
+
* names none. Returns the names it couldn't read beside them.
|
|
47
|
+
*/
|
|
48
|
+
export function viewportsFor(names: readonly string[] | undefined): {
|
|
49
|
+
readonly viewports: readonly VerifyViewport[];
|
|
50
|
+
readonly unknown: readonly string[];
|
|
51
|
+
} {
|
|
52
|
+
if (names === undefined || names.length === 0)
|
|
53
|
+
return { viewports: DEFAULT_VIEWPORTS, unknown: [] };
|
|
54
|
+
const viewports: VerifyViewport[] = [];
|
|
55
|
+
const unknown: string[] = [];
|
|
56
|
+
for (const raw of names) {
|
|
57
|
+
const name = raw.trim().toLowerCase();
|
|
58
|
+
const sized = /^(\d{3,4})x(\d{3,4})$/.exec(name);
|
|
59
|
+
const viewport =
|
|
60
|
+
NAMED_VIEWPORTS[name] ??
|
|
61
|
+
(sized ? { name, width: Number(sized[1]), height: Number(sized[2]) } : undefined);
|
|
62
|
+
if (
|
|
63
|
+
!viewport ||
|
|
64
|
+
viewport.width < 200 ||
|
|
65
|
+
viewport.height < 200 ||
|
|
66
|
+
viewport.width > 4000 ||
|
|
67
|
+
viewport.height > 4000
|
|
68
|
+
) {
|
|
69
|
+
unknown.push(raw);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!viewports.some((known) => known.name === viewport.name)) viewports.push(viewport);
|
|
73
|
+
}
|
|
74
|
+
return { viewports: viewports.length > 0 ? viewports : DEFAULT_VIEWPORTS, unknown };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** What one image costs each model family to read (D138 item 9). */
|
|
78
|
+
export interface TokenEstimate {
|
|
79
|
+
/** Claude's high-resolution tier (Claude 4.7 and later). */
|
|
80
|
+
readonly claude: number;
|
|
81
|
+
/** GPT at `detail: "high"` (gpt-5.5, gpt-5.6, gpt-6-astra). */
|
|
82
|
+
readonly gpt: number;
|
|
83
|
+
/** Gemini 3 and 4 at the default media resolution. */
|
|
84
|
+
readonly gemini: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Claude: tokens of an image already within its tier's limits. */
|
|
88
|
+
const claudeTokens = (width: number, height: number): number =>
|
|
89
|
+
Math.ceil(width / 28) * Math.ceil(height / 28);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The size Claude resizes an image to (its documented reference implementation): the largest
|
|
93
|
+
* aspect-preserving size whose 28-px-rounded sides fit `maxEdge` and whose tokens fit `maxTokens`.
|
|
94
|
+
*/
|
|
95
|
+
function claudeSize(
|
|
96
|
+
width: number,
|
|
97
|
+
height: number,
|
|
98
|
+
maxEdge: number,
|
|
99
|
+
maxTokens: number,
|
|
100
|
+
): readonly [number, number] {
|
|
101
|
+
const fits = (w: number, h: number): boolean =>
|
|
102
|
+
Math.ceil(w / 28) * 28 <= maxEdge &&
|
|
103
|
+
Math.ceil(h / 28) * 28 <= maxEdge &&
|
|
104
|
+
claudeTokens(w, h) <= maxTokens;
|
|
105
|
+
if (fits(width, height)) return [width, height];
|
|
106
|
+
if (height > width) {
|
|
107
|
+
const [h, w] = claudeSize(height, width, maxEdge, maxTokens);
|
|
108
|
+
return [w, h];
|
|
109
|
+
}
|
|
110
|
+
const aspect = width / height;
|
|
111
|
+
let lo = 1;
|
|
112
|
+
let hi = width;
|
|
113
|
+
while (lo + 1 < hi) {
|
|
114
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
115
|
+
if (fits(mid, Math.max(Math.round(mid / aspect), 1))) lo = mid;
|
|
116
|
+
else hi = mid;
|
|
117
|
+
}
|
|
118
|
+
return [lo, Math.max(Math.round(lo / aspect), 1)];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** GPT at `detail: "high"`: fit 2048 × 2048, then a 2,500-patch budget, then the 1.2 multiplier. */
|
|
122
|
+
function gptTokens(width: number, height: number): number {
|
|
123
|
+
let w = width;
|
|
124
|
+
let h = height;
|
|
125
|
+
const edge = Math.min(1, 2048 / Math.max(w, h));
|
|
126
|
+
if (edge < 1) {
|
|
127
|
+
w = Math.max(1, Math.round(w * edge));
|
|
128
|
+
h = Math.max(1, Math.round(h * edge));
|
|
129
|
+
}
|
|
130
|
+
let patches = Math.ceil(w / 32) * Math.ceil(h / 32);
|
|
131
|
+
const budget = 2500;
|
|
132
|
+
if (patches > budget) {
|
|
133
|
+
const shrink = Math.sqrt((32 ** 2 * budget) / (w * h));
|
|
134
|
+
const adjusted =
|
|
135
|
+
shrink *
|
|
136
|
+
Math.min(
|
|
137
|
+
Math.floor((w * shrink) / 32) / ((w * shrink) / 32),
|
|
138
|
+
Math.floor((h * shrink) / 32) / ((h * shrink) / 32),
|
|
139
|
+
);
|
|
140
|
+
patches = Math.ceil(Math.floor(w * adjusted) / 32) * Math.ceil(Math.floor(h * adjusted) / 32);
|
|
141
|
+
}
|
|
142
|
+
return Math.ceil(patches * 1.2);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* What an image of `width` × `height` pixels costs Claude, GPT and Gemini to read, by each
|
|
147
|
+
* provider's published rule as verified on 2026-10-17 (VERIFIED_FACTS, WP-09). Estimates: harnesses
|
|
148
|
+
* use them to budget, and each provider may round differently by a token.
|
|
149
|
+
*/
|
|
150
|
+
export function estimateImageTokens(width: number, height: number): TokenEstimate {
|
|
151
|
+
const [cw, ch] = claudeSize(width, height, 2576, 4784);
|
|
152
|
+
return { claude: claudeTokens(cw, ch), gpt: gptTokens(width, height), gemini: 1120 };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** One screenshot in a verdict (AX-05). */
|
|
156
|
+
export interface VerdictScreenshot {
|
|
157
|
+
/** The viewport's name. */
|
|
158
|
+
readonly viewport: string;
|
|
159
|
+
/** The PNG, at device pixel ratio 1. */
|
|
160
|
+
readonly path: string;
|
|
161
|
+
/** The image's width in pixels. */
|
|
162
|
+
readonly width: number;
|
|
163
|
+
/** The image's height in pixels. */
|
|
164
|
+
readonly height: number;
|
|
165
|
+
/** What reading the image costs each model family ({@link estimateImageTokens}). */
|
|
166
|
+
readonly tokensEstimate: TokenEstimate;
|
|
167
|
+
/** Whether the caller is handed the image: on failure, or when asked (`screenshots`). */
|
|
168
|
+
readonly returned: boolean;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** One ARIA snapshot in a verdict: the text-only picture of what a viewport shows. */
|
|
172
|
+
export interface VerdictAria {
|
|
173
|
+
/** The viewport's name. */
|
|
174
|
+
readonly viewport: string;
|
|
175
|
+
/** The snapshot's YAML. */
|
|
176
|
+
readonly path: string;
|
|
177
|
+
/** A one-line count of what it holds: headings, controls, landmarks. */
|
|
178
|
+
readonly summary: string;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** The verdict of one `verify` run (INTERFACES §13). `status` is `fail` exactly when an error exists. */
|
|
182
|
+
export interface VerifyVerdict {
|
|
183
|
+
/** `fail` when any diagnostic is an error, else `pass`. */
|
|
184
|
+
readonly status: "pass" | "fail";
|
|
185
|
+
/** What was verified. */
|
|
186
|
+
readonly artifact: {
|
|
187
|
+
/** The artifact, when it has one already: a manifest `id` or a published path. */
|
|
188
|
+
readonly id?: string;
|
|
189
|
+
/** The source path as the request named it. */
|
|
190
|
+
readonly path: string;
|
|
191
|
+
/** The snapshot's digest (DATA_MODEL §2); empty when verify couldn't read the source. */
|
|
192
|
+
readonly sourceDigest: string;
|
|
193
|
+
/** The environment's digest, `lockDigest` included (DATA_MODEL §2); empty likewise. */
|
|
194
|
+
readonly envDigest: string;
|
|
195
|
+
/** The version this source would publish as, when the artifact is known (D89). */
|
|
196
|
+
readonly versionId?: string;
|
|
197
|
+
};
|
|
198
|
+
/** Every finding, errors first, identical ones folded with a `count`. */
|
|
199
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
200
|
+
/** One per viewport rendered. */
|
|
201
|
+
readonly screenshots: readonly VerdictScreenshot[];
|
|
202
|
+
/** One per viewport rendered. */
|
|
203
|
+
readonly aria: readonly VerdictAria[];
|
|
204
|
+
/** What the smoke test did. */
|
|
205
|
+
readonly smoke: {
|
|
206
|
+
/** Controls the smoke test used. */
|
|
207
|
+
readonly interactions: number;
|
|
208
|
+
/** Server functions that don't check `dryRun()` and were refused instead of run (D55). */
|
|
209
|
+
readonly skippedActions: readonly string[];
|
|
210
|
+
/** Field writes the interactions caused. */
|
|
211
|
+
readonly stateChanges: number;
|
|
212
|
+
};
|
|
213
|
+
/** What changed since the last passing version; empty when there is none. */
|
|
214
|
+
readonly regressions: {
|
|
215
|
+
/**
|
|
216
|
+
* The last passing version: the newest whose recorded verdict passed (D138 item 4). When it is
|
|
217
|
+
* this very source, nothing needed comparing.
|
|
218
|
+
*/
|
|
219
|
+
readonly against?: string;
|
|
220
|
+
/** Controls and landmarks the baseline had and this source doesn't, in brief. */
|
|
221
|
+
readonly aria?: string;
|
|
222
|
+
/** The share of pixels that differ from the baseline, per viewport. */
|
|
223
|
+
readonly pixels?: readonly { readonly viewport: string; readonly ratio: number }[];
|
|
224
|
+
/** Contracts the baseline had that this source drops: fields, actions, live sources, pages. */
|
|
225
|
+
readonly contracts?: readonly string[];
|
|
226
|
+
};
|
|
227
|
+
/** How long each stage took, in milliseconds, and `total`. */
|
|
228
|
+
readonly timingsMs: Readonly<Record<string, number>>;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const tokenEstimate: z.ZodType<TokenEstimate> = z.object({
|
|
232
|
+
claude: z.int().min(0),
|
|
233
|
+
gpt: z.int().min(0),
|
|
234
|
+
gemini: z.int().min(0),
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
/** The Zod schema of the `VerifyVerdict` type. */
|
|
238
|
+
export const VerifyVerdict: z.ZodType<VerifyVerdict> = z
|
|
239
|
+
.object({
|
|
240
|
+
status: z.enum(["pass", "fail"]),
|
|
241
|
+
artifact: z.object({
|
|
242
|
+
id: z.string().exactOptional(),
|
|
243
|
+
path: z.string(),
|
|
244
|
+
sourceDigest: z.string(),
|
|
245
|
+
envDigest: z.string(),
|
|
246
|
+
versionId: z.string().exactOptional(),
|
|
247
|
+
}),
|
|
248
|
+
diagnostics: z.array(Diagnostic).readonly(),
|
|
249
|
+
screenshots: z
|
|
250
|
+
.array(
|
|
251
|
+
z.object({
|
|
252
|
+
viewport: z.string(),
|
|
253
|
+
path: z.string(),
|
|
254
|
+
width: z.int().min(1),
|
|
255
|
+
height: z.int().min(1),
|
|
256
|
+
tokensEstimate: tokenEstimate,
|
|
257
|
+
returned: z.boolean(),
|
|
258
|
+
}),
|
|
259
|
+
)
|
|
260
|
+
.readonly(),
|
|
261
|
+
aria: z
|
|
262
|
+
.array(z.object({ viewport: z.string(), path: z.string(), summary: z.string() }))
|
|
263
|
+
.readonly(),
|
|
264
|
+
smoke: z.object({
|
|
265
|
+
interactions: z.int().min(0),
|
|
266
|
+
skippedActions: z.array(z.string()).readonly(),
|
|
267
|
+
stateChanges: z.int().min(0),
|
|
268
|
+
}),
|
|
269
|
+
regressions: z.object({
|
|
270
|
+
against: z.string().exactOptional(),
|
|
271
|
+
aria: z.string().exactOptional(),
|
|
272
|
+
pixels: z
|
|
273
|
+
.array(z.object({ viewport: z.string(), ratio: z.number().min(0).max(1) }))
|
|
274
|
+
.readonly()
|
|
275
|
+
.exactOptional(),
|
|
276
|
+
contracts: z.array(z.string()).readonly().exactOptional(),
|
|
277
|
+
}),
|
|
278
|
+
timingsMs: z.record(z.string(), z.number().min(0)),
|
|
279
|
+
})
|
|
280
|
+
.register(wireRegistry, {
|
|
281
|
+
id: "VerifyVerdict",
|
|
282
|
+
description:
|
|
283
|
+
"The verdict of artifact/verify: pass or fail, diagnostics, screenshots with token estimates, ARIA snapshots, the smoke test, regressions and timings.",
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
/** The notification `artifact/verify` sends while it runs, when the client accepts it. */
|
|
287
|
+
export const ARTIFACT_PROGRESS = "artifact/progress";
|
|
288
|
+
|
|
289
|
+
/** `artifact/progress`: one stage of a long request started or ended. */
|
|
290
|
+
export interface ArtifactProgressParams {
|
|
291
|
+
/** The `progressToken` the request carried. */
|
|
292
|
+
readonly progressToken: string;
|
|
293
|
+
/** The stage that started: `prepare`, `compile`, `boot`, `render`, `smoke`, `regression`. */
|
|
294
|
+
readonly stage: string;
|
|
295
|
+
/** How much of the request is done, from 0 to 1, when known. */
|
|
296
|
+
readonly fraction?: number;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/** The Zod schema of the `ArtifactProgressParams` type. */
|
|
300
|
+
export const ArtifactProgressParams: z.ZodType<ArtifactProgressParams> = z
|
|
301
|
+
.object({
|
|
302
|
+
progressToken: z.string().min(1),
|
|
303
|
+
stage: z.string().min(1),
|
|
304
|
+
fraction: z.number().min(0).max(1).exactOptional(),
|
|
305
|
+
})
|
|
306
|
+
.register(wireRegistry, {
|
|
307
|
+
id: "ArtifactProgressParams",
|
|
308
|
+
description: "One stage of a long request (artifact/verify) started.",
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* The global the verify runner's recorder installs in every frame of a render: a page in the
|
|
313
|
+
* `verify` target reports errors its React error boundaries caught through it, with their
|
|
314
|
+
* `cause` chains, so the runner judges each by its cause (D138 items 2 and 3, Opus review finding
|
|
315
|
+
* 3). Viewers' pages never have it.
|
|
316
|
+
*/
|
|
317
|
+
export const VERIFY_REPORT = "__mostraVerifyReport";
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* What a verify run's page tells the runner about its fields (D138 item 3), on
|
|
321
|
+
* `globalThis[VERIFY_PROBE]` in the `verify` target only: every field it mounted, how, and with
|
|
322
|
+
* which initial value's type; internal to Mostra.
|
|
323
|
+
*/
|
|
324
|
+
export const VERIFY_PROBE = "__mostraVerify";
|
|
325
|
+
|
|
326
|
+
/** One mounted field, as the probe reports it; internal to Mostra. */
|
|
327
|
+
export interface ProbedField {
|
|
328
|
+
/** The field ID. */
|
|
329
|
+
readonly id: string;
|
|
330
|
+
/** Its scope, as first mounted. */
|
|
331
|
+
readonly scope: "viewer" | "artifact";
|
|
332
|
+
/** The hook that named it: `useField`, `useChoice`, `useForm` or `storage`. */
|
|
333
|
+
readonly hook: string;
|
|
334
|
+
/** `typeof` its initial value, `array` or `null`. */
|
|
335
|
+
readonly initialType: string;
|
|
336
|
+
/** How many components have it mounted now. */
|
|
337
|
+
readonly mounts: number;
|
|
338
|
+
/** Other hook kinds, scopes or initial types it was mounted with, if any. */
|
|
339
|
+
readonly conflicts: readonly string[];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** The verify runner's methods (ARCHITECTURE §1): the supervisor asks, the runner answers; internal to Mostra. */
|
|
343
|
+
export const VERIFY_RUNNER_METHODS = {
|
|
344
|
+
/** Opens one capability link in a fresh browser context and reports what the page did. */
|
|
345
|
+
render: "verify/render",
|
|
346
|
+
/** Compares two screenshots and writes their difference. */
|
|
347
|
+
compare: "verify/compare",
|
|
348
|
+
} as const;
|
|
349
|
+
|
|
350
|
+
/** `verify/render`'s params; internal to Mostra. */
|
|
351
|
+
export interface RenderRequest {
|
|
352
|
+
/** The capability link to open, as a viewer would (D138 item 1). */
|
|
353
|
+
readonly url: string;
|
|
354
|
+
/** The viewport to render at, DPR 1. */
|
|
355
|
+
readonly viewport: VerifyViewport;
|
|
356
|
+
/** The fixed time `Date` reports, in ms since the epoch: the same for every render of a run. */
|
|
357
|
+
readonly clockMs: number;
|
|
358
|
+
/** Where the screenshot and the ARIA snapshot are written, named after `name`. */
|
|
359
|
+
readonly outDir: string;
|
|
360
|
+
/** The render's name: its files are `<name>.png` and `<name>.aria.yml`. */
|
|
361
|
+
readonly name: string;
|
|
362
|
+
/** What to collect besides readiness and the page's own errors. */
|
|
363
|
+
readonly collect: {
|
|
364
|
+
/** A screenshot of the viewport. */
|
|
365
|
+
readonly screenshot: boolean;
|
|
366
|
+
/** The ARIA snapshot. */
|
|
367
|
+
readonly aria: boolean;
|
|
368
|
+
/** axe-core's violations. */
|
|
369
|
+
readonly axe: boolean;
|
|
370
|
+
/** The page's mounted fields, from the field probe. */
|
|
371
|
+
readonly fields: boolean;
|
|
372
|
+
/** Run the smoke test after rendering, within this budget. */
|
|
373
|
+
readonly smoke?: { readonly maxInteractions: number; readonly maxMs: number };
|
|
374
|
+
};
|
|
375
|
+
/** When this render must have ended, in ms since the epoch. */
|
|
376
|
+
readonly deadline: number;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/** `verify/render`'s answer; internal to Mostra. */
|
|
380
|
+
export interface RenderResult {
|
|
381
|
+
/** Whether the page reported `mostra/ready`. */
|
|
382
|
+
readonly ready: boolean;
|
|
383
|
+
/** What the runner found: page errors, console output, failed requests, axe, smoke, blank. */
|
|
384
|
+
readonly findings: readonly Diagnostic[];
|
|
385
|
+
/** The screenshot written, when asked for. */
|
|
386
|
+
readonly screenshot?: { readonly path: string; readonly width: number; readonly height: number };
|
|
387
|
+
/** The ARIA snapshot written, and its text, when asked for. */
|
|
388
|
+
readonly aria?: { readonly path: string; readonly text: string };
|
|
389
|
+
/** The mounted fields the probe reported, when asked for. */
|
|
390
|
+
readonly fields?: readonly ProbedField[];
|
|
391
|
+
/** What the smoke test did, when asked for. */
|
|
392
|
+
readonly smoke?: {
|
|
393
|
+
/** Controls used. */
|
|
394
|
+
readonly interactions: number;
|
|
395
|
+
/** Field writes they caused. */
|
|
396
|
+
readonly stateChanges: number;
|
|
397
|
+
/** Server functions the sandbox refused during the smoke test. */
|
|
398
|
+
readonly skipped: readonly string[];
|
|
399
|
+
/** Whether it stopped at its budget. */
|
|
400
|
+
readonly budget: boolean;
|
|
401
|
+
};
|
|
402
|
+
/** Whether the render ran past its deadline and stopped where it was. */
|
|
403
|
+
readonly timedOut: boolean;
|
|
404
|
+
/** When each step ended, in ms after the render started. */
|
|
405
|
+
readonly timingsMs: Readonly<Record<string, number>>;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** `verify/compare`'s params; internal to Mostra. */
|
|
409
|
+
export interface CompareRequest {
|
|
410
|
+
/** The baseline's screenshot. */
|
|
411
|
+
readonly a: string;
|
|
412
|
+
/** The source's screenshot. */
|
|
413
|
+
readonly b: string;
|
|
414
|
+
/** Where to write the difference image. */
|
|
415
|
+
readonly diff: string;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/** `verify/compare`'s answer; internal to Mostra. */
|
|
419
|
+
export interface CompareResult {
|
|
420
|
+
/** The share of pixels that differ beyond pixelmatch's perceptual threshold. */
|
|
421
|
+
readonly ratio: number;
|
|
422
|
+
/** Whether the two images had different sizes (then `ratio` is 1). */
|
|
423
|
+
readonly sizeChanged: boolean;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/** A one-line count of an ARIA snapshot: headings, controls and landmarks. */
|
|
427
|
+
export function ariaSummary(text: string): string {
|
|
428
|
+
const counts = new Map<string, number>();
|
|
429
|
+
for (const match of text.matchAll(/^\s*- ([a-z]+)\b/gm)) {
|
|
430
|
+
const role = match[1] as string;
|
|
431
|
+
counts.set(role, (counts.get(role) ?? 0) + 1);
|
|
432
|
+
}
|
|
433
|
+
const named: [string, string][] = [
|
|
434
|
+
["heading", "headings"],
|
|
435
|
+
["button", "buttons"],
|
|
436
|
+
["link", "links"],
|
|
437
|
+
["textbox", "text fields"],
|
|
438
|
+
["checkbox", "checkboxes"],
|
|
439
|
+
["combobox", "comboboxes"],
|
|
440
|
+
["tab", "tabs"],
|
|
441
|
+
["img", "images"],
|
|
442
|
+
["table", "tables"],
|
|
443
|
+
];
|
|
444
|
+
const parts = named
|
|
445
|
+
.filter(([role]) => counts.has(role))
|
|
446
|
+
.map(([role, plural]) => `${counts.get(role)} ${counts.get(role) === 1 ? role : plural}`);
|
|
447
|
+
const landmarks = [
|
|
448
|
+
"main",
|
|
449
|
+
"navigation",
|
|
450
|
+
"banner",
|
|
451
|
+
"contentinfo",
|
|
452
|
+
"form",
|
|
453
|
+
"region",
|
|
454
|
+
"dialog",
|
|
455
|
+
].filter((role) => counts.has(role));
|
|
456
|
+
if (landmarks.length > 0) parts.push(`landmarks: ${landmarks.join(", ")}`);
|
|
457
|
+
return parts.length > 0 ? parts.join(", ") : "no headings, controls or landmarks";
|
|
458
|
+
}
|
package/src/view.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What one view is (D104, D108): its artifact, version, policy, submit channels and trusted
|
|
3
|
+
* controls. The browser protocol's frame ticket, the bridge's `ui/initialize` result and the
|
|
4
|
+
* interaction core's channel policy share these shapes, so they live in a module of their own:
|
|
5
|
+
* the bridge, which every version embeds, imports them without the interaction schemas.
|
|
6
|
+
*/
|
|
7
|
+
import * as z from "zod";
|
|
8
|
+
import { ArtifactId, VersionId, ViewId } from "./ids.ts";
|
|
9
|
+
import { SubmissionPolicy } from "./manifest.ts";
|
|
10
|
+
import { wireRegistry } from "./wire-registry.ts";
|
|
11
|
+
|
|
12
|
+
/** Where a submit came from (D40). */
|
|
13
|
+
export type SubmitChannel = "shell" | "artifact";
|
|
14
|
+
|
|
15
|
+
/** The Zod schema of the `SubmitChannel` type. */
|
|
16
|
+
export const SubmitChannel: z.ZodType<SubmitChannel> = z
|
|
17
|
+
.enum(["shell", "artifact"])
|
|
18
|
+
.register(wireRegistry, {
|
|
19
|
+
id: "SubmitChannel",
|
|
20
|
+
description: "Where a submit comes from: the shell's trusted Submit, or the artifact's code.",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A trusted control the shell renders outside the artifact's frame (D06, PRODUCT vocabulary):
|
|
25
|
+
* Submit, Choose (review sets) and Approve. Open for later controls on the wire.
|
|
26
|
+
*/
|
|
27
|
+
export type TrustedControl = "submit" | "choose" | "approve" | (string & {});
|
|
28
|
+
|
|
29
|
+
/** The Zod schema of the `TrustedControl` type. */
|
|
30
|
+
export const TrustedControl: z.ZodType<TrustedControl> = z
|
|
31
|
+
.string()
|
|
32
|
+
.regex(/^[a-z][a-z0-9-]{0,31}$/)
|
|
33
|
+
.register(wireRegistry, {
|
|
34
|
+
id: "TrustedControl",
|
|
35
|
+
description: "A trusted control the shell renders: submit, choose, approve; open for more.",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Which submit channels a view accepts and which trusted controls its shell renders (D40, D108):
|
|
40
|
+
* the `trustedControls` port's answer, or the home's `HomeConfig.submitChannels`.
|
|
41
|
+
*/
|
|
42
|
+
export interface ControlsPolicy {
|
|
43
|
+
/** The channels submissions may come through; at least one. */
|
|
44
|
+
readonly submitChannels: readonly SubmitChannel[];
|
|
45
|
+
/** The trusted controls the shell may render; absent: every control the artifact asks for. */
|
|
46
|
+
readonly controls?: readonly TrustedControl[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The Zod schema of the `ControlsPolicy` type. */
|
|
50
|
+
export const ControlsPolicy: z.ZodType<ControlsPolicy> = z
|
|
51
|
+
.object({
|
|
52
|
+
submitChannels: z.array(SubmitChannel).min(1).max(2).readonly(),
|
|
53
|
+
controls: z.array(TrustedControl).max(32).readonly().exactOptional(),
|
|
54
|
+
})
|
|
55
|
+
.register(wireRegistry, {
|
|
56
|
+
id: "ControlsPolicy",
|
|
57
|
+
description:
|
|
58
|
+
"Which submit channels a view accepts and which trusted controls its shell renders (D108).",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/** A review set's ID: letters, digits, `_` and `-` (its choice is the field `review.<id>.choice`). */
|
|
62
|
+
export const REVIEW_SET_ID_PATTERN: RegExp = /^[A-Za-z0-9_-]{1,64}$/;
|
|
63
|
+
|
|
64
|
+
/** Where a client runtime runs (D111): Mostra's gateway, a static export, an MCP App, or `verify`. */
|
|
65
|
+
export type DeliveryTarget = "live" | "static" | "mcp-app" | "verify";
|
|
66
|
+
|
|
67
|
+
/** A version by ID and number. */
|
|
68
|
+
export interface VersionRef {
|
|
69
|
+
/** The version's ID. */
|
|
70
|
+
readonly id: string;
|
|
71
|
+
/** Its number, for people. */
|
|
72
|
+
readonly number: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** The Zod schema of the `VersionRef` type. */
|
|
76
|
+
export const VersionRef: z.ZodType<VersionRef> = z
|
|
77
|
+
.object({ id: VersionId.schema, number: z.int().min(1) })
|
|
78
|
+
.register(wireRegistry, {
|
|
79
|
+
id: "VersionRef",
|
|
80
|
+
description: "A version by ID and number.",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* What one view is (D104, D108): the shell learns it from its frame ticket and hands it to the
|
|
85
|
+
* frame in `ui/initialize`'s result, so the client runtime names the view in every request and
|
|
86
|
+
* knows what the host allows.
|
|
87
|
+
*/
|
|
88
|
+
export interface ViewContext {
|
|
89
|
+
/** The artifact. */
|
|
90
|
+
readonly artifactId: string;
|
|
91
|
+
/** The view this frame load is; every mutation and submit names it (D104). */
|
|
92
|
+
readonly viewId: string;
|
|
93
|
+
/** The version the view shows. */
|
|
94
|
+
readonly version: VersionRef;
|
|
95
|
+
/** The artifact's latest version when the view opened. */
|
|
96
|
+
readonly latest: VersionRef;
|
|
97
|
+
/** The submission policy in force (D102). */
|
|
98
|
+
readonly policy: SubmissionPolicy;
|
|
99
|
+
/** The submit channels this view accepts (D108). */
|
|
100
|
+
readonly submitChannels: readonly SubmitChannel[];
|
|
101
|
+
/** The trusted controls the shell renders for this view (D108). */
|
|
102
|
+
readonly controls: readonly TrustedControl[];
|
|
103
|
+
/** Always `live` in a frame Mostra's shell hosts. */
|
|
104
|
+
readonly target: DeliveryTarget;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** The Zod schema of the `ViewContext` type. */
|
|
108
|
+
export const ViewContext: z.ZodType<ViewContext> = z
|
|
109
|
+
.object({
|
|
110
|
+
artifactId: ArtifactId.schema,
|
|
111
|
+
viewId: ViewId.schema,
|
|
112
|
+
version: VersionRef,
|
|
113
|
+
latest: VersionRef,
|
|
114
|
+
policy: SubmissionPolicy,
|
|
115
|
+
submitChannels: z.array(SubmitChannel).min(1).max(2).readonly(),
|
|
116
|
+
controls: z.array(TrustedControl).max(32).readonly(),
|
|
117
|
+
target: z.enum(["live", "static", "mcp-app", "verify"]),
|
|
118
|
+
})
|
|
119
|
+
.register(wireRegistry, {
|
|
120
|
+
id: "ViewContext",
|
|
121
|
+
description:
|
|
122
|
+
"What one view is: its artifact, view ID, version, latest version, policy, channels and controls.",
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A view as a page reads it from `ui/initialize` (Claude review finding 5): every published
|
|
127
|
+
* version embeds the page's reader, so it takes values a later Mostra may add (a channel, a
|
|
128
|
+
* policy, a target) without refusing the whole view; {@link readViewContext} reads them safely.
|
|
129
|
+
*/
|
|
130
|
+
export interface ViewContextWire {
|
|
131
|
+
/** The artifact. */
|
|
132
|
+
readonly artifactId: string;
|
|
133
|
+
/** The view this frame load is (D104). */
|
|
134
|
+
readonly viewId: string;
|
|
135
|
+
/** The version the view shows. */
|
|
136
|
+
readonly version: VersionRef;
|
|
137
|
+
/** The artifact's latest version when the view opened. */
|
|
138
|
+
readonly latest: VersionRef;
|
|
139
|
+
/** The submission policy in force (D102); a later policy or scope is read as `once` per viewer. */
|
|
140
|
+
readonly policy: {
|
|
141
|
+
/** `once`, `epochs`, `none`, or one a later release adds. */
|
|
142
|
+
readonly policy: string;
|
|
143
|
+
/** `per-artifact` or `per-viewer` under `once`, or one a later release adds. */
|
|
144
|
+
readonly scope?: string;
|
|
145
|
+
};
|
|
146
|
+
/** The submit channels the view accepts (D108); channels this release doesn't know are not allowed. */
|
|
147
|
+
readonly submitChannels: readonly string[];
|
|
148
|
+
/** The trusted controls the shell renders for the view (D108). */
|
|
149
|
+
readonly controls: readonly string[];
|
|
150
|
+
/** Where the page runs (D111); a target this release doesn't know is read as `live`. */
|
|
151
|
+
readonly target: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** The Zod schema of the `ViewContextWire` type: open where later revisions may add values. */
|
|
155
|
+
export const ViewContextWire: z.ZodType<ViewContextWire> = z.looseObject({
|
|
156
|
+
artifactId: ArtifactId.schema,
|
|
157
|
+
viewId: ViewId.schema,
|
|
158
|
+
version: VersionRef,
|
|
159
|
+
latest: VersionRef,
|
|
160
|
+
policy: z.looseObject({ policy: z.string(), scope: z.string().exactOptional() }),
|
|
161
|
+
submitChannels: z.array(z.string()).max(16).readonly(),
|
|
162
|
+
controls: z.array(z.string()).max(32).readonly(),
|
|
163
|
+
target: z.string(),
|
|
164
|
+
}) as z.ZodType<ViewContextWire>;
|
|
165
|
+
|
|
166
|
+
const CONTROL_NAME = /^[a-z][a-z0-9-]{0,31}$/;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The view a page acts on, with every value this release doesn't know read the safe way: an
|
|
170
|
+
* unknown channel isn't allowed (the shell's stays), an unknown policy or `once` scope is read as
|
|
171
|
+
* `once` per viewer (the page may submit and the server decides; it closes on its own submission
|
|
172
|
+
* only), and an unknown target as `live`.
|
|
173
|
+
*/
|
|
174
|
+
export function readViewContext(wire: ViewContextWire): ViewContext {
|
|
175
|
+
const channels = (["shell", "artifact"] as const).filter((channel) =>
|
|
176
|
+
wire.submitChannels.includes(channel),
|
|
177
|
+
);
|
|
178
|
+
const { policy: name, scope } = wire.policy;
|
|
179
|
+
const policy: SubmissionPolicy =
|
|
180
|
+
name === "none"
|
|
181
|
+
? { policy: "none" }
|
|
182
|
+
: name === "epochs"
|
|
183
|
+
? { policy: "epochs" }
|
|
184
|
+
: name === "once" && (scope === undefined || scope === "per-artifact")
|
|
185
|
+
? { policy: "once", scope: "per-artifact" }
|
|
186
|
+
: { policy: "once", scope: "per-viewer" };
|
|
187
|
+
const target = (["live", "static", "mcp-app", "verify"] as const).find(
|
|
188
|
+
(known) => known === wire.target,
|
|
189
|
+
);
|
|
190
|
+
return {
|
|
191
|
+
artifactId: wire.artifactId,
|
|
192
|
+
viewId: wire.viewId,
|
|
193
|
+
version: wire.version,
|
|
194
|
+
latest: wire.latest,
|
|
195
|
+
policy,
|
|
196
|
+
submitChannels: channels.length > 0 ? channels : ["shell"],
|
|
197
|
+
controls: wire.controls.filter((control) => CONTROL_NAME.test(control)),
|
|
198
|
+
target: target ?? "live",
|
|
199
|
+
};
|
|
200
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// The one host API this package uses: Web Crypto's random source, present in browsers and in
|
|
2
|
+
// Node.js 19 and later. Declared here so the package compiles without DOM or Node types.
|
|
3
|
+
declare global {
|
|
4
|
+
var crypto: {
|
|
5
|
+
getRandomValues<T extends Uint8Array>(array: T): T;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export {};
|