@the-inclusionist/engine 9.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 +120 -78
- package/app/css/style.css +761 -377
- package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
- 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 +36 -84
- package/dist-pkg/boot/create-game.d.ts +499 -219
- package/dist-pkg/boot/create-game.js +3944 -562
- package/dist-pkg/core/a11y-sr.d.ts +25 -3
- package/dist-pkg/core/a11y-sr.js +38 -19
- package/dist-pkg/core/accessible-label.d.ts +17 -0
- package/dist-pkg/core/accessible-label.js +37 -0
- package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
- package/dist-pkg/core/accommodation-subjects.js +32 -0
- package/dist-pkg/core/accommodations.d.ts +125 -0
- package/dist-pkg/core/accommodations.js +195 -0
- package/dist-pkg/core/actions.d.ts +108 -55
- package/dist-pkg/core/actions.js +122 -71
- package/dist-pkg/core/calm-mode.d.ts +31 -0
- package/dist-pkg/core/calm-mode.js +47 -0
- package/dist-pkg/core/camera-cycle.d.ts +15 -0
- package/dist-pkg/core/camera-cycle.js +7 -0
- package/dist-pkg/core/caption-duration.d.ts +15 -0
- package/dist-pkg/core/caption-duration.js +19 -0
- package/dist-pkg/core/cartridge-problems.d.ts +34 -0
- package/dist-pkg/core/cartridge-problems.js +53 -0
- package/dist-pkg/core/constants.d.ts +0 -54
- package/dist-pkg/core/constants.js +9 -76
- package/dist-pkg/core/contract.d.ts +142 -164
- package/dist-pkg/core/contract.js +222 -208
- package/dist-pkg/core/dom-query.d.ts +4 -4
- package/dist-pkg/core/dom-query.js +12 -20
- package/dist-pkg/core/entity.d.ts +62 -77
- package/dist-pkg/core/entity.js +18 -32
- package/dist-pkg/core/escape-html.d.ts +9 -10
- package/dist-pkg/core/escape-html.js +16 -20
- package/dist-pkg/core/flash-threshold.d.ts +17 -0
- package/dist-pkg/core/flash-threshold.js +113 -0
- package/dist-pkg/core/game-speed.d.ts +11 -0
- package/dist-pkg/core/game-speed.js +16 -0
- package/dist-pkg/core/genres.d.ts +20 -0
- package/dist-pkg/core/genres.js +44 -0
- package/dist-pkg/core/i18n.d.ts +71 -60
- package/dist-pkg/core/i18n.js +186 -200
- package/dist-pkg/core/loop.d.ts +17 -6
- package/dist-pkg/core/loop.js +26 -26
- package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
- package/dist-pkg/core/pause-icon-catalogue.js +54 -0
- package/dist-pkg/core/ring.d.ts +17 -0
- package/dist-pkg/core/ring.js +29 -0
- package/dist-pkg/core/rng.d.ts +7 -12
- package/dist-pkg/core/rng.js +23 -53
- package/dist-pkg/core/route.d.ts +26 -26
- package/dist-pkg/core/route.js +126 -121
- package/dist-pkg/core/scenes.d.ts +37 -40
- package/dist-pkg/core/scenes.js +41 -43
- package/dist-pkg/core/screens.d.ts +4 -4
- package/dist-pkg/core/screens.js +11 -16
- package/dist-pkg/core/session-clock.d.ts +23 -0
- package/dist-pkg/core/session-clock.js +37 -0
- package/dist-pkg/core/setting-defaults.d.ts +61 -0
- package/dist-pkg/core/setting-defaults.js +66 -0
- package/dist-pkg/core/speech-rate.d.ts +29 -0
- package/dist-pkg/core/speech-rate.js +47 -0
- package/dist-pkg/core/state.d.ts +118 -118
- package/dist-pkg/core/state.js +322 -297
- package/dist-pkg/core/visual-cycles.d.ts +30 -0
- package/dist-pkg/core/visual-cycles.js +52 -0
- package/dist-pkg/core/visual-state.d.ts +13 -0
- package/dist-pkg/core/visual-state.js +6 -0
- package/dist-pkg/educational/activities-registry.d.ts +1 -1
- package/dist-pkg/educational/activities-registry.js +9 -8
- package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
- package/dist-pkg/educational/adaptive-engine.js +17 -17
- package/dist-pkg/educational/segment-bar.d.ts +12 -12
- package/dist-pkg/educational/segment-bar.js +9 -9
- package/dist-pkg/i18n/en.js +324 -223
- package/dist-pkg/i18n/es.js +323 -223
- package/dist-pkg/i18n/pt.js +348 -226
- package/dist-pkg/input/default-bindings.d.ts +37 -38
- package/dist-pkg/input/default-bindings.js +127 -144
- package/dist-pkg/input/devices.d.ts +7 -7
- package/dist-pkg/input/devices.js +17 -16
- package/dist-pkg/input/edges.d.ts +23 -32
- package/dist-pkg/input/edges.js +23 -28
- package/dist-pkg/input/empathy-filter.d.ts +22 -0
- package/dist-pkg/input/empathy-filter.js +34 -0
- package/dist-pkg/input/face-map.d.ts +96 -0
- package/dist-pkg/input/face-map.js +255 -0
- package/dist-pkg/input/face-signals.d.ts +40 -0
- package/dist-pkg/input/face-signals.js +48 -0
- package/dist-pkg/input/gamepad.d.ts +195 -145
- package/dist-pkg/input/gamepad.js +383 -556
- package/dist-pkg/input/gaze-cycle.d.ts +64 -0
- package/dist-pkg/input/gaze-cycle.js +133 -0
- package/dist-pkg/input/gaze-relative.d.ts +68 -0
- package/dist-pkg/input/gaze-relative.js +142 -0
- package/dist-pkg/input/hand-map.d.ts +28 -0
- package/dist-pkg/input/hand-map.js +142 -0
- package/dist-pkg/input/input-cooldown.d.ts +17 -0
- package/dist-pkg/input/input-cooldown.js +39 -0
- 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 +15 -21
- package/dist-pkg/input/keyboard-runtime.js +23 -27
- package/dist-pkg/input/keyboard.d.ts +68 -63
- package/dist-pkg/input/keyboard.js +83 -105
- package/dist-pkg/input/keydown.d.ts +123 -137
- package/dist-pkg/input/keydown.js +284 -289
- package/dist-pkg/input/latch-edge.d.ts +33 -21
- package/dist-pkg/input/latch-edge.js +34 -35
- package/dist-pkg/input/latch-scope.d.ts +51 -50
- package/dist-pkg/input/latch-scope.js +61 -82
- package/dist-pkg/input/latch-store.d.ts +26 -30
- package/dist-pkg/input/latch-store.js +42 -50
- package/dist-pkg/input/latch-sync.d.ts +29 -29
- package/dist-pkg/input/latch-sync.js +25 -25
- package/dist-pkg/input/latch.d.ts +14 -17
- package/dist-pkg/input/latch.js +29 -37
- package/dist-pkg/input/pad-defaults.d.ts +13 -16
- package/dist-pkg/input/pad-defaults.js +21 -28
- package/dist-pkg/input/pad-reading.d.ts +76 -0
- package/dist-pkg/input/pad-reading.js +169 -0
- package/dist-pkg/input/pad-wizard.d.ts +99 -0
- package/dist-pkg/input/pad-wizard.js +256 -0
- package/dist-pkg/input/pointer-space.d.ts +19 -20
- package/dist-pkg/input/pointer-space.js +27 -32
- package/dist-pkg/input/pointer.d.ts +39 -40
- package/dist-pkg/input/pointer.js +42 -45
- package/dist-pkg/input/state.d.ts +101 -89
- package/dist-pkg/input/state.js +54 -134
- package/dist-pkg/input/switch-scan.d.ts +59 -0
- package/dist-pkg/input/switch-scan.js +67 -0
- package/dist-pkg/input/synthetic-source.d.ts +42 -0
- package/dist-pkg/input/synthetic-source.js +57 -0
- package/dist-pkg/input/touch-bindings.d.ts +127 -116
- package/dist-pkg/input/touch-bindings.js +158 -173
- package/dist-pkg/input/touch.d.ts +147 -72
- package/dist-pkg/input/touch.js +362 -126
- package/dist-pkg/input/transport-in-use.d.ts +107 -0
- package/dist-pkg/input/transport-in-use.js +130 -0
- package/dist-pkg/input/transports.d.ts +90 -117
- package/dist-pkg/input/transports.js +104 -106
- package/dist-pkg/input/virtual-controller.d.ts +82 -0
- package/dist-pkg/input/virtual-controller.js +69 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
- package/dist-pkg/input/vocabulary-migration.js +80 -79
- package/dist-pkg/input/voice-map.d.ts +59 -0
- package/dist-pkg/input/voice-map.js +123 -0
- package/dist-pkg/platform/audio-ambient.d.ts +13 -2
- package/dist-pkg/platform/audio-ambient.js +14 -14
- package/dist-pkg/platform/audio-earcons.d.ts +20 -19
- package/dist-pkg/platform/audio-earcons.js +51 -42
- package/dist-pkg/platform/audio-jingles.js +9 -10
- package/dist-pkg/platform/audio-mixer.d.ts +14 -2
- package/dist-pkg/platform/audio-mixer.js +31 -39
- package/dist-pkg/platform/audio-sonar.d.ts +49 -152
- package/dist-pkg/platform/audio-sonar.js +124 -302
- package/dist-pkg/platform/audio.d.ts +62 -19
- package/dist-pkg/platform/audio.js +193 -168
- 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/flash-sampler.d.ts +19 -0
- package/dist-pkg/platform/flash-sampler.js +79 -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 +77 -0
- package/dist-pkg/platform/heavy-catalogue.js +256 -0
- package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
- package/dist-pkg/platform/heavy-mirror.js +73 -0
- package/dist-pkg/platform/heavy.d.ts +136 -0
- package/dist-pkg/platform/heavy.js +324 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
- package/dist-pkg/platform/interruptible-speech.js +77 -54
- package/dist-pkg/platform/kokoro-port.d.ts +27 -0
- package/dist-pkg/platform/kokoro-port.js +50 -0
- package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
- package/dist-pkg/platform/kokoro-runtime.js +52 -0
- package/dist-pkg/platform/kokoro.d.ts +70 -0
- package/dist-pkg/platform/kokoro.js +133 -0
- package/dist-pkg/platform/listener-scope.d.ts +12 -0
- package/dist-pkg/platform/listener-scope.js +90 -0
- package/dist-pkg/platform/locale-host.d.ts +14 -0
- package/dist-pkg/platform/locale-host.js +45 -0
- package/dist-pkg/platform/microphone.d.ts +51 -0
- package/dist-pkg/platform/microphone.js +118 -0
- package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
- package/dist-pkg/platform/onnx-runtime.js +42 -0
- package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
- package/dist-pkg/platform/reading-in-worker.js +125 -0
- package/dist-pkg/platform/reading-model.d.ts +94 -0
- package/dist-pkg/platform/reading-model.js +272 -0
- package/dist-pkg/platform/reading-runtime.d.ts +24 -0
- package/dist-pkg/platform/reading-runtime.js +164 -0
- package/dist-pkg/platform/reading-worker.d.ts +41 -0
- package/dist-pkg/platform/reading-worker.js +58 -0
- package/dist-pkg/platform/reading.d.ts +80 -0
- package/dist-pkg/platform/reading.js +136 -0
- package/dist-pkg/platform/speech-recognition.d.ts +60 -0
- package/dist-pkg/platform/speech-recognition.js +104 -0
- package/dist-pkg/platform/speech.d.ts +23 -1
- package/dist-pkg/platform/speech.js +29 -18
- package/dist-pkg/platform/storage-keys.d.ts +96 -0
- package/dist-pkg/platform/storage-keys.js +106 -0
- package/dist-pkg/platform/storage.d.ts +46 -111
- package/dist-pkg/platform/storage.js +104 -169
- package/dist-pkg/platform/tts.d.ts +85 -39
- package/dist-pkg/platform/tts.js +447 -127
- package/dist-pkg/platform/vision-loop.d.ts +23 -0
- package/dist-pkg/platform/vision-loop.js +56 -0
- package/dist-pkg/platform/vision.d.ts +132 -0
- package/dist-pkg/platform/vision.js +117 -0
- package/dist-pkg/platform/voice-listener.d.ts +40 -0
- package/dist-pkg/platform/voice-listener.js +88 -0
- package/dist-pkg/platform/voice-plan.d.ts +15 -98
- package/dist-pkg/platform/voice-plan.js +56 -143
- package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
- package/dist-pkg/platform/vosk-runtime.js +151 -0
- package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
- package/dist-pkg/platform/vosk-vocabulary.js +178 -0
- package/dist-pkg/render/canvas.d.ts +13 -7
- package/dist-pkg/render/canvas.js +13 -13
- package/dist-pkg/render/crt.d.ts +48 -12
- package/dist-pkg/render/crt.js +78 -80
- package/dist-pkg/render/cvd-matrices.d.ts +22 -18
- package/dist-pkg/render/cvd-matrices.js +37 -38
- package/dist-pkg/render/hc-role-data.d.ts +7 -7
- package/dist-pkg/render/hc-role-data.js +14 -14
- package/dist-pkg/render/high-contrast.d.ts +67 -56
- package/dist-pkg/render/high-contrast.js +226 -217
- package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
- package/dist-pkg/render/low-vision-drawing.js +46 -0
- package/dist-pkg/render/lq-filter.d.ts +32 -20
- package/dist-pkg/render/lq-filter.js +59 -65
- package/dist-pkg/render/port.d.ts +86 -88
- package/dist-pkg/render/port.js +17 -23
- package/dist-pkg/render/screen-pipeline.d.ts +42 -42
- package/dist-pkg/render/screen-pipeline.js +80 -87
- package/dist-pkg/render/sprite-fx.d.ts +2 -1
- package/dist-pkg/render/sprite-fx.js +16 -14
- package/dist-pkg/render/viewports.d.ts +20 -15
- package/dist-pkg/render/viewports.js +83 -114
- package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
- package/dist-pkg/render/viz-axes-labels.js +88 -0
- package/dist-pkg/render/viz-axes.d.ts +89 -86
- package/dist-pkg/render/viz-axes.js +128 -116
- package/dist-pkg/render/viz-modes.d.ts +28 -29
- package/dist-pkg/render/viz-modes.js +40 -45
- package/dist-pkg/render/viz-refusal.d.ts +32 -0
- package/dist-pkg/render/viz-refusal.js +57 -0
- package/dist-pkg/render/viz-setters.d.ts +104 -66
- package/dist-pkg/render/viz-setters.js +182 -191
- package/dist-pkg/ui/aac-sets.d.ts +45 -0
- package/dist-pkg/ui/aac-sets.js +41 -0
- package/dist-pkg/ui/audio-choices.d.ts +68 -0
- package/dist-pkg/ui/audio-choices.js +98 -0
- package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
- package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
- package/dist-pkg/ui/camera-control.d.ts +53 -0
- package/dist-pkg/ui/camera-control.js +48 -0
- package/dist-pkg/ui/changed-mark.d.ts +9 -8
- package/dist-pkg/ui/changed-mark.js +22 -53
- package/dist-pkg/ui/control-choices.d.ts +37 -0
- package/dist-pkg/ui/control-choices.js +84 -0
- package/dist-pkg/ui/debug-panel.d.ts +59 -43
- package/dist-pkg/ui/debug-panel.js +68 -69
- package/dist-pkg/ui/declared-words.d.ts +21 -0
- package/dist-pkg/ui/declared-words.js +66 -0
- package/dist-pkg/ui/dom.d.ts +10 -14
- package/dist-pkg/ui/dom.js +10 -47
- package/dist-pkg/ui/drawing-problems.d.ts +25 -0
- package/dist-pkg/ui/drawing-problems.js +94 -0
- package/dist-pkg/ui/eye-control.d.ts +36 -0
- package/dist-pkg/ui/eye-control.js +178 -0
- package/dist-pkg/ui/face-control.d.ts +25 -0
- package/dist-pkg/ui/face-control.js +183 -0
- package/dist-pkg/ui/focus-trap.d.ts +39 -49
- package/dist-pkg/ui/focus-trap.js +56 -65
- package/dist-pkg/ui/fonts.d.ts +157 -68
- package/dist-pkg/ui/fonts.js +305 -115
- 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 +47 -0
- package/dist-pkg/ui/game-options.js +158 -0
- package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
- package/dist-pkg/ui/gaze-overlay.js +165 -0
- package/dist-pkg/ui/hand-control.d.ts +25 -0
- package/dist-pkg/ui/hand-control.js +143 -0
- package/dist-pkg/ui/help-panel.d.ts +87 -0
- package/dist-pkg/ui/help-panel.js +242 -0
- package/dist-pkg/ui/hud-bands.d.ts +62 -0
- package/dist-pkg/ui/hud-bands.js +146 -0
- 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 +73 -73
- package/dist-pkg/ui/hud.js +94 -98
- package/dist-pkg/ui/item-announcement.d.ts +13 -12
- package/dist-pkg/ui/item-announcement.js +25 -26
- package/dist-pkg/ui/layout.d.ts +103 -28
- package/dist-pkg/ui/layout.js +117 -99
- 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/locale-flags.d.ts +16 -0
- package/dist-pkg/ui/locale-flags.js +30 -0
- package/dist-pkg/ui/loop-crash.d.ts +17 -17
- package/dist-pkg/ui/loop-crash.js +33 -62
- package/dist-pkg/ui/menu-intent.d.ts +61 -0
- package/dist-pkg/ui/menu-intent.js +88 -0
- package/dist-pkg/ui/menu-items.d.ts +20 -0
- package/dist-pkg/ui/menu-items.js +51 -0
- package/dist-pkg/ui/menu-nav.d.ts +98 -92
- package/dist-pkg/ui/menu-nav.js +398 -286
- package/dist-pkg/ui/mobility-choices.d.ts +26 -0
- package/dist-pkg/ui/mobility-choices.js +41 -0
- package/dist-pkg/ui/motion-choices.d.ts +31 -0
- package/dist-pkg/ui/motion-choices.js +68 -0
- package/dist-pkg/ui/motion-scene.d.ts +24 -19
- package/dist-pkg/ui/motion-scene.js +29 -61
- package/dist-pkg/ui/mount-panel.d.ts +81 -0
- package/dist-pkg/ui/mount-panel.js +61 -0
- package/dist-pkg/ui/panel-shell.d.ts +65 -31
- package/dist-pkg/ui/panel-shell.js +92 -66
- package/dist-pkg/ui/panel-widgets.d.ts +150 -0
- package/dist-pkg/ui/panel-widgets.js +294 -0
- package/dist-pkg/ui/pause-buttons.d.ts +35 -0
- package/dist-pkg/ui/pause-buttons.js +66 -0
- package/dist-pkg/ui/pause-icons.d.ts +261 -347
- package/dist-pkg/ui/pause-icons.js +671 -601
- package/dist-pkg/ui/pause-markup.d.ts +86 -0
- package/dist-pkg/ui/pause-markup.js +125 -0
- package/dist-pkg/ui/reach-notice.d.ts +22 -23
- package/dist-pkg/ui/reach-notice.js +55 -58
- package/dist-pkg/ui/scan-overlay.d.ts +23 -0
- package/dist-pkg/ui/scan-overlay.js +50 -0
- 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 +70 -0
- package/dist-pkg/ui/settings-aac.js +208 -0
- package/dist-pkg/ui/settings-audio.d.ts +97 -114
- package/dist-pkg/ui/settings-audio.js +493 -425
- package/dist-pkg/ui/settings-controls.d.ts +53 -96
- package/dist-pkg/ui/settings-controls.js +143 -215
- package/dist-pkg/ui/settings-empathy.d.ts +39 -30
- package/dist-pkg/ui/settings-empathy.js +53 -60
- package/dist-pkg/ui/settings-mobility.d.ts +192 -0
- package/dist-pkg/ui/settings-mobility.js +332 -0
- package/dist-pkg/ui/settings-motion.d.ts +91 -70
- package/dist-pkg/ui/settings-motion.js +287 -198
- package/dist-pkg/ui/settings-panel.d.ts +58 -45
- package/dist-pkg/ui/settings-panel.js +189 -94
- package/dist-pkg/ui/settings-typo.d.ts +29 -78
- package/dist-pkg/ui/settings-typo.js +158 -129
- package/dist-pkg/ui/settings-visual.d.ts +29 -87
- package/dist-pkg/ui/settings-visual.js +240 -193
- package/dist-pkg/ui/shell.d.ts +112 -135
- package/dist-pkg/ui/shell.js +148 -217
- package/dist-pkg/ui/simulation-list.d.ts +27 -0
- package/dist-pkg/ui/simulation-list.js +76 -0
- package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
- package/dist-pkg/ui/simulation-over-the-world.js +131 -0
- package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
- package/dist-pkg/ui/simulation-refusal.js +8 -56
- package/dist-pkg/ui/switchable-control.d.ts +11 -0
- package/dist-pkg/ui/switchable-control.js +19 -0
- package/dist-pkg/ui/title.d.ts +3 -12
- package/dist-pkg/ui/title.js +49 -18
- package/dist-pkg/ui/top-band.d.ts +26 -0
- package/dist-pkg/ui/top-band.js +96 -0
- package/dist-pkg/ui/typo-choices.d.ts +71 -0
- package/dist-pkg/ui/typo-choices.js +85 -0
- package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
- package/dist-pkg/ui/visual-axes-panel.js +12 -94
- package/dist-pkg/ui/visual-choices.d.ts +77 -0
- package/dist-pkg/ui/visual-choices.js +107 -0
- package/dist-pkg/ui/vlibras.d.ts +77 -10
- package/dist-pkg/ui/vlibras.js +130 -81
- package/dist-pkg/ui/voice-control.d.ts +68 -0
- package/dist-pkg/ui/voice-control.js +276 -0
- package/dist-pkg/ui/voice-settings.d.ts +95 -0
- package/dist-pkg/ui/voice-settings.js +352 -0
- package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
- package/dist-pkg/ui/where-the-child-is.js +70 -0
- package/docs/CREDITS.md +300 -44
- package/docs/LICENSES.md +189 -145
- package/package.json +51 -27
- 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 +388 -0
- 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/Apache-2.0.txt +176 -0
- package/scripts/licences/GPL-3.0.txt +674 -0
- package/scripts/licences/MIT.txt +17 -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 +301 -0
- package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
- package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-700.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/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.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/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.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/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/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/ufmag-400.woff2 +0 -0
- package/dist-pkg/core/anel.d.ts +0 -17
- package/dist-pkg/core/anel.js +0 -31
- package/dist-pkg/core/collision.d.ts +0 -21
- package/dist-pkg/core/collision.js +0 -62
- package/dist-pkg/core/layers.d.ts +0 -63
- package/dist-pkg/core/layers.js +0 -95
- package/dist-pkg/core/letter-grid.d.ts +0 -55
- package/dist-pkg/core/letter-grid.js +0 -116
- package/dist-pkg/core/password.d.ts +0 -34
- package/dist-pkg/core/password.js +0 -205
- package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
- package/dist-pkg/core/rotulo-acessivel.js +0 -41
- package/dist-pkg/core/run-state.d.ts +0 -115
- package/dist-pkg/core/run-state.js +0 -40
- package/dist-pkg/core/tiles.d.ts +0 -12
- package/dist-pkg/core/tiles.js +0 -61
- package/dist-pkg/core/world.d.ts +0 -4
- package/dist-pkg/core/world.js +0 -58
- package/dist-pkg/input/origem-sintetica.d.ts +0 -44
- package/dist-pkg/input/origem-sintetica.js +0 -60
- package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
- package/dist-pkg/input/transporte-em-uso.js +0 -130
- package/dist-pkg/platform/audio-nav.d.ts +0 -51
- package/dist-pkg/platform/audio-nav.js +0 -99
- package/dist-pkg/platform/guide-intensity.d.ts +0 -40
- package/dist-pkg/platform/guide-intensity.js +0 -73
- package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
- package/dist-pkg/platform/pesados-catalogo.js +0 -177
- package/dist-pkg/platform/pesados.d.ts +0 -31
- package/dist-pkg/platform/pesados.js +0 -75
- package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
- package/dist-pkg/platform/vozes-prontas.js +0 -61
- package/dist-pkg/render/camera.d.ts +0 -58
- package/dist-pkg/render/camera.js +0 -105
- package/dist-pkg/render/cenario-data.d.ts +0 -127
- package/dist-pkg/render/cenario-data.js +0 -145
- package/dist-pkg/render/city-tex.d.ts +0 -63
- package/dist-pkg/render/city-tex.js +0 -228
- package/dist-pkg/render/city-tiles.d.ts +0 -11
- package/dist-pkg/render/city-tiles.js +0 -140
- package/dist-pkg/render/draw.d.ts +0 -149
- package/dist-pkg/render/draw.js +0 -231
- package/dist-pkg/render/fx.d.ts +0 -63
- package/dist-pkg/render/fx.js +0 -123
- package/dist-pkg/render/minimap.d.ts +0 -11
- package/dist-pkg/render/minimap.js +0 -94
- package/dist-pkg/render/parallax.d.ts +0 -85
- package/dist-pkg/render/parallax.js +0 -158
- package/dist-pkg/render/player-anim.d.ts +0 -71
- package/dist-pkg/render/player-anim.js +0 -152
- package/dist-pkg/render/recycling-tex.d.ts +0 -48
- package/dist-pkg/render/recycling-tex.js +0 -164
- package/dist-pkg/render/scene-city.d.ts +0 -77
- package/dist-pkg/render/scene-city.js +0 -181
- package/dist-pkg/render/scene-parallax.d.ts +0 -72
- package/dist-pkg/render/scene-parallax.js +0 -426
- package/dist-pkg/render/scene-sky.d.ts +0 -126
- package/dist-pkg/render/scene-sky.js +0 -295
- package/dist-pkg/render/set-cenario.d.ts +0 -54
- package/dist-pkg/render/set-cenario.js +0 -103
- package/dist-pkg/render/textures.d.ts +0 -75
- package/dist-pkg/render/textures.js +0 -240
- package/dist-pkg/render/title-scene.d.ts +0 -46
- package/dist-pkg/render/title-scene.js +0 -75
- package/dist-pkg/render/weather.d.ts +0 -96
- package/dist-pkg/render/weather.js +0 -171
- package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
- package/dist-pkg/render/wheelchair-sprites.js +0 -69
- package/dist-pkg/render/world-tex.d.ts +0 -18
- package/dist-pkg/render/world-tex.js +0 -87
- package/dist-pkg/ui/activities-menu.d.ts +0 -258
- package/dist-pkg/ui/activities-menu.js +0 -648
- package/dist-pkg/ui/caa-sets.d.ts +0 -39
- package/dist-pkg/ui/caa-sets.js +0 -65
- package/dist-pkg/ui/latch-refusal.d.ts +0 -32
- package/dist-pkg/ui/latch-refusal.js +0 -60
- package/dist-pkg/ui/map-hub.d.ts +0 -56
- package/dist-pkg/ui/map-hub.js +0 -138
- package/dist-pkg/ui/settings-caa.d.ts +0 -45
- package/dist-pkg/ui/settings-caa.js +0 -137
- package/dist-pkg/ui/settings-motor.d.ts +0 -175
- package/dist-pkg/ui/settings-motor.js +0 -342
- package/dist-pkg/ui/webcam.d.ts +0 -7
- package/dist-pkg/ui/webcam.js +0 -93
|
@@ -1,156 +1,69 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// platform/voice-plan.ts —
|
|
2
|
+
// platform/voice-plan.ts — the shape of a voice a child may pick, and which of them speak a language (ADR-0185).
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// a resposta honesta a «o que é que esta criança está a ouvir AGORA». Sem rede, sem cache, sem tempo. Quem
|
|
7
|
-
// busca de facto é a outra metade; quem decide O QUE buscar e o que DIZER é esta.
|
|
8
|
-
//
|
|
9
|
-
// ⚠️ POR QUE O CATÁLOGO VIVE AQUI E NÃO NO `TTS_SOURCES`. A tabela do `platform/tts` é indexada por idioma e
|
|
10
|
-
// tem UMA voz por idioma; este catálogo tem QUATRO vozes para TRÊS idiomas, porque o en-US tem duas. Ligá-las
|
|
11
|
-
// hoje mudaria comportamento: o `loadTTS` passaria a pedir `en_US-ryan-medium` à PORTA DO CARTUCHO
|
|
12
|
-
// (ADR-0094), que pode não ter essa voz. A tabela liga-se a isto quando o buscador existir, e nem um dia
|
|
13
|
-
// antes — uma lista ligada a um fornecedor que não a conhece é pior do que uma lista à espera.
|
|
14
|
-
//
|
|
15
|
-
// ⚠️ E QUAL DAS DUAS VOZES EN-US A CRIANÇA OUVE POR PADRÃO NÃO SE DECIDE AQUI. O ADR-0110 deixa-o
|
|
16
|
-
// explicitamente em aberto, e a ORDEM DESTE ARRAY NÃO É UMA PREFERÊNCIA — é a ordem em que o Dev as nomeou.
|
|
17
|
-
// Ler ordem como escolha seria decidir por omissão, que é o defeito que este projeto persegue.
|
|
4
|
+
// 📌 The engine owns no neural voice catalogue of its own (ADR-0207) and Kokoro's voices come through the
|
|
5
|
+
// game's port (`platform/kokoro`, ADR-0198). What stays here is the rule every list obeys — the browser's and Kokoro's.
|
|
18
6
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* modelos `.param`/`.bin` e não `.onnx` — e este projeto corre sherpa-onnx. Dois dos links que chegaram em
|
|
23
|
-
* 2026-09-08 apontavam para os espelhos `ncnn`, e é por isso que a proibição tem gate e não só um comentário.
|
|
24
|
-
* ⚠️ E NENHUMA `int8`, pela razão MEDIDA do mesmo §5: no backend WASM o int8 corre ~3× MAIS LENTO que o fp32
|
|
25
|
-
* (RTF 5,6 contra 2,5, do log do próprio Dev) e produz saída incorrecta ou muda. Quantizar não encurta a
|
|
26
|
-
* espera aqui — alonga-a.
|
|
7
|
+
* The voices a child may pick for a language (ADR-0185): matched on the LANGUAGE of the tag, not the region — a Mexican
|
|
8
|
+
* voice reads Spanish from Spain, and a Brazilian game tagged `pt` is still Portuguese. A voice reading another language
|
|
9
|
+
* is not offered: Portuguese text through English phonemes is noise.
|
|
27
10
|
*/
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
Object.freeze({ locale: 'en-US', engine: 'piper', voice: 'en_US-ryan-medium' }),
|
|
31
|
-
Object.freeze({ locale: 'en-US', engine: 'piper', voice: 'en_US-amy-medium' }),
|
|
32
|
-
Object.freeze({ locale: 'es-MX', engine: 'piper', voice: 'es_MX-claude-high' }),
|
|
33
|
-
]);
|
|
34
|
-
/**
|
|
35
|
-
* DE ONDE VÊM OS MODELOS (ADR-0114), num sítio só.
|
|
36
|
-
*
|
|
37
|
-
* 📏 MEDIDO EM 2026-09-08, e não escolhido: o `piper.ttstool.com` — que o Dev nomeou ao perguntar — serve o
|
|
38
|
-
* próprio runtime da própria origem e busca os modelos aqui. As quatro vozes deste catálogo respondem 200
|
|
39
|
-
* neste endereço, com `Access-Control-Allow-Origin: *`, logo um PWA pode buscá-las de outra origem.
|
|
40
|
-
*
|
|
41
|
-
* ⚠️ UM SÍTIO SÓ É A METADE QUE O REGISTO PEDE. Um endereço repetido no ponto de uso é como o CDN do
|
|
42
|
-
* WebGazer chegou ao `ui/webcam` — escrito à mão, sem política, e sem ninguém a poder mudá-lo de uma vez.
|
|
43
|
-
*
|
|
44
|
-
* ========================= 🔴 MUDOU DE ESPELHO EM 2026-09-09, E A REGRA É «BUSCAR DE ONDE O LEITOR LÊ» ====
|
|
45
|
-
* Era `rhasspy/piper-voices`, medido a 08/09 como o espelho que o `piper.ttstool.com` usa. Depois de o
|
|
46
|
-
* `platform/pesados` passar a descer os modelos no primeiro carregamento, mediu-se o outro lado — o
|
|
47
|
-
* `@mintplex-labs/piper-tts-web@1.0.4` INSTALADO, lido do bundle e não do README — e ele busca em
|
|
48
|
-
* `diffusionstudio/piper-voices`, com uma guarda que recusa qualquer URL fora de `huggingface.co`.
|
|
49
|
-
*
|
|
50
|
-
* 🎯 ENDEREÇOS DIFERENTES SIGNIFICAM CACHE DIFERENTE: a Cache Storage é indexada pela URL do pedido, logo os
|
|
51
|
-
* 241 MB que desciam no primeiro dia NÃO ERAM LIDOS POR NINGUÉM, e a biblioteca descarregava tudo outra vez
|
|
52
|
-
* no dia em que a voz fosse pedida. Até 482 MB num link de escola para uma voz.
|
|
53
|
-
*
|
|
54
|
-
* 📏 E OS DOIS ESPELHOS SERVEM OS MESMOS BYTES — 63 201 294 para o `pt_BR-faber-medium`, caminhos idênticos,
|
|
55
|
-
* `Access-Control-Allow-Origin: *` nos dois. Medido nos dois no mesmo minuto, o que torna esta troca uma
|
|
56
|
-
* correcção de facto e não uma preferência entre fornecedores.
|
|
57
|
-
*
|
|
58
|
-
* ⚠️ A CLÁUSULA DO ADR-0114 NÃO SE MEXE: o host continua nomeado num ponto só. O que mudou foi QUAL, e a
|
|
59
|
-
* regra que decide isso passa a estar escrita para não voltar a divergir — **busca-se de onde o LEITOR lê**.
|
|
60
|
-
* No dia em que a engine for dona do runtime (ADR-0124 cláusula 2), o leitor passa a ser ela e é ela que
|
|
61
|
-
* escolhe; até lá, o único leitor é a porta do cartucho.
|
|
62
|
-
*/
|
|
63
|
-
export const HOST_DOS_MODELOS = 'https://huggingface.co/diffusionstudio/piper-voices/resolve/main/';
|
|
64
|
-
/**
|
|
65
|
-
* O CAMINHO DO MODELO, DERIVADO DO IDENTIFICADOR — e não uma segunda tabela.
|
|
66
|
-
*
|
|
67
|
-
* `pt_BR-faber-medium` diz tudo o que o caminho precisa: `pt/pt_BR/faber/medium/pt_BR-faber-medium.onnx`.
|
|
68
|
-
* 🎯 DERIVAR EM VEZ DE TABELAR é a decisão inteira desta função: uma tabela de caminhos ao lado da tabela
|
|
69
|
-
* de vozes seria o mesmo facto escrito duas vezes, e este repositório já pagou isso três vezes — o
|
|
70
|
-
* `DomQuery`, os rótulos de movimento reduzido, as chaves de armazenamento. Duas listas divergem, e
|
|
71
|
-
* divergem uma entrada de cada vez.
|
|
72
|
-
*
|
|
73
|
-
* ⚠️ Devolve `null` para um identificador que não tenha a forma esperada, em vez de montar um caminho
|
|
74
|
-
* torto: uma URL inventada dá 404 na escola, e um `null` dá para reportar antes de sair de casa.
|
|
75
|
-
*/
|
|
76
|
-
export function caminhoDoModelo(v) {
|
|
77
|
-
const partes = v.voice.split('-');
|
|
78
|
-
if (partes.length !== 3)
|
|
79
|
-
return null;
|
|
80
|
-
const [locale, nome, qualidade] = partes;
|
|
81
|
-
const idioma = locale.split('_')[0];
|
|
82
|
-
if (!idioma || !nome || !qualidade || idioma === locale)
|
|
83
|
-
return null;
|
|
84
|
-
return `${idioma}/${locale}/${nome}/${qualidade}/${v.voice}.onnx`;
|
|
85
|
-
}
|
|
86
|
-
/** O endereço completo do modelo. `null` quando o identificador não se deixa ler. */
|
|
87
|
-
export function urlDoModelo(v) {
|
|
88
|
-
const caminho = caminhoDoModelo(v);
|
|
89
|
-
return caminho === null ? null : HOST_DOS_MODELOS + caminho;
|
|
11
|
+
export function voicesForLocale(tag, catalogue) {
|
|
12
|
+
return catalogue.filter((v) => speaksLanguageOf(v.locale, tag));
|
|
90
13
|
}
|
|
14
|
+
/** The primary language of a BCP-47 tag, lower case: `pt` of `pt-BR`. A browser's `en_US` is normalised by whoever reads it. */
|
|
15
|
+
const primaryLanguage = (tag) => (tag.split('-')[0] ?? '').toLowerCase();
|
|
91
16
|
/**
|
|
92
|
-
* A
|
|
93
|
-
*
|
|
94
|
-
* 📌 `.onnx.json` e não um segundo caminho: é o mesmo ficheiro com outro sufixo, medido a responder 200 no
|
|
95
|
-
* mesmo sítio. Escrevê-lo como derivação mantém a regra de que o identificador é a única fonte.
|
|
17
|
+
* A language's name, written in another language: `languageName('en-GB', 'pt-BR')` is «inglês» — the primary language, because a
|
|
18
|
+
* voice of the same language would have read the part (ADR-0243 §3). Where the platform cannot name it, the tag's language code.
|
|
96
19
|
*/
|
|
97
|
-
export function
|
|
98
|
-
const
|
|
99
|
-
|
|
20
|
+
export function languageName(tag, inLanguage) {
|
|
21
|
+
const code = primaryLanguage(tag);
|
|
22
|
+
try {
|
|
23
|
+
return new Intl.DisplayNames([inLanguage], { type: 'language' }).of(code) ?? code;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return code;
|
|
27
|
+
}
|
|
100
28
|
}
|
|
101
|
-
|
|
29
|
+
/** Does a voice tagged `locale` speak the language of `tag`? By the primary language, as `voicesForLocale` matches. */
|
|
30
|
+
export function speaksLanguageOf(locale, tag) {
|
|
31
|
+
return primaryLanguage(locale) === primaryLanguage(tag);
|
|
32
|
+
}
|
|
33
|
+
/** The engine of a browser (Web Speech) voice in a list; every other engine is neural (ADR-0200). */
|
|
34
|
+
const BROWSER_ENGINE = 'webspeech';
|
|
35
|
+
const browser = (v) => v.engine === BROWSER_ENGINE;
|
|
36
|
+
const exactTag = (v, tag) => v.locale.toLowerCase() === tag.toLowerCase();
|
|
102
37
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* 📌 `falhou` VOLTA À FILA. Uma escola perde a rede a meio da manhã e recupera-a; uma voz marcada como
|
|
111
|
-
* falhada para sempre seria uma criança sem voz até alguém recarregar a página. Quem chama decide QUANDO
|
|
112
|
-
* tentar de novo — este módulo só diz que ainda há o que buscar.
|
|
38
|
+
* THE VOICE ORDER (ADR-0243 §2, the two errata of 2026-09-26), after the child's chosen voice. A BROWSER voice before a NEURAL one
|
|
39
|
+
* (the Dev: «Se a do navegador (mais leve) pode ser usada, a do navegador, senão ganha a voz neural (backup)»), but the exact tag
|
|
40
|
+
* before the region: asked whether a pt-PT browser voice reads a pt-BR part or the neural pt-BR voice does, the Dev: «Rede neural
|
|
41
|
+
* pt-BR.» So a voice of the same language and another region reads only where no voice of the exact tag exists, browser first.
|
|
42
|
+
* Every step is tried over the whole list, in order; within a step the list's own order decides. The interface's own voice
|
|
43
|
+
* follows the same order (`platform/tts`'s `voiceInUse`).
|
|
113
44
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
...porBuscar.filter((v) => v.locale === localeCorrente),
|
|
121
|
-
...porBuscar.filter((v) => v.locale !== localeCorrente),
|
|
122
|
-
];
|
|
123
|
-
}
|
|
45
|
+
const VOICE_ORDER = [
|
|
46
|
+
(v, tag) => browser(v) && exactTag(v, tag),
|
|
47
|
+
(v, tag) => !browser(v) && exactTag(v, tag),
|
|
48
|
+
(v) => browser(v),
|
|
49
|
+
(v) => !browser(v),
|
|
50
|
+
];
|
|
124
51
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* família do `reflectTTS`». Uma engine que dissesse «voz neural» enquanto o modelo ainda desce faria um adulto
|
|
129
|
-
* concluir que a qualidade que ouve É a qualidade final — e desistir de esperar por uma coisa que já vinha a
|
|
130
|
-
* caminho. Dizer `recuo` e dizer PORQUÊ custa uma linha e é a diferença entre informar e enganar.
|
|
131
|
-
*
|
|
132
|
-
* 📌 A PRIMEIRA VOZ PRONTA DO IDIOMA, e nada mais: onde há duas prontas, esta função NÃO escolhe entre elas —
|
|
133
|
-
* devolve a primeira do catálogo porque tem de devolver alguma, e qual delas a criança prefere é a pergunta
|
|
134
|
-
* que o ADR-0110 deixou em aberto. Ver o cabeçalho.
|
|
52
|
+
* THE VOICE OF A LANGUAGE (ADR-0243 §2): the child's chosen voice when it speaks that language; else the first voice `VOICE_ORDER`
|
|
53
|
+
* reaches — the exact tag before the region, a browser voice before a neural one. `chosen` comes in order of precedence.
|
|
54
|
+
* 🔴 No voice of another language is ever returned: `null` means the list has none for it, and the part is not spoken (§3).
|
|
135
55
|
*/
|
|
136
|
-
export function
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// porque ninguém a mandou —, e chamar-lhe «a buscar» esconderia um buscador que nunca arrancou atrás de
|
|
150
|
-
// uma frase tranquilizadora. É o mesmo defeito de forma que o `neuralDisponivel` já custou à #91.
|
|
151
|
-
if (doIdioma.some((v) => estadoDe(estados, v) === 'a-buscar'))
|
|
152
|
-
return { tipo: 'recuo', porque: 'a-buscar' };
|
|
153
|
-
if (doIdioma.some((v) => estadoDe(estados, v) === 'falhou'))
|
|
154
|
-
return { tipo: 'recuo', porque: 'falhou' };
|
|
155
|
-
return { tipo: 'recuo', porque: 'ausente' };
|
|
56
|
+
export function voiceOfLanguage(tag, voices, chosen = []) {
|
|
57
|
+
const own = voicesForLocale(tag, voices);
|
|
58
|
+
for (const id of chosen) {
|
|
59
|
+
const picked = id ? own.find((v) => v.voice === id) : undefined;
|
|
60
|
+
if (picked)
|
|
61
|
+
return picked;
|
|
62
|
+
}
|
|
63
|
+
for (const step of VOICE_ORDER) {
|
|
64
|
+
const found = own.find((v) => step(v, tag));
|
|
65
|
+
if (found)
|
|
66
|
+
return found;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
156
69
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/** The three files of the runtime. The model is chosen by language, below. */
|
|
3
|
+
export declare const VOICE_RUNTIME_FILES: readonly ["commands:runtime", "commands:runtime:worker", "commands:runtime:wasm"];
|
|
4
|
+
/** The catalogue id of the model that hears THIS language, or `null` where the project has none. */
|
|
5
|
+
export declare function commandModelId(language: string): string | null;
|
|
6
|
+
/** What the recogniser answers with. `partial` grows during one utterance; `text` is the sentence once it ends. */
|
|
7
|
+
export interface VoskHeard {
|
|
8
|
+
readonly result: {
|
|
9
|
+
readonly partial?: string;
|
|
10
|
+
readonly text?: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface VoskRecognizer {
|
|
14
|
+
on(event: 'partialresult' | 'result', cb: (heard: VoskHeard) => void): void;
|
|
15
|
+
/** One block of sound, as the audio graph delivers it. */
|
|
16
|
+
acceptWaveform(buffer: AudioBuffer): void;
|
|
17
|
+
remove(): void;
|
|
18
|
+
}
|
|
19
|
+
export interface VoskModel {
|
|
20
|
+
KaldiRecognizer: new (sampleRate: number, grammar: string) => VoskRecognizer;
|
|
21
|
+
terminate?(): void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* What the bundle exports. `resolve` is how it asks US for the two files it needs beside the model — the worker it spawns and
|
|
25
|
+
* the wasm that worker loads — so nothing is ever guessed from the bundle's own address.
|
|
26
|
+
*/
|
|
27
|
+
export interface VoskApi {
|
|
28
|
+
createModel(url: string, resolve: (logicalPath: string) => string, logLevel?: number): Promise<VoskModel>;
|
|
29
|
+
}
|
|
30
|
+
export interface VoskDeps {
|
|
31
|
+
/** The page's address, to make the delivery paths absolute. */
|
|
32
|
+
readonly base: string;
|
|
33
|
+
/** The child's language (`core/i18n.bcp47`): it chooses the model. */
|
|
34
|
+
readonly language: string;
|
|
35
|
+
/**
|
|
36
|
+
* Whether a catalogue file (by its upstream address) is in the checked cache — `platform/heavy`'s `checkedCacheHas`, over the
|
|
37
|
+
* host's `caches`. REQUIRED (ADR-0232 D4): the root lends the cache; this module reaches none.
|
|
38
|
+
*/
|
|
39
|
+
readonly hasFile: (upstreamUrl: string) => Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Imports the bundle and answers with what it exports — `createBundleLoader` below, built ONCE by the root, so the bundle is
|
|
42
|
+
* put in the page once per address. REQUIRED, and injected so a gate never imports 3 MiB of wasm loader.
|
|
43
|
+
*/
|
|
44
|
+
readonly loadBundle: (absoluteUrl: string) => Promise<VoskApi>;
|
|
45
|
+
/**
|
|
46
|
+
* The host's `fetch`, lent by the root, to read the MODEL'S VOCABULARY from the archive the recogniser opens
|
|
47
|
+
* (`platform/vosk-vocabulary`, ADR-0194 §4): the runtime keeps it inside its worker and tells the page nothing. Optional; without
|
|
48
|
+
* it the load carries no `vocabulary`, and a name with a word the model lacks goes unreported.
|
|
49
|
+
*/
|
|
50
|
+
readonly fetch?: (absoluteUrl: string) => Promise<{
|
|
51
|
+
readonly ok: boolean;
|
|
52
|
+
readonly body: ReadableStream<BufferSource> | null;
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
export type VoskLoad = {
|
|
56
|
+
readonly ok: true;
|
|
57
|
+
readonly model: VoskModel;
|
|
58
|
+
/**
|
|
59
|
+
* The words the loaded model knows, read from its archive once asked — `null` when they cannot be read. Present only when the
|
|
60
|
+
* deps lent a `fetch`.
|
|
61
|
+
*/
|
|
62
|
+
readonly vocabulary?: () => Promise<ReadonlySet<string> | null>;
|
|
63
|
+
}
|
|
64
|
+
/** The catalogue ids that are not in the checked cache — `language` when the project has no model for it. */
|
|
65
|
+
| {
|
|
66
|
+
readonly ok: false;
|
|
67
|
+
readonly missing: readonly string[];
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* PUTS THE BUNDLE IN THE PAGE ONCE PER ADDRESS, and answers with what it exports. A second call answers the same one: the
|
|
71
|
+
* bundle registers a worker and a wasm module, and loading it twice would pay for both again on a machine that has little of
|
|
72
|
+
* either. A rejection is forgotten, so a load that failed on a bad minute can be retried.
|
|
73
|
+
*
|
|
74
|
+
* 🔴 THE MEMO IS THE LOADER'S, AND THE LOADER IS BUILT ONCE BY THE ROOT (ADR-0232 D4), which hands it to every start of the
|
|
75
|
+
* recogniser. A memo built inside `loadVoskRuntime` was a new memo every call, so «once» only ever held within one call; a
|
|
76
|
+
* memo at module level was one per PAGE, shared by roots that share nothing else. `load` is the root's `import(url)`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function createBundleLoader(load: (absoluteUrl: string) => Promise<unknown>): (absoluteUrl: string) => Promise<VoskApi>;
|
|
79
|
+
/**
|
|
80
|
+
* ONE MODEL PER LANGUAGE, LOADED ONCE AND KEPT (ADR-0256): the 👄 and a choice by voice ask the same `load`, and a listener that
|
|
81
|
+
* stops no longer ends the model — the one handed out has a `terminate` that does nothing; the real one is ended when it is
|
|
82
|
+
* pushed out (more than `keep` languages, the oldest first) or by `closeAll()`, the root's end.
|
|
83
|
+
* 📏 Why: every start used to spawn a worker and unpack ~40 MiB of model, and every choice started two — the Dev's machine froze
|
|
84
|
+
* on 2026-09-27. A load that failed is forgotten, so a model that comes down later is found.
|
|
85
|
+
*/
|
|
86
|
+
export declare function keepVoskModels(load: (d: VoskDeps) => Promise<VoskLoad>, keep?: number): {
|
|
87
|
+
load(d: VoskDeps): Promise<VoskLoad>;
|
|
88
|
+
closeAll(): void;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Opens the recogniser for the child's language, or says what is missing.
|
|
92
|
+
*
|
|
93
|
+
* ⚠️ THE MODEL IS A `.tar.gz` THE BUNDLE FETCHES ITSELF, so what it is given is the DELIVERY path: the service worker answers it
|
|
94
|
+
* from the checked cache, and a school with no network after the first day still hears the child (pillar 8).
|
|
95
|
+
*/
|
|
96
|
+
export declare function loadVoskRuntime(d: VoskDeps): Promise<VoskLoad>;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// platform/vosk-runtime — THE RECOGNISER THAT HEARS COMMANDS, FROM THE GAME'S OWN ORIGIN (ADR-0189, ADR-0193; issue #184).
|
|
3
|
+
//
|
|
4
|
+
// The same shape as `platform/vision`, and for the same reasons: the runtime and the model are the files the install already
|
|
5
|
+
// fetched and checked by sha256 (`platform/heavy`), they are asked for at `heavy/<host><path>` beside the page, and a file
|
|
6
|
+
// that is not in the checked cache is never loaded — the loader answers WHICH ones are missing, so the child hears why speaking
|
|
7
|
+
// does not work instead of meeting a button that does nothing.
|
|
8
|
+
//
|
|
9
|
+
// 🎯 AND THIS RUNTIME EXISTS BECAUSE NO PUBLISHED ONE COULD BE USED: every `vosk-browser` build evaluates text as code, which
|
|
10
|
+
// this engine's policy refuses (ADR-0193 — never `'unsafe-eval'`, never a patch). It was rebuilt with `-s DYNAMIC_EXECUTION=0`
|
|
11
|
+
// and runs under the policy as it is (`docs/6-DevOps-SRE/models.md`).
|
|
12
|
+
//
|
|
13
|
+
// 🔴 IT IS AN ES MODULE THAT RESOLVES ITS OWN FILES THROUGH US, and this was MEASURED in a browser on 2026-09-21 after the
|
|
14
|
+
// first version of this loader assumed the opposite. The real bundle of `vosk-browser-dynamic-execution-0` ends in
|
|
15
|
+
// `export { createModel, Model, … }` and asks for the other two files by logical name:
|
|
16
|
+
// new Worker(resolver("npm/vosk/vosk.worker.js"), { type: "module" }) · wasmUrl: this.resolver("npm/vosk/vosk.wasm")
|
|
17
|
+
// So it is loaded with `import()` (the same way `platform/vision` loads `tasks-vision`), and the resolver answers with the
|
|
18
|
+
// DELIVERY path of each file — which is how the service worker gets to serve all three from the checked cache.
|
|
19
|
+
//
|
|
20
|
+
// ⚠️ THE LESSON IS ABOUT THE GATE AND NOT ABOUT THE FILE: the old shape («a classic script that defines a global and finds its
|
|
21
|
+
// neighbours by itself») had seven red mutations against a double built in the image of that belief. A double can only measure
|
|
22
|
+
// the contract you think you have; the one that exists was three lines of the served file away.
|
|
23
|
+
import { HEAVY_FILES, deliveryPath } from './heavy.js';
|
|
24
|
+
import { commandsLanguageOf } from './heavy-catalogue.js';
|
|
25
|
+
import { readModelVocabulary } from './vosk-vocabulary.js';
|
|
26
|
+
/** The three files of the runtime. The model is chosen by language, below. */
|
|
27
|
+
export const VOICE_RUNTIME_FILES = ['commands:runtime', 'commands:runtime:worker', 'commands:runtime:wasm'];
|
|
28
|
+
/** The catalogue id of the model that hears THIS language, or `null` where the project has none. */
|
|
29
|
+
export function commandModelId(language) {
|
|
30
|
+
const wanted = language.split('-')[0].toLowerCase();
|
|
31
|
+
const found = HEAVY_FILES.find((p) => commandsLanguageOf(p.id) === wanted);
|
|
32
|
+
return found ? found.id : null;
|
|
33
|
+
}
|
|
34
|
+
const urlOf = (id) => HEAVY_FILES.find((x) => x.id === id)?.url ?? null;
|
|
35
|
+
/**
|
|
36
|
+
* PUTS THE BUNDLE IN THE PAGE ONCE PER ADDRESS, and answers with what it exports. A second call answers the same one: the
|
|
37
|
+
* bundle registers a worker and a wasm module, and loading it twice would pay for both again on a machine that has little of
|
|
38
|
+
* either. A rejection is forgotten, so a load that failed on a bad minute can be retried.
|
|
39
|
+
*
|
|
40
|
+
* 🔴 THE MEMO IS THE LOADER'S, AND THE LOADER IS BUILT ONCE BY THE ROOT (ADR-0232 D4), which hands it to every start of the
|
|
41
|
+
* recogniser. A memo built inside `loadVoskRuntime` was a new memo every call, so «once» only ever held within one call; a
|
|
42
|
+
* memo at module level was one per PAGE, shared by roots that share nothing else. `load` is the root's `import(url)`.
|
|
43
|
+
*/
|
|
44
|
+
export function createBundleLoader(load) {
|
|
45
|
+
const asked = new Map();
|
|
46
|
+
return (absoluteUrl) => {
|
|
47
|
+
const already = asked.get(absoluteUrl);
|
|
48
|
+
if (already)
|
|
49
|
+
return already;
|
|
50
|
+
const pending = load(absoluteUrl);
|
|
51
|
+
asked.set(absoluteUrl, pending);
|
|
52
|
+
pending.catch(() => { asked.delete(absoluteUrl); });
|
|
53
|
+
return pending;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* ONE MODEL PER LANGUAGE, LOADED ONCE AND KEPT (ADR-0256): the 👄 and a choice by voice ask the same `load`, and a listener that
|
|
58
|
+
* stops no longer ends the model — the one handed out has a `terminate` that does nothing; the real one is ended when it is
|
|
59
|
+
* pushed out (more than `keep` languages, the oldest first) or by `closeAll()`, the root's end.
|
|
60
|
+
* 📏 Why: every start used to spawn a worker and unpack ~40 MiB of model, and every choice started two — the Dev's machine froze
|
|
61
|
+
* on 2026-09-27. A load that failed is forgotten, so a model that comes down later is found.
|
|
62
|
+
*/
|
|
63
|
+
export function keepVoskModels(load, keep = 2) {
|
|
64
|
+
/** Per language: the load as it came (whose model is the one to end) and the one handed out. */
|
|
65
|
+
const kept = new Map();
|
|
66
|
+
const end = (entry) => {
|
|
67
|
+
void entry.real.then((l) => { if (l.ok)
|
|
68
|
+
l.model.terminate?.(); }, () => { });
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
load(d) {
|
|
72
|
+
const key = d.language.split('-')[0].toLowerCase();
|
|
73
|
+
const found = kept.get(key);
|
|
74
|
+
if (found) {
|
|
75
|
+
kept.delete(key);
|
|
76
|
+
kept.set(key, found);
|
|
77
|
+
return found.lent;
|
|
78
|
+
} // the most recent last
|
|
79
|
+
const real = load(d);
|
|
80
|
+
const lent = real.then((l) => (l.ok ? { ...l, model: { get KaldiRecognizer() { return l.model.KaldiRecognizer; }, terminate: () => { } } } : l));
|
|
81
|
+
const entry = { real, lent };
|
|
82
|
+
kept.set(key, entry);
|
|
83
|
+
const forget = () => { if (kept.get(key) === entry)
|
|
84
|
+
kept.delete(key); };
|
|
85
|
+
real.then((l) => { if (!l.ok)
|
|
86
|
+
forget(); }, forget);
|
|
87
|
+
while (kept.size > keep) {
|
|
88
|
+
const [oldest, q] = kept.entries().next().value;
|
|
89
|
+
kept.delete(oldest);
|
|
90
|
+
end(q);
|
|
91
|
+
}
|
|
92
|
+
return lent;
|
|
93
|
+
},
|
|
94
|
+
closeAll() { for (const entry of kept.values())
|
|
95
|
+
end(entry); kept.clear(); },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Opens the recogniser for the child's language, or says what is missing.
|
|
100
|
+
*
|
|
101
|
+
* ⚠️ THE MODEL IS A `.tar.gz` THE BUNDLE FETCHES ITSELF, so what it is given is the DELIVERY path: the service worker answers it
|
|
102
|
+
* from the checked cache, and a school with no network after the first day still hears the child (pillar 8).
|
|
103
|
+
*/
|
|
104
|
+
export async function loadVoskRuntime(d) {
|
|
105
|
+
const modelId = commandModelId(d.language);
|
|
106
|
+
if (!modelId)
|
|
107
|
+
return { ok: false, missing: ['language'] };
|
|
108
|
+
const missing = [];
|
|
109
|
+
for (const id of [...VOICE_RUNTIME_FILES, modelId]) {
|
|
110
|
+
const url = urlOf(id);
|
|
111
|
+
if (!url || !(await d.hasFile(url)))
|
|
112
|
+
missing.push(id);
|
|
113
|
+
}
|
|
114
|
+
if (missing.length)
|
|
115
|
+
return { ok: false, missing };
|
|
116
|
+
const at = (id) => new URL(deliveryPath(urlOf(id)), d.base).href;
|
|
117
|
+
const api = await d.loadBundle(at('commands:runtime'));
|
|
118
|
+
// the loader answers whatever the address held; a file that is not the recogniser says so here, not as a TypeError below
|
|
119
|
+
if (typeof api?.createModel !== 'function') {
|
|
120
|
+
throw new Error('vosk-runtime: the bundle exported no `createModel` — the delivery has the wrong file');
|
|
121
|
+
}
|
|
122
|
+
/*
|
|
123
|
+
* WHERE THE BUNDLE'S TWO NEIGHBOURS LIVE, answered by us and never guessed. The logical names are the bundle's own
|
|
124
|
+
* (`npm/vosk/…`), and an unknown one THROWS instead of falling back to a file that happens to be handy: a worker fed the
|
|
125
|
+
* wasm, or the other way round, fails deep inside a thread with no way back to the child.
|
|
126
|
+
*/
|
|
127
|
+
const beside = (logicalPath) => {
|
|
128
|
+
if (logicalPath.endsWith('.worker.js'))
|
|
129
|
+
return at('commands:runtime:worker');
|
|
130
|
+
if (logicalPath.endsWith('.wasm'))
|
|
131
|
+
return at('commands:runtime:wasm');
|
|
132
|
+
throw new Error(`vosk-runtime: the bundle asked for a file this delivery does not carry: ${logicalPath}`);
|
|
133
|
+
};
|
|
134
|
+
// 📌 `-1` is the bundle's «say nothing»: a recogniser that logs every frame fills a school machine's console with noise.
|
|
135
|
+
const model = await api.createModel(at(modelId), beside, -1);
|
|
136
|
+
const { fetch } = d;
|
|
137
|
+
if (!fetch)
|
|
138
|
+
return { ok: true, model };
|
|
139
|
+
// the SAME address the worker was given: the service worker answers both from the checked cache, and the words read are the
|
|
140
|
+
// words of the model that was loaded, never another language's
|
|
141
|
+
const vocabulary = async () => {
|
|
142
|
+
try {
|
|
143
|
+
const r = await fetch(at(modelId));
|
|
144
|
+
return r.ok && r.body ? await readModelVocabulary(r.body) : null;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
return { ok: true, model, vocabulary };
|
|
151
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/**
|
|
3
|
+
* The words the model in this `.tar.gz` knows — the output symbol table of its `Gr.fst` — or `null` when that cannot be read
|
|
4
|
+
* (no word graph, a header that is not OpenFst's, a stream that ends early). Stops reading the archive once the table is read.
|
|
5
|
+
*/
|
|
6
|
+
export declare function readModelVocabulary(archive: ReadableStream<BufferSource>): Promise<ReadonlySet<string> | null>;
|