@the-inclusionist/engine 10.0.0 → 11.0.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/README.md +32 -1
- package/app/css/style.css +216 -42
- package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
- package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
- package/app/public/vendor/fonts.css +11 -1175
- package/dist-pkg/boot/create-game.d.ts +84 -33
- package/dist-pkg/boot/create-game.js +708 -307
- package/dist-pkg/core/a11y-sr.d.ts +1 -1
- package/dist-pkg/core/a11y-sr.js +3 -5
- package/dist-pkg/core/accommodations.d.ts +26 -8
- package/dist-pkg/core/accommodations.js +27 -10
- package/dist-pkg/core/actions.d.ts +39 -10
- package/dist-pkg/core/actions.js +28 -6
- package/dist-pkg/core/contract.d.ts +0 -2
- package/dist-pkg/core/contract.js +0 -2
- package/dist-pkg/core/i18n.d.ts +36 -71
- package/dist-pkg/core/i18n.js +131 -198
- package/dist-pkg/core/session-clock.d.ts +23 -0
- package/dist-pkg/core/session-clock.js +37 -0
- package/dist-pkg/i18n/en.js +44 -49
- package/dist-pkg/i18n/es.js +44 -49
- package/dist-pkg/i18n/pt.js +49 -54
- package/dist-pkg/input/gamepad.d.ts +42 -11
- package/dist-pkg/input/gamepad.js +50 -15
- package/dist-pkg/input/key-default.d.ts +30 -0
- package/dist-pkg/input/key-default.js +60 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +0 -4
- package/dist-pkg/input/keyboard.d.ts +0 -1
- package/dist-pkg/input/keydown.d.ts +5 -11
- package/dist-pkg/input/keydown.js +3 -3
- package/dist-pkg/input/latch-edge.d.ts +10 -2
- package/dist-pkg/input/latch-edge.js +4 -3
- package/dist-pkg/input/latch-scope.d.ts +27 -22
- package/dist-pkg/input/latch-scope.js +25 -37
- package/dist-pkg/input/latch-store.d.ts +9 -12
- package/dist-pkg/input/latch-store.js +13 -18
- package/dist-pkg/input/latch-sync.d.ts +5 -4
- package/dist-pkg/input/latch-sync.js +5 -5
- package/dist-pkg/input/pad-reading.js +7 -2
- package/dist-pkg/input/pad-wizard.d.ts +4 -1
- package/dist-pkg/input/pad-wizard.js +60 -9
- package/dist-pkg/input/switch-scan.d.ts +29 -12
- package/dist-pkg/input/switch-scan.js +15 -2
- package/dist-pkg/input/touch-bindings.d.ts +3 -6
- package/dist-pkg/input/touch.d.ts +17 -2
- package/dist-pkg/input/touch.js +55 -17
- package/dist-pkg/input/transport-in-use.d.ts +5 -5
- package/dist-pkg/input/transport-in-use.js +5 -5
- package/dist-pkg/input/transports.d.ts +0 -9
- package/dist-pkg/input/transports.js +1 -1
- package/dist-pkg/input/virtual-controller.d.ts +39 -3
- package/dist-pkg/input/virtual-controller.js +32 -4
- package/dist-pkg/input/voice-map.d.ts +27 -11
- package/dist-pkg/input/voice-map.js +41 -43
- package/dist-pkg/platform/audio-ambient.d.ts +0 -1
- package/dist-pkg/platform/audio-ambient.js +3 -1
- package/dist-pkg/platform/audio-mixer.js +4 -9
- package/dist-pkg/platform/audio-sonar.d.ts +8 -94
- package/dist-pkg/platform/audio-sonar.js +22 -207
- package/dist-pkg/platform/audio.d.ts +10 -1
- package/dist-pkg/platform/audio.js +35 -2
- package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
- package/dist-pkg/platform/choose-by-voice.js +157 -0
- package/dist-pkg/platform/font-library.d.ts +77 -0
- package/dist-pkg/platform/font-library.js +98 -0
- package/dist-pkg/platform/font-library.json +721 -0
- package/dist-pkg/platform/heavy-catalogue.d.ts +46 -0
- package/dist-pkg/platform/heavy-catalogue.js +47 -14
- package/dist-pkg/platform/heavy-mirror.d.ts +3 -9
- package/dist-pkg/platform/heavy-mirror.js +14 -17
- package/dist-pkg/platform/heavy.d.ts +40 -8
- package/dist-pkg/platform/heavy.js +177 -22
- package/dist-pkg/platform/interruptible-speech.d.ts +15 -8
- package/dist-pkg/platform/interruptible-speech.js +37 -13
- package/dist-pkg/platform/listener-scope.js +22 -13
- package/dist-pkg/platform/locale-host.d.ts +7 -3
- package/dist-pkg/platform/locale-host.js +13 -2
- package/dist-pkg/platform/reading-in-worker.d.ts +24 -0
- package/dist-pkg/platform/reading-in-worker.js +38 -0
- package/dist-pkg/platform/reading-model.d.ts +21 -0
- package/dist-pkg/platform/reading-model.js +25 -0
- package/dist-pkg/platform/reading-runtime.js +13 -8
- package/dist-pkg/platform/reading.d.ts +12 -1
- package/dist-pkg/platform/reading.js +9 -1
- package/dist-pkg/platform/speech-recognition.d.ts +10 -1
- package/dist-pkg/platform/speech-recognition.js +29 -9
- package/dist-pkg/platform/speech.d.ts +10 -1
- package/dist-pkg/platform/speech.js +24 -13
- package/dist-pkg/platform/tts.d.ts +37 -4
- package/dist-pkg/platform/tts.js +279 -57
- package/dist-pkg/platform/voice-listener.d.ts +6 -2
- package/dist-pkg/platform/voice-listener.js +1 -1
- package/dist-pkg/platform/voice-plan.d.ts +13 -0
- package/dist-pkg/platform/voice-plan.js +57 -2
- package/dist-pkg/platform/vosk-runtime.d.ts +25 -0
- package/dist-pkg/platform/vosk-runtime.js +59 -1
- package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
- package/dist-pkg/platform/vosk-vocabulary.js +178 -0
- package/dist-pkg/render/crt.d.ts +11 -9
- package/dist-pkg/render/crt.js +6 -10
- package/dist-pkg/render/cvd-matrices.d.ts +5 -1
- package/dist-pkg/render/cvd-matrices.js +5 -1
- package/dist-pkg/render/high-contrast.d.ts +1 -2
- package/dist-pkg/render/high-contrast.js +5 -1
- package/dist-pkg/render/viz-axes.d.ts +9 -0
- package/dist-pkg/render/viz-axes.js +15 -2
- package/dist-pkg/ui/aac-sets.d.ts +29 -24
- package/dist-pkg/ui/aac-sets.js +22 -30
- package/dist-pkg/ui/audio-choices.d.ts +10 -5
- package/dist-pkg/ui/audio-choices.js +14 -10
- package/dist-pkg/ui/camera-control.d.ts +47 -0
- package/dist-pkg/ui/camera-control.js +35 -1
- package/dist-pkg/ui/declared-words.d.ts +21 -0
- package/dist-pkg/ui/declared-words.js +66 -0
- package/dist-pkg/ui/drawing-problems.js +4 -3
- package/dist-pkg/ui/eye-control.js +17 -17
- package/dist-pkg/ui/face-control.js +15 -15
- package/dist-pkg/ui/fonts.d.ts +42 -8
- package/dist-pkg/ui/fonts.js +58 -24
- package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
- package/dist-pkg/ui/footer-scroll-driver.js +201 -0
- package/dist-pkg/ui/footer-scroll.d.ts +38 -0
- package/dist-pkg/ui/footer-scroll.js +55 -0
- package/dist-pkg/ui/game-options.d.ts +14 -9
- package/dist-pkg/ui/game-options.js +41 -21
- package/dist-pkg/ui/hand-control.js +15 -15
- package/dist-pkg/ui/help-panel.d.ts +19 -8
- package/dist-pkg/ui/help-panel.js +15 -5
- package/dist-pkg/ui/hud-bands.d.ts +29 -12
- package/dist-pkg/ui/hud-bands.js +63 -25
- package/dist-pkg/ui/hud-row.d.ts +34 -0
- package/dist-pkg/ui/hud-row.js +80 -0
- package/dist-pkg/ui/hud.d.ts +0 -3
- package/dist-pkg/ui/layout.js +5 -2
- package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
- package/dist-pkg/ui/libras-avatar-clip.js +86 -0
- package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
- package/dist-pkg/ui/libras-avatar-load.js +134 -0
- package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
- package/dist-pkg/ui/libras-avatar-plan.js +211 -0
- package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
- package/dist-pkg/ui/libras-avatar-player.js +226 -0
- package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
- package/dist-pkg/ui/libras-avatar-stage.js +208 -0
- package/dist-pkg/ui/libras-glosses.d.ts +28 -0
- package/dist-pkg/ui/libras-glosses.js +161 -0
- package/dist-pkg/ui/menu-intent.d.ts +29 -0
- package/dist-pkg/ui/menu-intent.js +35 -1
- package/dist-pkg/ui/menu-items.d.ts +10 -0
- package/dist-pkg/ui/menu-items.js +29 -0
- package/dist-pkg/ui/menu-nav.d.ts +40 -4
- package/dist-pkg/ui/menu-nav.js +132 -47
- package/dist-pkg/ui/panel-widgets.d.ts +34 -0
- package/dist-pkg/ui/panel-widgets.js +86 -0
- package/dist-pkg/ui/pause-icons.d.ts +30 -14
- package/dist-pkg/ui/pause-icons.js +106 -45
- package/dist-pkg/ui/scan-overlay.d.ts +3 -3
- package/dist-pkg/ui/scan-overlay.js +11 -3
- package/dist-pkg/ui/screen-text.d.ts +25 -0
- package/dist-pkg/ui/screen-text.js +152 -0
- package/dist-pkg/ui/session-clock.d.ts +32 -0
- package/dist-pkg/ui/session-clock.js +67 -0
- package/dist-pkg/ui/settings-aac.d.ts +3 -1
- package/dist-pkg/ui/settings-aac.js +32 -13
- package/dist-pkg/ui/settings-audio.d.ts +10 -5
- package/dist-pkg/ui/settings-audio.js +101 -35
- package/dist-pkg/ui/settings-controls.d.ts +0 -4
- package/dist-pkg/ui/settings-mobility.d.ts +3 -6
- package/dist-pkg/ui/settings-mobility.js +4 -46
- package/dist-pkg/ui/settings-motion.js +2 -2
- package/dist-pkg/ui/settings-panel.d.ts +10 -0
- package/dist-pkg/ui/settings-panel.js +25 -1
- package/dist-pkg/ui/settings-typo.d.ts +5 -6
- package/dist-pkg/ui/settings-typo.js +20 -11
- package/dist-pkg/ui/settings-visual.js +2 -2
- package/dist-pkg/ui/shell.d.ts +1 -3
- package/dist-pkg/ui/shell.js +8 -4
- package/dist-pkg/ui/title.d.ts +2 -11
- package/dist-pkg/ui/title.js +39 -6
- package/dist-pkg/ui/top-band.d.ts +5 -3
- package/dist-pkg/ui/top-band.js +21 -25
- package/dist-pkg/ui/typo-choices.d.ts +3 -3
- package/dist-pkg/ui/typo-choices.js +9 -8
- package/dist-pkg/ui/vlibras.d.ts +71 -27
- package/dist-pkg/ui/vlibras.js +116 -44
- package/dist-pkg/ui/voice-control.d.ts +23 -1
- package/dist-pkg/ui/voice-control.js +149 -16
- package/dist-pkg/ui/voice-settings.d.ts +2 -3
- package/dist-pkg/ui/voice-settings.js +53 -3
- package/dist-pkg/ui/where-the-child-is.js +2 -2
- package/docs/CREDITS.md +122 -10
- package/docs/LICENSES.md +36 -7
- package/package.json +34 -9
- package/scripts/check-cartridge.mjs +78 -0
- package/scripts/game-build.d.mts +25 -0
- package/scripts/game-build.mjs +144 -0
- package/scripts/heavy-into-the-delivery.mjs +284 -40
- package/scripts/libras-avatar.json +680 -0
- package/scripts/libras-avatar.mjs +246 -0
- package/scripts/libras-glosses/gloss.py +95 -0
- package/scripts/libras-glosses/pyproject.toml +32 -0
- package/scripts/libras-glosses/uv.lock +781 -0
- package/scripts/libras-glosses.mjs +351 -0
- package/scripts/licences/OFL-1.1.txt +86 -0
- package/scripts/licences/UFL-1.0.txt +96 -0
- package/scripts/licences/fonts.mjs +389 -0
- package/scripts/licences/third-party.mjs +35 -21
- package/app/public/vendor/fonts/bitter-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/bitter-var.woff2 +0 -0
- package/app/public/vendor/fonts/bodonimoda-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/bodonimoda-var.woff2 +0 -0
- package/app/public/vendor/fonts/cat-abril_fatface-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-abril_fatface-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-adlam_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-adlam_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-agu_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-agu_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-alfa_slab_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-alfa_slab_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-are_you_serious-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-are_you_serious-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-asimovian-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-asimovian-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bakbak_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bakbak_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bangers-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bangers-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-barriecito-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-barriecito-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-berkshire_swash-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-berkshire_swash-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bevan-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bevan-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bitcount-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bitcount-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bowlby_one_sc-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bowlby_one_sc-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bungee_shade-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bungee_shade-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cherry_bomb_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cherry_bomb_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chokokutai-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chokokutai-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chonburi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chonburi-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-climate_crisis-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-climate_crisis-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cookie-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-dela_gothic_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-dela_gothic_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-fascinate_inline-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-fascinate_inline-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ga_maamli-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ga_maamli-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-itim-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-itim-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-jacquard_24-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-jacquard_24-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kablammo-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kablammo-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-katibeh-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-katibeh-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lemonada-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lemonada-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lilita_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lilita_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lobster-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lobster-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-luckiest_guy-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-luckiest_guy-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-marhey-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-marhey-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-modak-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-modak-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-momo_signature-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-momo_signature-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monofett-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monofett-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monomakh-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monomakh-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monoton-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monoton-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-nerko_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-nerko_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_adlam-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_adlam-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_arabic-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_arabic-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_devanagari-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_devanagari-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_hebrew-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_hebrew-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_jp-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_jp-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_khmer-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_khmer-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_kr-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_kr-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_sc-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_sc-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_thai-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_thai-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ole-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ole-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pacifico-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pacifico-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-patrick_hand-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-patrick_hand-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-petit_formal_script-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-petit_formal_script-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pixelify_sans-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pixelify_sans-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-plaster-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-plaster-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ar_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_at-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_at_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_nsw-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_nsw_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_qld-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_qld_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_sa-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_sa_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_tas-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_tas_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_vic-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_vic_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_vlg-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_vlg_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_wal-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_wal_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_br_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ca_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_co_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cu_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_grund-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_grund_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_la-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_la_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_sas-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_sas_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_va-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_va_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_loopet-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_loopet_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_uloopet-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_uloopet_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_es_deco_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_es_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_moderne-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_moderne_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_trad-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_gb_j_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_gb_s_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_lijeva-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_lijeva_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hu-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hu_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_id-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_id_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ie-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ie_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_in-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_in_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_is-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_is_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_moderna-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_moderna_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_trad-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_mx_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ng_modern-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ng_modern_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nl-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_no-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_no_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_basic-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_basic_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pe_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pl-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pt_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ro-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ro_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_sk-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_sk_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_tz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_tz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_us_modern_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_us_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_vn-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_vn_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_za-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_za_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-potta_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-potta_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranchers-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranchers-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-risque-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-risque-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruge_boogie-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruge_boogie-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruslan_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruslan_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sacramento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sacramento-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sancreek-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sancreek-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sankofa_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sankofa_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sedgwick_ave_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sedgwick_ave_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-shantell_sans-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-shantell_sans-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-smokum-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-smokum-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-solitreo-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-solitreo-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-spicy_rice-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-spicy_rice-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sriracha-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sriracha-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-stix_two_math-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-titan_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-titan_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yatra_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yatra_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yomogi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yomogi-400.woff2 +0 -0
- package/app/public/vendor/fonts/dmserifdisplay-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/dmserifdisplay-400.woff2 +0 -0
- package/app/public/vendor/fonts/domine-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/domine-var.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
- package/app/public/vendor/fonts/fraunces-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fraunces-var.woff2 +0 -0
- package/app/public/vendor/fonts/fredoka-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fredoka-var.woff2 +0 -0
- package/app/public/vendor/fonts/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.woff2 +0 -0
- package/app/public/vendor/fonts/jakarta-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/jakarta-var.woff2 +0 -0
- package/app/public/vendor/fonts/lato-400.woff2 +0 -0
- package/app/public/vendor/fonts/lato-700.woff2 +0 -0
- package/app/public/vendor/fonts/literata-400.woff2 +0 -0
- package/app/public/vendor/fonts/literata-700.woff2 +0 -0
- package/app/public/vendor/fonts/lora-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/lora-var.woff2 +0 -0
- package/app/public/vendor/fonts/merriweather-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/merriweather-var.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
- package/app/public/vendor/fonts/notosans-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/notosans-var.woff2 +0 -0
- package/app/public/vendor/fonts/nunito-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/nunito-var.woff2 +0 -0
- package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
- package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
- package/app/public/vendor/fonts/playfair-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/playfair-var.woff2 +0 -0
- package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
- package/app/public/vendor/fonts/quicksand-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/quicksand-var.woff2 +0 -0
- package/app/public/vendor/fonts/robotoflex-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/robotoflex-var.woff2 +0 -0
- package/app/public/vendor/fonts/sora-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/sora-var.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
- package/app/public/vendor/fonts/spacegrotesk-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spacegrotesk-var.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-400.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-700.woff2 +0 -0
- package/app/public/vendor/fonts/teachers-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/teachers-var.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-400.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
- package/dist-pkg/platform/guide-intensity.d.ts +0 -39
- package/dist-pkg/platform/guide-intensity.js +0 -71
- package/dist-pkg/ui/latch-refusal.d.ts +0 -33
- package/dist-pkg/ui/latch-refusal.js +0 -60
|
@@ -24,6 +24,52 @@ export declare function readingLanguageOf(id: string): string | null;
|
|
|
24
24
|
* models behind it out of the start of every delivery.
|
|
25
25
|
*/
|
|
26
26
|
export declare function commandsLanguageOf(id: string): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* WHERE THE DELIVERY PUTS THE LIBRAS PLAYER'S FILES (ADR-0234, route B, the engine's interpreter since phase B3): the avatar, its
|
|
29
|
+
* clips, their manifest and the build-time glosses, beside the game's page (`inclusionist-heavy --libras`). Written here, below
|
|
30
|
+
* the player that reads it (`ui/libras-avatar-plan` re-exports it), because the delivery's list of those files names it too.
|
|
31
|
+
*
|
|
32
|
+
* 📌 THERE IS NO CATALOGUE ENTRY FOR IT: the avatar and the clips are this project's own export of LAViD-UFPB's GPL-3.0 sign
|
|
33
|
+
* sources, pinned by sha256 in `scripts/libras-avatar.json`, and each delivery lists what it wrote (`DELIVERY_LISTS`). Nothing
|
|
34
|
+
* closed and nothing patched is served for it.
|
|
35
|
+
*/
|
|
36
|
+
export declare const LIBRAS_AVATAR_FOLDER = "libras/avatar/";
|
|
37
|
+
/**
|
|
38
|
+
* THE START OF THE FREE PLAYER'S STAGE CHUNK, under the page: `ui/libras-avatar-stage` and the three.js it carries, which the
|
|
39
|
+
* bundler emits as `assets/libras-avatar-stage-<content hash>.js`. The precache leaves it out on purpose (three.js is only a
|
|
40
|
+
* deaf-mode child's download), so the delivery finds the hashed name after the build and lists it; a NAME's start and not a
|
|
41
|
+
* folder, because the rest of `assets/` belongs to the precache.
|
|
42
|
+
*/
|
|
43
|
+
export declare const LIBRAS_AVATAR_STAGE_CHUNK = "assets/libras-avatar-stage-";
|
|
44
|
+
/**
|
|
45
|
+
* A LIST THE DELIVERY WRITES OF ITS OWN FILES, each with its sha256 — for what no catalogue entry can pin because each delivery
|
|
46
|
+
* makes it: the Libras player's avatar, clips and manifest, the glosses of the engine's and the game's texts, and the build's
|
|
47
|
+
* stage chunk (ADR-0234, pillar 8). The device reads the list and keeps each file only if its bytes are the listed ones, in the
|
|
48
|
+
* checked cache, under the file's own address, where the service worker answers the player from offline.
|
|
49
|
+
*
|
|
50
|
+
* ⚠️ WHAT THE LIST PROVES, AND WHAT IT DOES NOT: it comes from the page's own origin, like the page's code, so it is exactly as
|
|
51
|
+
* trusted as the page — it is not a pin. What it guarantees is that what is kept is what this delivery wrote: never a truncated
|
|
52
|
+
* body, a fallback page served for a missing file, or a file of the previous delivery. The avatar's and the clips' hashes in it
|
|
53
|
+
* are the ones `scripts/libras-avatar.json` pins, checked when the delivery wrote them.
|
|
54
|
+
*/
|
|
55
|
+
export interface DeliveryList {
|
|
56
|
+
readonly id: string;
|
|
57
|
+
/** Where the delivery writes the list, relative to the page. */
|
|
58
|
+
readonly path: string;
|
|
59
|
+
/**
|
|
60
|
+
* The only places the list may name, relative to the page: a listed file outside them is refused, never kept. Each is a
|
|
61
|
+
* folder (ending in `/`) or, for a file whose name the build hashes, the start of that name (`LIBRAS_AVATAR_STAGE_CHUNK`).
|
|
62
|
+
*/
|
|
63
|
+
readonly folders: readonly string[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The lists a device may read, each asked for with deaf mode (`heavyAtBoot`) — one per delivery step that writes files of its own:
|
|
67
|
+
* · `libras:avatar:delivery`, the Libras player's avatar, clips, manifest and glosses and the stage chunk with three.js, written by
|
|
68
|
+
* `--libras` (ADR-0234, phase B3). A delivery built without it has no such list: a quiet 404, and deaf mode says «signing
|
|
69
|
+
* unavailable» when the sonar is pressed.
|
|
70
|
+
* 📌 THE RULE IS «WHAT THE DELIVERY CARRIES, DEAF MODE KEEPS»: the files are kept whichever interpreter the host lends.
|
|
71
|
+
*/
|
|
72
|
+
export declare const DELIVERY_LISTS: readonly DeliveryList[];
|
|
27
73
|
/**
|
|
28
74
|
* 📌 Every entry with an address needs its licence group in `scripts/licences/third-party.mjs`: the delivery writes that group's
|
|
29
75
|
* `LICENSE` and `NOTICE` beside the file, and refuses a file whose licence nobody recorded (ADR-0177).
|
|
@@ -52,21 +52,23 @@ const MEDIAPIPE = Object.freeze([
|
|
|
52
52
|
* same reason — the engine imports nothing from npm at run time, so a game that never asks for this voice carries none of it, and
|
|
53
53
|
* the published package stays free of a bundler-only import.
|
|
54
54
|
*
|
|
55
|
-
* ·
|
|
56
|
-
* AGPL-3.0 (LICENSES.md)
|
|
55
|
+
* · eSpeak NG turns a sentence into phonemes, in every language the project speaks. GPL-3.0-or-later, compatible with the engine's
|
|
56
|
+
* AGPL-3.0 (LICENSES.md). It is the PROJECT'S OWN BUILD (issue #192): the npm build named no source, so the engine compiles it
|
|
57
|
+
* from a pinned commit (`scripts/models/build-espeak-ng.ps1`), and that commit and that recipe travel beside the mirror's copy.
|
|
58
|
+
* Its address is the project's mirror because nothing upstream holds these bytes.
|
|
57
59
|
* · onnxruntime-web runs Kokoro's graph. The `jsep` pair is what its own threads load, which is why both are here: a worker that
|
|
58
60
|
* cannot find them answers nothing, and the child hears silence (measured in the quiz demo, #181).
|
|
59
61
|
*
|
|
60
|
-
* ⚠️ sha256 MEASURED on the files the dev dependency
|
|
61
|
-
*
|
|
62
|
+
* ⚠️ sha256 MEASURED on the files, not taken from a page: onnxruntime-web's on those the dev dependency put on the build machine,
|
|
63
|
+
* which the first delivery run proved jsDelivr serves; eSpeak NG's on two runs of its recipe, which wrote the same bytes.
|
|
62
64
|
*/
|
|
63
|
-
const ESPEAK = 'https://
|
|
65
|
+
const ESPEAK = 'https://lfs-oinclusionista.jrocha.dev.br/espeak-ng-530bf0a';
|
|
64
66
|
const ORT = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.27.0';
|
|
65
67
|
const VOICE_RUNTIME = Object.freeze([
|
|
66
|
-
{ id: 'voz:runtime:fonemas', url: `${ESPEAK}/
|
|
67
|
-
sha256: '
|
|
68
|
-
{ id: 'voz:runtime:fonemas:wasm', url: `${ESPEAK}/
|
|
69
|
-
sha256: '
|
|
68
|
+
{ id: 'voz:runtime:fonemas', url: `${ESPEAK}/espeak-ng.js`, bytes: 70_951,
|
|
69
|
+
sha256: 'd2f7cea5ed29daed420a05271a48e5b7ab5315b1f4b33fa04ea54014c155889e' },
|
|
70
|
+
{ id: 'voz:runtime:fonemas:wasm', url: `${ESPEAK}/espeak-ng.wasm`, bytes: 1_493_661,
|
|
71
|
+
sha256: '44e0cc6accb436880d1d52d2dd7b69a72f8f6a8c8f2cdb3dcf00e3914db4eb05' },
|
|
70
72
|
{ id: 'voz:runtime:onnx', url: `${ORT}/dist/ort.webgpu.bundle.min.mjs`, bytes: 113_035,
|
|
71
73
|
sha256: '3a18c7f261e05d44a15b2eef18a28e5f53c044d5d140bcea6066baf1f09c8b53' },
|
|
72
74
|
{ id: 'voz:runtime:onnx:cola', url: `${ORT}/dist/ort-wasm-simd-threaded.jsep.mjs`, bytes: 46_614,
|
|
@@ -84,8 +86,9 @@ const VOICE_RUNTIME = Object.freeze([
|
|
|
84
86
|
* exported here from weights that ship no ONNX. The project mirrors them under ADR-0203 — «hospedar na Cloudflare do projeto» —
|
|
85
87
|
* with the licence of each beside it in `the-inclusionist-lfs`.
|
|
86
88
|
*
|
|
87
|
-
* ⚠️ AND THEY ARE BIG: 378 MiB for pt, 162 for en, 310 for es
|
|
88
|
-
*
|
|
89
|
+
* ⚠️ AND THEY ARE BIG: 378 MiB for pt, 162 for en, 310 for es — and a device that reads keeps all three, because a child tries
|
|
90
|
+
* the three languages at once (ADR-0225 erratum, the Dev: «Negativo, baixar os três.»). The start asks for the child's language
|
|
91
|
+
* first and then each other whole (`heavyAtBoot`); a game that does not declare `uses: { reading: true }` asks for none of them.
|
|
89
92
|
*
|
|
90
93
|
* 📌 The ids are in English while their neighbours are not: what is here stays until the renaming of the whole catalogue (the
|
|
91
94
|
* English plan, phase 2, a single BREAKING release), and nothing new arrives in Portuguese meanwhile.
|
|
@@ -152,9 +155,11 @@ export function readingLanguageOf(id) {
|
|
|
152
155
|
* rebuilt from lichess-org/vosk-browser with `-s DYNAMIC_EXECUTION=0` and runs under the policy as it is (`models.md`).
|
|
153
156
|
* The models are alphacephei's small ones, repacked deterministically as the `.tar.gz` that build loads.
|
|
154
157
|
*
|
|
155
|
-
* ⚠️ ONE MODEL PER LANGUAGE, like the reading: pt 30.9 MiB, en 39.2, es 37.9.
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
+
* ⚠️ ONE MODEL PER LANGUAGE, like the reading: pt 30.9 MiB, en 39.2, es 37.9. A delivery carries the three unless
|
|
159
|
+
* `inclusionist-heavy --commands` narrows it, and the start asks for every language the page can switch to, the child's first
|
|
160
|
+
* (ADR-0225 erratum: a language changed mid-game must find its model), as it does for the reading. 📌 But unlike the reading,
|
|
161
|
+
* NO GAME DECLARES THIS: a child who speaks instead of pressing is using a transport, and a cartridge does not get to deny her
|
|
162
|
+
* one (ADR-0111).
|
|
158
163
|
*
|
|
159
164
|
* ⚠️ sha256 MEASURED on the mirror's own files (2026-09-21), each checked against the `SHA256SUMS` its folder publishes.
|
|
160
165
|
*/
|
|
@@ -181,6 +186,34 @@ export function commandsLanguageOf(id) {
|
|
|
181
186
|
const parts = id.split(':');
|
|
182
187
|
return parts[0] === 'commands' && parts[1] === 'model' && parts[2] ? parts[2] : null;
|
|
183
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* WHERE THE DELIVERY PUTS THE LIBRAS PLAYER'S FILES (ADR-0234, route B, the engine's interpreter since phase B3): the avatar, its
|
|
191
|
+
* clips, their manifest and the build-time glosses, beside the game's page (`inclusionist-heavy --libras`). Written here, below
|
|
192
|
+
* the player that reads it (`ui/libras-avatar-plan` re-exports it), because the delivery's list of those files names it too.
|
|
193
|
+
*
|
|
194
|
+
* 📌 THERE IS NO CATALOGUE ENTRY FOR IT: the avatar and the clips are this project's own export of LAViD-UFPB's GPL-3.0 sign
|
|
195
|
+
* sources, pinned by sha256 in `scripts/libras-avatar.json`, and each delivery lists what it wrote (`DELIVERY_LISTS`). Nothing
|
|
196
|
+
* closed and nothing patched is served for it.
|
|
197
|
+
*/
|
|
198
|
+
export const LIBRAS_AVATAR_FOLDER = 'libras/avatar/';
|
|
199
|
+
/**
|
|
200
|
+
* THE START OF THE FREE PLAYER'S STAGE CHUNK, under the page: `ui/libras-avatar-stage` and the three.js it carries, which the
|
|
201
|
+
* bundler emits as `assets/libras-avatar-stage-<content hash>.js`. The precache leaves it out on purpose (three.js is only a
|
|
202
|
+
* deaf-mode child's download), so the delivery finds the hashed name after the build and lists it; a NAME's start and not a
|
|
203
|
+
* folder, because the rest of `assets/` belongs to the precache.
|
|
204
|
+
*/
|
|
205
|
+
export const LIBRAS_AVATAR_STAGE_CHUNK = 'assets/libras-avatar-stage-';
|
|
206
|
+
/**
|
|
207
|
+
* The lists a device may read, each asked for with deaf mode (`heavyAtBoot`) — one per delivery step that writes files of its own:
|
|
208
|
+
* · `libras:avatar:delivery`, the Libras player's avatar, clips, manifest and glosses and the stage chunk with three.js, written by
|
|
209
|
+
* `--libras` (ADR-0234, phase B3). A delivery built without it has no such list: a quiet 404, and deaf mode says «signing
|
|
210
|
+
* unavailable» when the sonar is pressed.
|
|
211
|
+
* 📌 THE RULE IS «WHAT THE DELIVERY CARRIES, DEAF MODE KEEPS»: the files are kept whichever interpreter the host lends.
|
|
212
|
+
*/
|
|
213
|
+
export const DELIVERY_LISTS = Object.freeze([
|
|
214
|
+
Object.freeze({ id: 'libras:avatar:delivery', path: 'libras/offline-avatar.json',
|
|
215
|
+
folders: Object.freeze([LIBRAS_AVATAR_FOLDER, LIBRAS_AVATAR_STAGE_CHUNK]) }),
|
|
216
|
+
]);
|
|
184
217
|
/**
|
|
185
218
|
* KOKORO (ADR-0186, ADR-0198; the Dev: «Faça»): the fp32 model, its tokenizer vocabulary and a style table per voice of the engine's
|
|
186
219
|
* languages. The engine loads them itself when a game declares `uses.neuralVoice` (ADR-0216); the phonemizer and the runtime that
|
|
@@ -4,15 +4,9 @@ export declare const MIRROR_FOLDERS: ReadonlyArray<readonly [string, string]>;
|
|
|
4
4
|
/**
|
|
5
5
|
* Addresses the project does NOT mirror, each with why — they go on being fetched upstream even when a base is set.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* catalogued byte counts. Nothing failed: the staging folder is marked «🔴 ON HOLD» and `upload-to-r2.ps1` skips it, because
|
|
11
|
-
* espeak-ng is GPL-3.0-or-later and serving the binary obliges publishing the matching SOURCE beside it (ADR-0203 erratum,
|
|
12
|
-
* issue #192). Emptying the list without checking what the bucket serves would have pointed every school at a 404.
|
|
13
|
-
*
|
|
14
|
-
* ⚠️ So it stays upstream until `espeak-ng-1.0.2/source/` exists. The decision to mirror it is unchanged; what is missing is
|
|
15
|
-
* the obligation that decision carries, and a mirror is distribution.
|
|
7
|
+
* 📌 EMPTY, and a line here is a written decision, never an omission. The last one was the npm build of eSpeak NG, kept upstream
|
|
8
|
+
* because the project could not name the source it was built from; the engine now pins its own build, whose folder carries that
|
|
9
|
+
* source (issue #192). ⚠️ Before adding a line, check what the bucket serves: the mirror answers 404 for a folder not uploaded.
|
|
16
10
|
*/
|
|
17
11
|
export declare const NOT_MIRRORED: ReadonlyArray<readonly [string, string]>;
|
|
18
12
|
/** The path a mirror serves this upstream address under, or `null` when no mirror of this project holds it. */
|
|
@@ -29,29 +29,26 @@ export const MIRROR_FOLDERS = [
|
|
|
29
29
|
// `vosk-browser` evaluates text as code, so this one was rebuilt with `-s DYNAMIC_EXECUTION=0` to run under the policy.
|
|
30
30
|
['https://lfs-oinclusionista.jrocha.dev.br/vosk-browser-dynamic-execution-0', 'vosk-browser-dynamic-execution-0'],
|
|
31
31
|
['https://lfs-oinclusionista.jrocha.dev.br/vosk-models', 'vosk-models'],
|
|
32
|
-
// The neural voice's phonemizer
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
['https://
|
|
32
|
+
// The neural voice's phonemizer, the project's own build of eSpeak NG (issue #192): it has no upstream either, and its folder
|
|
33
|
+
// carries the Corresponding Source the GPL asks for — the pinned commit and the recipe, in `corresponding-source/`. The commit is in the folder
|
|
34
|
+
// name on purpose: a mirror that drops it cannot serve two builds during an upgrade.
|
|
35
|
+
['https://lfs-oinclusionista.jrocha.dev.br/espeak-ng-530bf0a', 'espeak-ng-530bf0a'],
|
|
36
|
+
// The graph runtime the neural voice shares with the reading models (the Dev on 2026-09-22).
|
|
36
37
|
['https://cdn.jsdelivr.net/npm/onnxruntime-web@1.27.0', 'onnxruntime-web-1.27.0'],
|
|
38
|
+
// The font library (ADR-0255): one folder per family under `fonts/`, catalogued in `platform/font-library.json`. It has no
|
|
39
|
+
// upstream either — the library IS the project's copy, and the reserved-name families in it are their authors' originals.
|
|
40
|
+
['https://lfs-oinclusionista.jrocha.dev.br/fonts', 'fonts'],
|
|
41
|
+
// 📌 The Libras player's avatar and clips are not catalogue files: `--libras` reads them from `<base>/vlibras-avatar-<commit>/`
|
|
42
|
+
// by their own pins (`scripts/libras-avatar.mjs`), so no mapping for them lives here.
|
|
37
43
|
];
|
|
38
44
|
/**
|
|
39
45
|
* Addresses the project does NOT mirror, each with why — they go on being fetched upstream even when a base is set.
|
|
40
46
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* catalogued byte counts. Nothing failed: the staging folder is marked «🔴 ON HOLD» and `upload-to-r2.ps1` skips it, because
|
|
45
|
-
* espeak-ng is GPL-3.0-or-later and serving the binary obliges publishing the matching SOURCE beside it (ADR-0203 erratum,
|
|
46
|
-
* issue #192). Emptying the list without checking what the bucket serves would have pointed every school at a 404.
|
|
47
|
-
*
|
|
48
|
-
* ⚠️ So it stays upstream until `espeak-ng-1.0.2/source/` exists. The decision to mirror it is unchanged; what is missing is
|
|
49
|
-
* the obligation that decision carries, and a mirror is distribution.
|
|
47
|
+
* 📌 EMPTY, and a line here is a written decision, never an omission. The last one was the npm build of eSpeak NG, kept upstream
|
|
48
|
+
* because the project could not name the source it was built from; the engine now pins its own build, whose folder carries that
|
|
49
|
+
* source (issue #192). ⚠️ Before adding a line, check what the bucket serves: the mirror answers 404 for a folder not uploaded.
|
|
50
50
|
*/
|
|
51
|
-
export const NOT_MIRRORED = [
|
|
52
|
-
['https://cdn.jsdelivr.net/npm/espeak-ng@1.0.2',
|
|
53
|
-
'GPL: the mirror folder is ON HOLD until the matching source is published beside the build (issue #192)'],
|
|
54
|
-
];
|
|
51
|
+
export const NOT_MIRRORED = [];
|
|
55
52
|
/** The path a mirror serves this upstream address under, or `null` when no mirror of this project holds it. */
|
|
56
53
|
export function mirrorPathOf(url) {
|
|
57
54
|
if (NOT_MIRRORED.some(([prefix]) => url.startsWith(prefix)))
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
2
|
import { CACHE_HEAVY, HEAVY_FILES, type HeavyFile } from './heavy-catalogue.js';
|
|
3
3
|
export { CACHE_HEAVY, HEAVY_FILES };
|
|
4
|
-
export type { HeavyFile };
|
|
5
4
|
/** What happened to each entry, so the caller can tell a person. */
|
|
6
5
|
export interface HeavyReport {
|
|
7
6
|
readonly id: string;
|
|
@@ -28,8 +27,16 @@ export interface HeavyOptions {
|
|
|
28
27
|
* `crypto.subtle`, which is an insecure context) keeps NOTHING: unverifiable is not verified.
|
|
29
28
|
*/
|
|
30
29
|
readonly digest: ((payload: ArrayBuffer) => Promise<string>) | null;
|
|
31
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Only these ids, when given, and IN THIS ORDER — the download is one at a time, so the order is who waits (`heavyAtBoot`
|
|
32
|
+
* puts everything of the child's language first). For a consumer that wants the voices and not the rest.
|
|
33
|
+
*/
|
|
32
34
|
readonly only?: readonly string[];
|
|
35
|
+
/**
|
|
36
|
+
* Files OUTSIDE the catalogue, kept by the same rules and FIRST: the font library's faces a cartridge declared
|
|
37
|
+
* (`platform/font-library`, ADR-0255) — a few hundred KB the child sees, which should not wait behind 850 MiB of models.
|
|
38
|
+
*/
|
|
39
|
+
readonly also?: readonly HeavyFile[];
|
|
33
40
|
/** The page's address the delivery's `heavy/` folder is resolved against (`document.baseURI`). */
|
|
34
41
|
readonly base: string;
|
|
35
42
|
}
|
|
@@ -38,21 +45,43 @@ export interface HeavyOptions {
|
|
|
38
45
|
*
|
|
39
46
|
* · The neural voice — its model, its voices AND the runtime that speaks them: without that answer they are 372 MB taken from a
|
|
40
47
|
* school's link and a child's device for nothing.
|
|
41
|
-
* · The reading models
|
|
42
|
-
*
|
|
48
|
+
* · The reading models, one per language (850 MiB for the three): `reading` is a language or a LIST of them, like `commands`, and
|
|
49
|
+
* the root asks for every language the page can switch to, the child's first (ADR-0225 erratum, the Dev: «Negativo, baixar os
|
|
50
|
+
* três. Toda criança vai experimentar as três línguas imediatamente.»). A language the delivery's `--reading` list left out is a
|
|
51
|
+
* quiet 404 here and, when she reads in it, a line of `problems` and a sentence to her. A game that never listens gets none.
|
|
43
52
|
* · 🔴 THE GRAPH RUNTIME IS NOT THE VOICE'S, and its `voz:` name said otherwise. `platform/onnx-runtime` runs Kokoro AND the
|
|
44
53
|
* reading models, so a game that only LISTENS needs it: without this line its delivery carried a 378 MiB model and nothing
|
|
45
54
|
* able to open it, and the first `listen()` asked for a file the build never wrote. Measured on 2026-09-21, building the
|
|
46
55
|
* very delivery this exists to serve. The PHONEMIZER (`voz:runtime:fonemas`, 18.7 MiB) stays the voice's — nothing else
|
|
47
56
|
* turns letters into sounds.
|
|
48
|
-
* · The command models (issue #184): one per language too,
|
|
57
|
+
* · The command models (issue #184): one per language too, 108 MiB for the three, and the runtime that loads them. Nothing in
|
|
49
58
|
* the game decides this — speaking instead of pressing is a way INTO the controller, and a cartridge does not get to close
|
|
50
|
-
* one (ADR-0111).
|
|
59
|
+
* one (ADR-0111). `commands` is a language or a LIST of them, and the models come in the list's order: the root asks for
|
|
60
|
+
* every language the page can switch to, the child's first, because a language changed mid-game must find its model already
|
|
61
|
+
* kept (ADR-0225 erratum, the Dev: «A entrega leva as três línguas.»). The delivery carries the three unless its
|
|
62
|
+
* `--commands` list narrows it; a language it did not carry is a quiet 404 here and a line of `problems` when she speaks.
|
|
63
|
+
* · The Libras player (ADR-0234): the delivery's list of its avatar, clips, glosses and three.js chunk (34.9 MB in the engine's
|
|
64
|
+
* delivery), only with `libras`: the root asks for it while deaf mode is on, so a device whose child never asks for signing
|
|
65
|
+
* never downloads it. No game declares it either — deaf mode is the person's (ADR-0111) — and a delivery built without
|
|
66
|
+
* `--libras` simply has none, the same quiet 404 as a missing command model. No catalogue file is the player's: it is all the
|
|
67
|
+
* delivery's own, kept by what the delivery carries.
|
|
68
|
+
* The ids are the catalogue's files, then the delivery lists (`DELIVERY_LISTS`), by one rule.
|
|
69
|
+
*
|
|
70
|
+
* 🔴 THE ORDER IS WHO WAITS, because the download is one file at a time (rule 1): a file of a language takes that language's
|
|
71
|
+
* position in the list it was asked by, a file of no language (the runtimes, vision) takes the first, and the sort is stable. So
|
|
72
|
+
* everything of the child's language comes first, then each other language whole — her command model never waits behind 470 MiB
|
|
73
|
+
* of another language's reading.
|
|
74
|
+
* 🔴 AND WITHIN A POSITION, THE WAYS IN COME FIRST (`waitsBehind`): the command models and the camera's reader are how a child
|
|
75
|
+
* who does not press reaches the game at all (ADR-0111), and they have nothing to fall back on; the reading is the game's own
|
|
76
|
+
* listening, with nothing either; the neural voice comes last, because the browser's voice speaks meanwhile (ADR-0200). 📏 In
|
|
77
|
+
* the catalogue's order a 👄 turned on in a fresh install waited behind 336 MiB of neural voice and 378 MiB of reading for a
|
|
78
|
+
* 34 MiB model — seven seconds from a local disk, minutes on a school's link (measured on 2026-09-27).
|
|
51
79
|
*/
|
|
52
80
|
export declare function heavyAtBoot(declared: {
|
|
53
81
|
readonly kokoro: boolean;
|
|
54
|
-
readonly reading?: string | null;
|
|
55
|
-
readonly commands?: string | null;
|
|
82
|
+
readonly reading?: string | readonly string[] | null;
|
|
83
|
+
readonly commands?: string | readonly string[] | null;
|
|
84
|
+
readonly libras?: boolean;
|
|
56
85
|
}): readonly string[];
|
|
57
86
|
/**
|
|
58
87
|
* WHERE THE DELIVERY SERVES A HEAVY FILE (ADR-0177, issue #173): `heavy/<host><path>` beside the page. The child's device
|
|
@@ -87,6 +116,9 @@ export declare function deliveryCacheKey(urlOrRequest: string | {
|
|
|
87
116
|
* ⚠️ ENTRIES WITHOUT A `url` ARE NOT SKIPPED IN SILENCE — they return `sem-fonte`. It is the difference between "this
|
|
88
117
|
* subsystem has nowhere to come from yet" and "this subsystem is handled", exactly the distinction ADR-0119 measured as
|
|
89
118
|
* missing: the engine PROMISED four things and delivered one, with nothing saying so.
|
|
119
|
+
*
|
|
120
|
+
* The files handed in `also` come first (the declared library fonts), then the catalogue's, then the delivery's lists
|
|
121
|
+
* (`DELIVERY_LISTS`), each list ONE report for all its files.
|
|
90
122
|
*/
|
|
91
123
|
export declare function downloadHeavy(options: HeavyOptions): Promise<HeavyReport[]>;
|
|
92
124
|
/**
|
|
@@ -16,43 +16,95 @@
|
|
|
16
16
|
// start over a resource it may not even use today.
|
|
17
17
|
// 3. **IDEMPOTENT.** What is already in Cache Storage is not fetched again — which is what makes this safe to call on
|
|
18
18
|
// every start instead of only "on the first", which nobody can detect honestly.
|
|
19
|
-
import { CACHE_HEAVY, HEAVY_FILES, readingLanguageOf, commandsLanguageOf } from './heavy-catalogue.js';
|
|
19
|
+
import { CACHE_HEAVY, HEAVY_FILES, DELIVERY_LISTS, readingLanguageOf, commandsLanguageOf, } from './heavy-catalogue.js';
|
|
20
20
|
export { CACHE_HEAVY, HEAVY_FILES };
|
|
21
|
+
/**
|
|
22
|
+
* Who waits behind whom inside one language's position (`heavyAtBoot`): 0 the ways in (the command models and runtime, the
|
|
23
|
+
* camera's reader), 1 the reading and the graph runtime it opens its models with, 2 the rest — the neural voice, which the
|
|
24
|
+
* browser's voice covers until it lands.
|
|
25
|
+
*/
|
|
26
|
+
function waitsBehind(id) {
|
|
27
|
+
if (id.startsWith('commands:') || id.startsWith('visao:'))
|
|
28
|
+
return 0;
|
|
29
|
+
if (id.startsWith('reading:') || id.startsWith('voz:runtime:onnx'))
|
|
30
|
+
return 1;
|
|
31
|
+
return 2;
|
|
32
|
+
}
|
|
21
33
|
/**
|
|
22
34
|
* WHAT A GAME'S START FETCHES (ADR-0216 §3): the catalogue, less what this game did not ask for.
|
|
23
35
|
*
|
|
24
36
|
* · The neural voice — its model, its voices AND the runtime that speaks them: without that answer they are 372 MB taken from a
|
|
25
37
|
* school's link and a child's device for nothing.
|
|
26
|
-
* · The reading models
|
|
27
|
-
*
|
|
38
|
+
* · The reading models, one per language (850 MiB for the three): `reading` is a language or a LIST of them, like `commands`, and
|
|
39
|
+
* the root asks for every language the page can switch to, the child's first (ADR-0225 erratum, the Dev: «Negativo, baixar os
|
|
40
|
+
* três. Toda criança vai experimentar as três línguas imediatamente.»). A language the delivery's `--reading` list left out is a
|
|
41
|
+
* quiet 404 here and, when she reads in it, a line of `problems` and a sentence to her. A game that never listens gets none.
|
|
28
42
|
* · 🔴 THE GRAPH RUNTIME IS NOT THE VOICE'S, and its `voz:` name said otherwise. `platform/onnx-runtime` runs Kokoro AND the
|
|
29
43
|
* reading models, so a game that only LISTENS needs it: without this line its delivery carried a 378 MiB model and nothing
|
|
30
44
|
* able to open it, and the first `listen()` asked for a file the build never wrote. Measured on 2026-09-21, building the
|
|
31
45
|
* very delivery this exists to serve. The PHONEMIZER (`voz:runtime:fonemas`, 18.7 MiB) stays the voice's — nothing else
|
|
32
46
|
* turns letters into sounds.
|
|
33
|
-
* · The command models (issue #184): one per language too,
|
|
47
|
+
* · The command models (issue #184): one per language too, 108 MiB for the three, and the runtime that loads them. Nothing in
|
|
34
48
|
* the game decides this — speaking instead of pressing is a way INTO the controller, and a cartridge does not get to close
|
|
35
|
-
* one (ADR-0111).
|
|
49
|
+
* one (ADR-0111). `commands` is a language or a LIST of them, and the models come in the list's order: the root asks for
|
|
50
|
+
* every language the page can switch to, the child's first, because a language changed mid-game must find its model already
|
|
51
|
+
* kept (ADR-0225 erratum, the Dev: «A entrega leva as três línguas.»). The delivery carries the three unless its
|
|
52
|
+
* `--commands` list narrows it; a language it did not carry is a quiet 404 here and a line of `problems` when she speaks.
|
|
53
|
+
* · The Libras player (ADR-0234): the delivery's list of its avatar, clips, glosses and three.js chunk (34.9 MB in the engine's
|
|
54
|
+
* delivery), only with `libras`: the root asks for it while deaf mode is on, so a device whose child never asks for signing
|
|
55
|
+
* never downloads it. No game declares it either — deaf mode is the person's (ADR-0111) — and a delivery built without
|
|
56
|
+
* `--libras` simply has none, the same quiet 404 as a missing command model. No catalogue file is the player's: it is all the
|
|
57
|
+
* delivery's own, kept by what the delivery carries.
|
|
58
|
+
* The ids are the catalogue's files, then the delivery lists (`DELIVERY_LISTS`), by one rule.
|
|
59
|
+
*
|
|
60
|
+
* 🔴 THE ORDER IS WHO WAITS, because the download is one file at a time (rule 1): a file of a language takes that language's
|
|
61
|
+
* position in the list it was asked by, a file of no language (the runtimes, vision) takes the first, and the sort is stable. So
|
|
62
|
+
* everything of the child's language comes first, then each other language whole — her command model never waits behind 470 MiB
|
|
63
|
+
* of another language's reading.
|
|
64
|
+
* 🔴 AND WITHIN A POSITION, THE WAYS IN COME FIRST (`waitsBehind`): the command models and the camera's reader are how a child
|
|
65
|
+
* who does not press reaches the game at all (ADR-0111), and they have nothing to fall back on; the reading is the game's own
|
|
66
|
+
* listening, with nothing either; the neural voice comes last, because the browser's voice speaks meanwhile (ADR-0200). 📏 In
|
|
67
|
+
* the catalogue's order a 👄 turned on in a fresh install waited behind 336 MiB of neural voice and 378 MiB of reading for a
|
|
68
|
+
* 34 MiB model — seven seconds from a local disk, minutes on a school's link (measured on 2026-09-27).
|
|
36
69
|
*/
|
|
37
70
|
export function heavyAtBoot(declared) {
|
|
38
|
-
const reading = declared.reading
|
|
39
|
-
const commands = declared.commands
|
|
40
|
-
|
|
41
|
-
const language = readingLanguageOf(
|
|
71
|
+
const reading = languagesAsked(declared.reading);
|
|
72
|
+
const commands = languagesAsked(declared.commands);
|
|
73
|
+
const asked = (id) => {
|
|
74
|
+
const language = readingLanguageOf(id);
|
|
42
75
|
if (language)
|
|
43
|
-
return language
|
|
76
|
+
return reading.includes(language);
|
|
44
77
|
// 📌 THE COMMAND MODELS ARE A TRANSPORT'S, not a game's: no cartridge declares them, because a child who speaks instead of
|
|
45
|
-
// pressing is reaching the controller, and a cartridge does not get to deny her a way in (ADR-0111). The
|
|
46
|
-
// asked
|
|
47
|
-
const commanded = commandsLanguageOf(
|
|
78
|
+
// pressing is reaching the controller, and a cartridge does not get to deny her a way in (ADR-0111). The LANGUAGES are
|
|
79
|
+
// still asked, and the runtime comes with whichever one is.
|
|
80
|
+
const commanded = commandsLanguageOf(id);
|
|
48
81
|
if (commanded)
|
|
49
|
-
return commanded
|
|
50
|
-
if (
|
|
51
|
-
return
|
|
52
|
-
if (
|
|
53
|
-
return declared.
|
|
54
|
-
|
|
55
|
-
|
|
82
|
+
return commands.includes(commanded);
|
|
83
|
+
if (id.startsWith('commands:runtime'))
|
|
84
|
+
return commands.length > 0;
|
|
85
|
+
if (id.startsWith('libras:'))
|
|
86
|
+
return !!declared.libras;
|
|
87
|
+
if (id.startsWith('voz:runtime:onnx'))
|
|
88
|
+
return declared.kokoro || reading.length > 0;
|
|
89
|
+
return declared.kokoro || !(id.startsWith('voz:kokoro:') || id.startsWith('voz:runtime:'));
|
|
90
|
+
};
|
|
91
|
+
const rank = (id) => {
|
|
92
|
+
const read = readingLanguageOf(id);
|
|
93
|
+
if (read)
|
|
94
|
+
return reading.indexOf(read);
|
|
95
|
+
const spoken = commandsLanguageOf(id);
|
|
96
|
+
return spoken ? commands.indexOf(spoken) : 0;
|
|
97
|
+
};
|
|
98
|
+
return [
|
|
99
|
+
// `Array.prototype.sort` is stable (ES2019): within a position and a kind, the catalogue's order — a runtime before its model
|
|
100
|
+
...HEAVY_FILES.map((p) => p.id).filter(asked).sort((a, b) => rank(a) - rank(b) || waitsBehind(a) - waitsBehind(b)),
|
|
101
|
+
...DELIVERY_LISTS.map((l) => l.id).filter(asked),
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
/** The base languages asked — one tag or a list of them — without repeats, in the order asked (`es-MX` asks for `es`). */
|
|
105
|
+
function languagesAsked(asked) {
|
|
106
|
+
const tags = asked == null ? [] : typeof asked === 'string' ? [asked] : asked;
|
|
107
|
+
return [...new Set(tags.filter(Boolean).map((tag) => tag.split('-')[0].toLowerCase()))];
|
|
56
108
|
}
|
|
57
109
|
/**
|
|
58
110
|
* WHERE THE DELIVERY SERVES A HEAVY FILE (ADR-0177, issue #173): `heavy/<host><path>` beside the page. The child's device
|
|
@@ -91,20 +143,28 @@ export function deliveryCacheKey(urlOrRequest) {
|
|
|
91
143
|
* ⚠️ ENTRIES WITHOUT A `url` ARE NOT SKIPPED IN SILENCE — they return `sem-fonte`. It is the difference between "this
|
|
92
144
|
* subsystem has nowhere to come from yet" and "this subsystem is handled", exactly the distinction ADR-0119 measured as
|
|
93
145
|
* missing: the engine PROMISED four things and delivered one, with nothing saying so.
|
|
146
|
+
*
|
|
147
|
+
* The files handed in `also` come first (the declared library fonts), then the catalogue's, then the delivery's lists
|
|
148
|
+
* (`DELIVERY_LISTS`), each list ONE report for all its files.
|
|
94
149
|
*/
|
|
95
150
|
export async function downloadHeavy(options) {
|
|
96
|
-
const targets = options.
|
|
151
|
+
const targets = [...(options.also ?? []), ...(options.only
|
|
152
|
+
? [...new Set(options.only)].flatMap((id) => HEAVY_FILES.filter((p) => p.id === id))
|
|
153
|
+
: HEAVY_FILES)];
|
|
154
|
+
const lists = DELIVERY_LISTS.filter((l) => !options.only || options.only.includes(l.id));
|
|
97
155
|
const out = [];
|
|
98
156
|
const record = (r) => { out.push(r); options.onProgress?.(r); };
|
|
99
157
|
const { cacheStorage, fetch: fetchFile, digest, base } = options;
|
|
100
158
|
if (!cacheStorage || !fetchFile) {
|
|
101
|
-
for (const p of targets)
|
|
159
|
+
for (const p of [...targets, ...lists])
|
|
102
160
|
record({ id: p.id, outcome: 'falhou', error: 'sem Cache Storage ou sem fetch' });
|
|
103
161
|
return out;
|
|
104
162
|
}
|
|
105
163
|
const tools = { cache: await cacheStorage.open(CACHE_HEAVY), fetchFile, digest, base };
|
|
106
164
|
for (const p of targets)
|
|
107
165
|
record(await fetchOne(p, tools));
|
|
166
|
+
for (const l of lists)
|
|
167
|
+
record(await keepListed(l, tools));
|
|
108
168
|
return out;
|
|
109
169
|
}
|
|
110
170
|
/** One file's fate: already kept, fetched from the delivery and checked, or refused — always with the reason. */
|
|
@@ -142,6 +202,101 @@ async function keepIfChecked(p, url, resp, t) {
|
|
|
142
202
|
await t.cache.put(url, new Response(body, { status: resp.status, statusText: resp.statusText, headers: resp.headers }));
|
|
143
203
|
return { id: p.id, outcome: 'baixado', bytes: p.bytes };
|
|
144
204
|
}
|
|
205
|
+
/** The header a file kept from a delivery's list carries its listed sha256 in: how a later start knows it is kept, and current. */
|
|
206
|
+
const LISTED_SHA256 = 'x-inclusionist-sha256';
|
|
207
|
+
/**
|
|
208
|
+
* The files a delivery's list names, or a THROW saying why the list is refused whole: a list with no `files`, an entry without a
|
|
209
|
+
* path or a sha256, or one whose address falls outside the list's folders (a `..`, another origin, a query) — the list may only
|
|
210
|
+
* put the player's own files in the checked cache, never the game's page nor anything a route outside those folders serves.
|
|
211
|
+
*/
|
|
212
|
+
function listedFiles(data, l, base) {
|
|
213
|
+
const files = data?.files;
|
|
214
|
+
if (!Array.isArray(files))
|
|
215
|
+
throw new Error('its `files` is missing');
|
|
216
|
+
const folders = l.folders.map((folder) => new URL(folder, base).href);
|
|
217
|
+
return files.map((f) => {
|
|
218
|
+
const { path, sha256 } = (f ?? {});
|
|
219
|
+
if (typeof path !== 'string' || typeof sha256 !== 'string' || !/^[0-9a-f]{64}$/.test(sha256)) {
|
|
220
|
+
throw new Error(`a listed file is malformed: ${JSON.stringify(f)}`);
|
|
221
|
+
}
|
|
222
|
+
const at = new URL(path, base);
|
|
223
|
+
const url = at.href;
|
|
224
|
+
if (at.search || at.hash || !folders.some((folder) => url.startsWith(folder) && url.length > folder.length)) {
|
|
225
|
+
throw new Error(`it names ${path}, outside ${l.folders.join(' and ')}`);
|
|
226
|
+
}
|
|
227
|
+
return { path, url, sha256 };
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* A DELIVERY'S LIST, KEPT FILE BY FILE (ADR-0234, pillar 8): the list is read from the page's origin, and each file it names is
|
|
232
|
+
* fetched from there, CHECKED against its listed sha256, and kept under its own address, where the service worker answers it
|
|
233
|
+
* offline. A file already kept with that sha256 is not fetched again; a body that is not the listed one is never kept, and the
|
|
234
|
+
* report names it. One report for the list: `baixado` with the bytes fetched, `ja-tinha`, or `falhou` with the files refused.
|
|
235
|
+
*/
|
|
236
|
+
async function keepListed(l, t) {
|
|
237
|
+
const failed = (error) => ({ id: l.id, outcome: 'falhou', error });
|
|
238
|
+
const digest = t.digest;
|
|
239
|
+
if (!digest)
|
|
240
|
+
return failed('this host cannot compute a sha256 (crypto.subtle needs a secure context)');
|
|
241
|
+
const files = await readList(l, t);
|
|
242
|
+
if (typeof files === 'string')
|
|
243
|
+
return failed(files);
|
|
244
|
+
const refused = [];
|
|
245
|
+
let bytes = 0;
|
|
246
|
+
let fetched = 0;
|
|
247
|
+
for (const f of files) {
|
|
248
|
+
const kept = await keepListedFile(f, t, digest);
|
|
249
|
+
if (typeof kept === 'string')
|
|
250
|
+
refused.push(`${f.path}: ${kept}`);
|
|
251
|
+
else if (kept !== null) {
|
|
252
|
+
bytes += kept;
|
|
253
|
+
fetched += 1;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!refused.length)
|
|
257
|
+
return fetched ? { id: l.id, outcome: 'baixado', bytes } : { id: l.id, outcome: 'ja-tinha' };
|
|
258
|
+
const more = refused.length > 5 ? `; and ${refused.length - 5} more` : '';
|
|
259
|
+
return failed(`${refused.length} of ${files.length} files of ${l.path} not kept: ${refused.slice(0, 5).join('; ')}${more}`);
|
|
260
|
+
}
|
|
261
|
+
/** The list's files, or why it is refused whole (not there, not JSON, or naming what it may not). */
|
|
262
|
+
async function readList(l, t) {
|
|
263
|
+
try {
|
|
264
|
+
// never an old copy of the list: it is what says which files are current
|
|
265
|
+
const resp = await t.fetchFile(new URL(l.path, t.base).href, { cache: 'no-store' });
|
|
266
|
+
if (!resp.ok)
|
|
267
|
+
return `HTTP ${resp.status} — ${l.path}`;
|
|
268
|
+
return listedFiles(await resp.json(), l, t.base);
|
|
269
|
+
}
|
|
270
|
+
catch (e) {
|
|
271
|
+
return `the list ${l.path} is refused: ${e instanceof Error ? e.message : String(e)}`;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/** One listed file: `null` when it is already kept with its listed hash, the bytes kept, or why it was not kept. */
|
|
275
|
+
async function keepListedFile(f, t, digest) {
|
|
276
|
+
try {
|
|
277
|
+
if ((await t.cache.match(f.url))?.headers.get(LISTED_SHA256) === f.sha256)
|
|
278
|
+
return null;
|
|
279
|
+
/*
|
|
280
|
+
* 📌 THE LISTED HASH GOES IN THE QUERY: the service worker answers these folders from this cache by their address, so a file
|
|
281
|
+
* the list CHANGED would be answered with the copy it replaces. Another address reaches the delivery, and the old copy stays
|
|
282
|
+
* kept until the new one is checked — offline a child keeps the player she had.
|
|
283
|
+
*/
|
|
284
|
+
const resp = await t.fetchFile(`${f.url}?sha256=${f.sha256}`);
|
|
285
|
+
if (!resp.ok)
|
|
286
|
+
return `HTTP ${resp.status}`;
|
|
287
|
+
const body = await resp.arrayBuffer();
|
|
288
|
+
const got = await digest(body);
|
|
289
|
+
if (got !== f.sha256)
|
|
290
|
+
return `sha256 mismatch: expected ${f.sha256}, got ${got} — not kept`;
|
|
291
|
+
const headers = new Headers(resp.headers);
|
|
292
|
+
headers.set(LISTED_SHA256, f.sha256);
|
|
293
|
+
await t.cache.put(f.url, new Response(body, { status: resp.status, statusText: resp.statusText, headers }));
|
|
294
|
+
return body.byteLength;
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
return e instanceof Error ? e.message : String(e);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
145
300
|
/**
|
|
146
301
|
* THE SHA-256 OF A BODY AS LOWERCASE HEX, by the `crypto.subtle` it is handed (issue #168) — or `null` when there is none,
|
|
147
302
|
* which is a host outside a secure context: the answer `HeavyOptions.digest` reads as «cannot hash, so keep nothing».
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/**
|
|
3
|
+
* What the caller provides. Nothing here knows the neural engine, Web Audio or the browser. `Request` is what one utterance
|
|
4
|
+
* asks for: a text by default, or a text with the voice that reads it (ADR-0243 §2).
|
|
5
|
+
*/
|
|
6
|
+
export interface SpeechEngine<Audio, Fonte, Request = string> {
|
|
7
|
+
/** Request → audio. ASYNCHRONOUS on purpose: it is where neural synthesis spends its time. */
|
|
8
|
+
synthesize(request: Request): Promise<Audio>;
|
|
6
9
|
/** Starts playing and returns the source, so it can be stopped. `null` = it could not play right now. */
|
|
7
10
|
play(audio: Audio, onEnded: () => void): Fonte | null;
|
|
8
11
|
/** Silences the source. Called with what `play` returned, and never with `null`. */
|
|
9
12
|
stop(playing: Fonte): void;
|
|
10
13
|
}
|
|
11
|
-
export interface InterruptibleSpeech {
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
+
export interface InterruptibleSpeech<Request = string> {
|
|
15
|
+
/**
|
|
16
|
+
* Speaks `request`, SILENCING at once whatever is speaking. It does not queue: the latest request is the one that counts.
|
|
17
|
+
* `finished` is called ONCE, when this utterance is over for any reason — it ended, it was silenced or overtaken, or it could
|
|
18
|
+
* not be synthesised or played — so a caller speaking parts in order (ADR-0243 §1) knows when to go on, and never waits forever.
|
|
19
|
+
*/
|
|
20
|
+
speak(request: Request, finished?: () => void): void;
|
|
14
21
|
/** Silences and forgets. Used when a menu closes or narration is switched off. */
|
|
15
22
|
silence(): void;
|
|
16
23
|
/** Is anything playing? For tests and debugging only — the policy does not depend on it. */
|
|
17
24
|
speaking(): boolean;
|
|
18
25
|
}
|
|
19
|
-
export declare function createInterruptibleSpeech<Audio, Fonte>(engine: SpeechEngine<Audio, Fonte>): InterruptibleSpeech
|
|
26
|
+
export declare function createInterruptibleSpeech<Audio, Fonte, Request = string>(engine: SpeechEngine<Audio, Fonte, Request>): InterruptibleSpeech<Request>;
|