@oxy.so/bloom 7.1.4 → 7.2.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/assets/character-runtime/README.md +19 -114
- package/assets/character-runtime/legacy-engine.mjs +54 -406
- package/assets/character-runtime/legacy-geometry.mjs +85 -242
- package/assets/character-runtime/legacy-worker.mjs +23 -82
- package/assets/character-runtime/managed-avatar.mjs +18 -12
- package/assets/character-runtime/render-budget.mjs +11 -6
- package/assets/character-runtime/runtime.mjs +295 -744
- package/docs/adoption-matrix.mdx +12 -11
- package/docs/agent-avatar.mdx +8 -45
- package/docs/agent-creator.mdx +3 -13
- package/docs/app-shell.mdx +26 -2
- package/docs/appearance.mdx +16 -1
- package/docs/content-panel.mdx +4 -0
- package/docs/mail-thread.mdx +8 -0
- package/docs/page-footer.mdx +60 -0
- package/docs/sidebar.mdx +1 -1
- package/lib/commonjs/agent-avatar/AgentAvatar.js +1 -1
- package/lib/commonjs/agent-avatar/AgentAvatar.js.map +1 -1
- package/lib/commonjs/agent-avatar/CharacterAvatar.js +1 -2
- package/lib/commonjs/agent-avatar/CharacterAvatar.js.map +1 -1
- package/lib/commonjs/agent-avatar/config-character.js +0 -4
- package/lib/commonjs/agent-avatar/config-character.js.map +1 -1
- package/lib/commonjs/agent-avatar/legacy-recipe.js +6 -19
- package/lib/commonjs/agent-avatar/legacy-recipe.js.map +1 -1
- package/lib/commonjs/agent-creator/AgentCreatorBase.js +107 -67
- package/lib/commonjs/agent-creator/AgentCreatorBase.js.map +1 -1
- package/lib/commonjs/agent-creator/CharacterControls.js +5 -23
- package/lib/commonjs/agent-creator/CharacterControls.js.map +1 -1
- package/lib/commonjs/agent-creator/EmotionPicker.js +1 -8
- package/lib/commonjs/agent-creator/EmotionPicker.js.map +1 -1
- package/lib/commonjs/agent-creator/ShapeSilhouette.js +1 -8
- package/lib/commonjs/agent-creator/ShapeSilhouette.js.map +1 -1
- package/lib/commonjs/agent-creator/constants.js +17 -16
- package/lib/commonjs/agent-creator/constants.js.map +1 -1
- package/lib/commonjs/agent-creator/messages.js +1 -1
- package/lib/commonjs/agent-creator/messages.js.map +1 -1
- package/lib/commonjs/app-shell/AppShell.js +3 -2
- package/lib/commonjs/app-shell/AppShell.js.map +1 -1
- package/lib/commonjs/app-shell/AppShellBars.js +8 -5
- package/lib/commonjs/app-shell/AppShellBars.js.map +1 -1
- package/lib/commonjs/app-shell/AppShellEngine.js +81 -36
- package/lib/commonjs/app-shell/AppShellEngine.js.map +1 -1
- package/lib/commonjs/appearance/BloomScope.js +8 -3
- package/lib/commonjs/appearance/BloomScope.js.map +1 -1
- package/lib/commonjs/appearance/context.js.map +1 -1
- package/lib/commonjs/content-panel/ContentPanel.js +34 -23
- package/lib/commonjs/content-panel/ContentPanel.js.map +1 -1
- package/lib/commonjs/content-panel/ContentPanel.web.js +39 -17
- package/lib/commonjs/content-panel/ContentPanel.web.js.map +1 -1
- package/lib/commonjs/design-tokens/shapes.js +2 -2
- package/lib/commonjs/design-tokens/shapes.js.map +1 -1
- package/lib/commonjs/design-tokens/tokens.json +2 -2
- package/lib/commonjs/index.js +939 -927
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +939 -927
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/locale/translations/ar.js +1 -1
- package/lib/commonjs/locale/translations/ar.js.map +1 -1
- package/lib/commonjs/locale/translations/bn.js +1 -1
- package/lib/commonjs/locale/translations/bn.js.map +1 -1
- package/lib/commonjs/locale/translations/ca.js +1 -1
- package/lib/commonjs/locale/translations/ca.js.map +1 -1
- package/lib/commonjs/locale/translations/de.js +1 -1
- package/lib/commonjs/locale/translations/de.js.map +1 -1
- package/lib/commonjs/locale/translations/es.js +1 -1
- package/lib/commonjs/locale/translations/es.js.map +1 -1
- package/lib/commonjs/locale/translations/fr.js +1 -1
- package/lib/commonjs/locale/translations/fr.js.map +1 -1
- package/lib/commonjs/locale/translations/hi.js +1 -1
- package/lib/commonjs/locale/translations/hi.js.map +1 -1
- package/lib/commonjs/locale/translations/id.js +1 -1
- package/lib/commonjs/locale/translations/id.js.map +1 -1
- package/lib/commonjs/locale/translations/it.js +1 -1
- package/lib/commonjs/locale/translations/it.js.map +1 -1
- package/lib/commonjs/locale/translations/ja.js +1 -1
- package/lib/commonjs/locale/translations/ja.js.map +1 -1
- package/lib/commonjs/locale/translations/pt.js +1 -1
- package/lib/commonjs/locale/translations/pt.js.map +1 -1
- package/lib/commonjs/locale/translations/ru.js +1 -1
- package/lib/commonjs/locale/translations/ru.js.map +1 -1
- package/lib/commonjs/locale/translations/tr.js +1 -1
- package/lib/commonjs/locale/translations/tr.js.map +1 -1
- package/lib/commonjs/locale/translations/zh.js +1 -1
- package/lib/commonjs/locale/translations/zh.js.map +1 -1
- package/lib/commonjs/mail-thread/MailMessage.js +8 -14
- package/lib/commonjs/mail-thread/MailMessage.js.map +1 -1
- package/lib/commonjs/mail-thread/MailThread.js +6 -2
- package/lib/commonjs/mail-thread/MailThread.js.map +1 -1
- package/lib/commonjs/mail-thread/shared.js +2 -1
- package/lib/commonjs/mail-thread/shared.js.map +1 -1
- package/lib/commonjs/page-footer/PageFooter.js +137 -0
- package/lib/commonjs/page-footer/PageFooter.js.map +1 -0
- package/lib/commonjs/page-footer/PageFooterProvider.js +22 -0
- package/lib/commonjs/page-footer/PageFooterProvider.js.map +1 -0
- package/lib/commonjs/page-footer/context.js +11 -0
- package/lib/commonjs/page-footer/context.js.map +1 -0
- package/lib/commonjs/page-footer/index.js +27 -0
- package/lib/commonjs/page-footer/index.js.map +1 -0
- package/lib/commonjs/page-footer/types.js +6 -0
- package/lib/commonjs/page-footer/types.js.map +1 -0
- package/lib/commonjs/page-footer/use-page-footer-inset.js +19 -0
- package/lib/commonjs/page-footer/use-page-footer-inset.js.map +1 -0
- package/lib/commonjs/sidebar/Sidebar.js +6 -5
- package/lib/commonjs/sidebar/Sidebar.js.map +1 -1
- package/lib/commonjs/styles/panel-chrome.js +15 -1
- package/lib/commonjs/styles/panel-chrome.js.map +1 -1
- package/lib/module/agent-avatar/AgentAvatar.js +1 -1
- package/lib/module/agent-avatar/AgentAvatar.js.map +1 -1
- package/lib/module/agent-avatar/CharacterAvatar.js +1 -2
- package/lib/module/agent-avatar/CharacterAvatar.js.map +1 -1
- package/lib/module/agent-avatar/config-character.js +0 -4
- package/lib/module/agent-avatar/config-character.js.map +1 -1
- package/lib/module/agent-avatar/legacy-recipe.js +6 -19
- package/lib/module/agent-avatar/legacy-recipe.js.map +1 -1
- package/lib/module/agent-creator/AgentCreatorBase.js +109 -69
- package/lib/module/agent-creator/AgentCreatorBase.js.map +1 -1
- package/lib/module/agent-creator/CharacterControls.js +6 -24
- package/lib/module/agent-creator/CharacterControls.js.map +1 -1
- package/lib/module/agent-creator/EmotionPicker.js +1 -8
- package/lib/module/agent-creator/EmotionPicker.js.map +1 -1
- package/lib/module/agent-creator/ShapeSilhouette.js +1 -8
- package/lib/module/agent-creator/ShapeSilhouette.js.map +1 -1
- package/lib/module/agent-creator/constants.js +16 -8
- package/lib/module/agent-creator/constants.js.map +1 -1
- package/lib/module/agent-creator/messages.js +1 -1
- package/lib/module/agent-creator/messages.js.map +1 -1
- package/lib/module/app-shell/AppShell.js +3 -2
- package/lib/module/app-shell/AppShell.js.map +1 -1
- package/lib/module/app-shell/AppShellBars.js +8 -5
- package/lib/module/app-shell/AppShellBars.js.map +1 -1
- package/lib/module/app-shell/AppShellEngine.js +81 -36
- package/lib/module/app-shell/AppShellEngine.js.map +1 -1
- package/lib/module/appearance/BloomScope.js +8 -3
- package/lib/module/appearance/BloomScope.js.map +1 -1
- package/lib/module/appearance/context.js.map +1 -1
- package/lib/module/content-panel/ContentPanel.js +35 -24
- package/lib/module/content-panel/ContentPanel.js.map +1 -1
- package/lib/module/content-panel/ContentPanel.web.js +41 -19
- package/lib/module/content-panel/ContentPanel.web.js.map +1 -1
- package/lib/module/design-tokens/shapes.js +2 -2
- package/lib/module/design-tokens/shapes.js.map +1 -1
- package/lib/module/design-tokens/tokens.json +2 -2
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +1 -0
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/locale/translations/ar.js +1 -1
- package/lib/module/locale/translations/ar.js.map +1 -1
- package/lib/module/locale/translations/bn.js +1 -1
- package/lib/module/locale/translations/bn.js.map +1 -1
- package/lib/module/locale/translations/ca.js +1 -1
- package/lib/module/locale/translations/ca.js.map +1 -1
- package/lib/module/locale/translations/de.js +1 -1
- package/lib/module/locale/translations/de.js.map +1 -1
- package/lib/module/locale/translations/es.js +1 -1
- package/lib/module/locale/translations/es.js.map +1 -1
- package/lib/module/locale/translations/fr.js +1 -1
- package/lib/module/locale/translations/fr.js.map +1 -1
- package/lib/module/locale/translations/hi.js +1 -1
- package/lib/module/locale/translations/hi.js.map +1 -1
- package/lib/module/locale/translations/id.js +1 -1
- package/lib/module/locale/translations/id.js.map +1 -1
- package/lib/module/locale/translations/it.js +1 -1
- package/lib/module/locale/translations/it.js.map +1 -1
- package/lib/module/locale/translations/ja.js +1 -1
- package/lib/module/locale/translations/ja.js.map +1 -1
- package/lib/module/locale/translations/pt.js +1 -1
- package/lib/module/locale/translations/pt.js.map +1 -1
- package/lib/module/locale/translations/ru.js +1 -1
- package/lib/module/locale/translations/ru.js.map +1 -1
- package/lib/module/locale/translations/tr.js +1 -1
- package/lib/module/locale/translations/tr.js.map +1 -1
- package/lib/module/locale/translations/zh.js +1 -1
- package/lib/module/locale/translations/zh.js.map +1 -1
- package/lib/module/mail-thread/MailMessage.js +8 -14
- package/lib/module/mail-thread/MailMessage.js.map +1 -1
- package/lib/module/mail-thread/MailThread.js +6 -2
- package/lib/module/mail-thread/MailThread.js.map +1 -1
- package/lib/module/mail-thread/shared.js +2 -1
- package/lib/module/mail-thread/shared.js.map +1 -1
- package/lib/module/page-footer/PageFooter.js +132 -0
- package/lib/module/page-footer/PageFooter.js.map +1 -0
- package/lib/module/page-footer/PageFooterProvider.js +18 -0
- package/lib/module/page-footer/PageFooterProvider.js.map +1 -0
- package/lib/module/page-footer/context.js +7 -0
- package/lib/module/page-footer/context.js.map +1 -0
- package/lib/module/page-footer/index.js +6 -0
- package/lib/module/page-footer/index.js.map +1 -0
- package/lib/module/page-footer/types.js +4 -0
- package/lib/module/page-footer/types.js.map +1 -0
- package/lib/module/page-footer/use-page-footer-inset.js +16 -0
- package/lib/module/page-footer/use-page-footer-inset.js.map +1 -0
- package/lib/module/sidebar/Sidebar.js +6 -5
- package/lib/module/sidebar/Sidebar.js.map +1 -1
- package/lib/module/styles/panel-chrome.js +14 -1
- package/lib/module/styles/panel-chrome.js.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/CharacterAvatar.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/config-character.d.ts +0 -4
- package/lib/typescript/commonjs/agent-avatar/config-character.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts +10 -2
- package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/AgentCreatorBase.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts +1 -2
- package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts +0 -1
- package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/ShapeSilhouette.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/constants.d.ts +15 -7
- package/lib/typescript/commonjs/agent-creator/constants.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/messages.d.ts.map +1 -1
- package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts +4 -0
- package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts.map +1 -1
- package/lib/typescript/commonjs/app-shell/AppShellEngine.d.ts.map +1 -1
- package/lib/typescript/commonjs/app-shell/types.d.ts +11 -3
- package/lib/typescript/commonjs/app-shell/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/appearance/BloomScope.d.ts +1 -1
- package/lib/typescript/commonjs/appearance/BloomScope.d.ts.map +1 -1
- package/lib/typescript/commonjs/appearance/context.d.ts +2 -2
- package/lib/typescript/commonjs/appearance/context.d.ts.map +1 -1
- package/lib/typescript/commonjs/appearance/types.d.ts +4 -1
- package/lib/typescript/commonjs/appearance/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/content-panel/ContentPanel.d.ts +3 -4
- package/lib/typescript/commonjs/content-panel/ContentPanel.d.ts.map +1 -1
- package/lib/typescript/commonjs/content-panel/ContentPanel.web.d.ts +1 -1
- package/lib/typescript/commonjs/content-panel/ContentPanel.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/content-panel/types.d.ts +2 -2
- package/lib/typescript/commonjs/design-tokens/shapes.d.ts +2 -2
- package/lib/typescript/commonjs/index.d.ts +1 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +1 -0
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/mail-thread/MailMessage.d.ts.map +1 -1
- package/lib/typescript/commonjs/mail-thread/MailThread.d.ts +1 -1
- package/lib/typescript/commonjs/mail-thread/MailThread.d.ts.map +1 -1
- package/lib/typescript/commonjs/mail-thread/shared.d.ts +1 -1
- package/lib/typescript/commonjs/mail-thread/shared.d.ts.map +1 -1
- package/lib/typescript/commonjs/mail-thread/types.d.ts +2 -0
- package/lib/typescript/commonjs/mail-thread/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/page-footer/PageFooter.d.ts +7 -0
- package/lib/typescript/commonjs/page-footer/PageFooter.d.ts.map +1 -0
- package/lib/typescript/commonjs/page-footer/PageFooterProvider.d.ts +4 -0
- package/lib/typescript/commonjs/page-footer/PageFooterProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/page-footer/context.d.ts +3 -0
- package/lib/typescript/commonjs/page-footer/context.d.ts.map +1 -0
- package/lib/typescript/commonjs/page-footer/index.d.ts +5 -0
- package/lib/typescript/commonjs/page-footer/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/page-footer/types.d.ts +26 -0
- package/lib/typescript/commonjs/page-footer/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/page-footer/use-page-footer-inset.d.ts +7 -0
- package/lib/typescript/commonjs/page-footer/use-page-footer-inset.d.ts.map +1 -0
- package/lib/typescript/commonjs/sidebar/Sidebar.d.ts.map +1 -1
- package/lib/typescript/commonjs/sidebar/types.d.ts +1 -1
- package/lib/typescript/commonjs/styles/panel-chrome.d.ts +5 -0
- package/lib/typescript/commonjs/styles/panel-chrome.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/CharacterAvatar.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/config-character.d.ts +0 -4
- package/lib/typescript/module/agent-avatar/config-character.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts +10 -2
- package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/AgentCreatorBase.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/CharacterControls.d.ts +1 -2
- package/lib/typescript/module/agent-creator/CharacterControls.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/EmotionPicker.d.ts +0 -1
- package/lib/typescript/module/agent-creator/EmotionPicker.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/ShapeSilhouette.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/constants.d.ts +15 -7
- package/lib/typescript/module/agent-creator/constants.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/messages.d.ts.map +1 -1
- package/lib/typescript/module/app-shell/AppShellBars.d.ts +4 -0
- package/lib/typescript/module/app-shell/AppShellBars.d.ts.map +1 -1
- package/lib/typescript/module/app-shell/AppShellEngine.d.ts.map +1 -1
- package/lib/typescript/module/app-shell/types.d.ts +11 -3
- package/lib/typescript/module/app-shell/types.d.ts.map +1 -1
- package/lib/typescript/module/appearance/BloomScope.d.ts +1 -1
- package/lib/typescript/module/appearance/BloomScope.d.ts.map +1 -1
- package/lib/typescript/module/appearance/context.d.ts +2 -2
- package/lib/typescript/module/appearance/context.d.ts.map +1 -1
- package/lib/typescript/module/appearance/types.d.ts +4 -1
- package/lib/typescript/module/appearance/types.d.ts.map +1 -1
- package/lib/typescript/module/content-panel/ContentPanel.d.ts +3 -4
- package/lib/typescript/module/content-panel/ContentPanel.d.ts.map +1 -1
- package/lib/typescript/module/content-panel/ContentPanel.web.d.ts +1 -1
- package/lib/typescript/module/content-panel/ContentPanel.web.d.ts.map +1 -1
- package/lib/typescript/module/content-panel/types.d.ts +2 -2
- package/lib/typescript/module/design-tokens/shapes.d.ts +2 -2
- package/lib/typescript/module/index.d.ts +1 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +1 -0
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/mail-thread/MailMessage.d.ts.map +1 -1
- package/lib/typescript/module/mail-thread/MailThread.d.ts +1 -1
- package/lib/typescript/module/mail-thread/MailThread.d.ts.map +1 -1
- package/lib/typescript/module/mail-thread/shared.d.ts +1 -1
- package/lib/typescript/module/mail-thread/shared.d.ts.map +1 -1
- package/lib/typescript/module/mail-thread/types.d.ts +2 -0
- package/lib/typescript/module/mail-thread/types.d.ts.map +1 -1
- package/lib/typescript/module/page-footer/PageFooter.d.ts +7 -0
- package/lib/typescript/module/page-footer/PageFooter.d.ts.map +1 -0
- package/lib/typescript/module/page-footer/PageFooterProvider.d.ts +4 -0
- package/lib/typescript/module/page-footer/PageFooterProvider.d.ts.map +1 -0
- package/lib/typescript/module/page-footer/context.d.ts +3 -0
- package/lib/typescript/module/page-footer/context.d.ts.map +1 -0
- package/lib/typescript/module/page-footer/index.d.ts +5 -0
- package/lib/typescript/module/page-footer/index.d.ts.map +1 -0
- package/lib/typescript/module/page-footer/types.d.ts +26 -0
- package/lib/typescript/module/page-footer/types.d.ts.map +1 -0
- package/lib/typescript/module/page-footer/use-page-footer-inset.d.ts +7 -0
- package/lib/typescript/module/page-footer/use-page-footer-inset.d.ts.map +1 -0
- package/lib/typescript/module/sidebar/Sidebar.d.ts.map +1 -1
- package/lib/typescript/module/sidebar/types.d.ts +1 -1
- package/lib/typescript/module/styles/panel-chrome.d.ts +5 -0
- package/lib/typescript/module/styles/panel-chrome.d.ts.map +1 -1
- package/package.json +18 -1
- package/src/__tests__/support/adoption-matrix.ts +683 -0
- package/src/__tests__/support/card-surface.ts +25 -0
- package/src/__tests__/support/collision-fixture-barrel.ts +20 -0
- package/src/__tests__/support/commerce-harness.tsx +97 -0
- package/src/__tests__/support/composite.ts +68 -0
- package/src/__tests__/support/constructed-style-sheets.ts +68 -0
- package/src/__tests__/support/messages-in.ts +10 -0
- package/src/__tests__/support/press-host.ts +30 -0
- package/src/__tests__/support/rendered-style.ts +99 -0
- package/src/__tests__/support/unread-hook-fixture.ts +33 -0
- package/src/__tests__/support/worklet-capture-fixture.tsx +28 -0
- package/src/agent-avatar/AgentAvatar.tsx +1 -1
- package/src/agent-avatar/CharacterAvatar.tsx +1 -4
- package/src/agent-avatar/__tests__/artwork-golden.json +774 -0
- package/src/agent-avatar/config-character.ts +6 -39
- package/src/agent-avatar/legacy-recipe.ts +6 -34
- package/src/agent-creator/AgentCreatorBase.tsx +152 -121
- package/src/agent-creator/CharacterControls.tsx +14 -39
- package/src/agent-creator/EmotionPicker.tsx +16 -55
- package/src/agent-creator/ShapeSilhouette.tsx +1 -16
- package/src/agent-creator/__tests__/support/character-runtime-fixture.tsx +26 -0
- package/src/agent-creator/constants.ts +14 -47
- package/src/agent-creator/messages.ts +1 -2
- package/src/app-shell/AppShell.tsx +2 -2
- package/src/app-shell/AppShellBars.tsx +6 -4
- package/src/app-shell/AppShellEngine.tsx +51 -18
- package/src/app-shell/types.ts +11 -3
- package/src/appearance/BloomScope.tsx +5 -2
- package/src/appearance/context.ts +2 -2
- package/src/appearance/types.ts +4 -1
- package/src/content-panel/ContentPanel.tsx +32 -25
- package/src/content-panel/ContentPanel.web.tsx +32 -23
- package/src/content-panel/types.ts +2 -2
- package/src/design-tokens/shapes.ts +1 -1
- package/src/design-tokens/tokens.json +2 -2
- package/src/index.ts +1 -0
- package/src/index.web.ts +1 -0
- package/src/locale/translations/ar.ts +1 -1
- package/src/locale/translations/bn.ts +1 -1
- package/src/locale/translations/ca.ts +1 -1
- package/src/locale/translations/de.ts +1 -1
- package/src/locale/translations/es.ts +1 -1
- package/src/locale/translations/fr.ts +1 -1
- package/src/locale/translations/hi.ts +1 -1
- package/src/locale/translations/id.ts +1 -1
- package/src/locale/translations/it.ts +1 -1
- package/src/locale/translations/ja.ts +1 -1
- package/src/locale/translations/pt.ts +1 -1
- package/src/locale/translations/ru.ts +1 -1
- package/src/locale/translations/tr.ts +1 -1
- package/src/locale/translations/zh.ts +1 -1
- package/src/mail-thread/MailMessage.tsx +9 -11
- package/src/mail-thread/MailThread.tsx +3 -1
- package/src/mail-thread/shared.ts +2 -1
- package/src/mail-thread/types.ts +2 -0
- package/src/page-footer/PageFooter.tsx +96 -0
- package/src/page-footer/PageFooterProvider.tsx +9 -0
- package/src/page-footer/context.ts +6 -0
- package/src/page-footer/index.ts +4 -0
- package/src/page-footer/types.ts +26 -0
- package/src/page-footer/use-page-footer-inset.ts +17 -0
- package/src/sidebar/Sidebar.tsx +5 -4
- package/src/sidebar/types.ts +1 -1
- package/src/styles/panel-chrome.ts +9 -1
- package/src/theme/__tests__/__fixtures__/golden-resolved-tokens.json +9346 -0
- package/src/theme/__tests__/__fixtures__/tonal-glass-primary-failures.json +69 -0
- package/src/theme/__tests__/fixtures/color-engine-golden.json +1 -0
- package/assets/character-runtime/authored-parts.mjs +0 -754
- package/assets/character-runtime/catalog-parts.mjs +0 -362
- package/assets/character-runtime/character-recipe.mjs +0 -247
- package/assets/character-runtime/clippo-geometry.mjs +0 -679
- package/assets/character-runtime/controller-mode.mjs +0 -208
- package/assets/character-runtime/cyclops-geometry.mjs +0 -180
- package/assets/character-runtime/migrated-contours.mjs +0 -2067
- package/assets/character-runtime/migrated-faces.mjs +0 -59
- package/assets/character-runtime/pose-transition.mjs +0 -523
- package/assets/character-runtime/preparation-cache.mjs +0 -60
- package/assets/character-runtime/render-errors.mjs +0 -180
- package/assets/character-runtime/resolution.mjs +0 -10
- package/assets/character-runtime/sha256.mjs +0 -44
- package/assets/character-runtime/shared-programs.mjs +0 -534
- package/assets/character-runtime/shared-surface.mjs +0 -490
- package/assets/character-runtime/shared-textures.mjs +0 -420
- package/assets/character-runtime/thumbnails/eyes/todd.png +0 -0
- package/lib/commonjs/agent-avatar/character-colors.js +0 -19
- package/lib/commonjs/agent-avatar/character-colors.js.map +0 -1
- package/lib/commonjs/agent-avatar/character-shapes.js +0 -106
- package/lib/commonjs/agent-avatar/character-shapes.js.map +0 -1
- package/lib/commonjs/agent-creator/ClippoArtwork.js +0 -63
- package/lib/commonjs/agent-creator/ClippoArtwork.js.map +0 -1
- package/lib/commonjs/agent-creator/CyclopsArtwork.js +0 -45
- package/lib/commonjs/agent-creator/CyclopsArtwork.js.map +0 -1
- package/lib/commonjs/agent-creator/ToddArtwork.js +0 -29
- package/lib/commonjs/agent-creator/ToddArtwork.js.map +0 -1
- package/lib/module/agent-avatar/character-colors.js +0 -15
- package/lib/module/agent-avatar/character-colors.js.map +0 -1
- package/lib/module/agent-avatar/character-shapes.js +0 -97
- package/lib/module/agent-avatar/character-shapes.js.map +0 -1
- package/lib/module/agent-creator/ClippoArtwork.js +0 -59
- package/lib/module/agent-creator/ClippoArtwork.js.map +0 -1
- package/lib/module/agent-creator/CyclopsArtwork.js +0 -41
- package/lib/module/agent-creator/CyclopsArtwork.js.map +0 -1
- package/lib/module/agent-creator/ToddArtwork.js +0 -25
- package/lib/module/agent-creator/ToddArtwork.js.map +0 -1
- package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts +0 -13
- package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts.map +0 -1
- package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts +0 -19
- package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts.map +0 -1
- package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts +0 -6
- package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts.map +0 -1
- package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts +0 -5
- package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts.map +0 -1
- package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts +0 -6
- package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts.map +0 -1
- package/lib/typescript/module/agent-avatar/character-colors.d.ts +0 -13
- package/lib/typescript/module/agent-avatar/character-colors.d.ts.map +0 -1
- package/lib/typescript/module/agent-avatar/character-shapes.d.ts +0 -19
- package/lib/typescript/module/agent-avatar/character-shapes.d.ts.map +0 -1
- package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts +0 -6
- package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts.map +0 -1
- package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts +0 -5
- package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts.map +0 -1
- package/lib/typescript/module/agent-creator/ToddArtwork.d.ts +0 -6
- package/lib/typescript/module/agent-creator/ToddArtwork.d.ts.map +0 -1
- package/src/agent-avatar/character-colors.ts +0 -12
- package/src/agent-avatar/character-shapes.ts +0 -122
- package/src/agent-creator/ClippoArtwork.tsx +0 -49
- package/src/agent-creator/CyclopsArtwork.tsx +0 -27
- package/src/agent-creator/ToddArtwork.tsx +0 -24
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Serve this directory unchanged from a static URL and pass runtime.mjs's URL to
|
|
4
4
|
AgentAvatarProvider. The runtime loads lazily when an avatar becomes visible.
|
|
5
|
-
Serve .mjs as JavaScript and .wasm as application/wasm.
|
|
6
|
-
directory as a unit: changing only the runtime.mjs query does not invalidate
|
|
7
|
-
its relative imports under immutable HTTP caching.
|
|
5
|
+
Serve .mjs as JavaScript and .wasm as application/wasm.
|
|
8
6
|
|
|
9
7
|
The four generated engine files are preserved byte for byte from the supplied
|
|
10
8
|
local beta. integrity.json records their SHA-256 hashes. The complete supplied
|
|
@@ -16,97 +14,18 @@ runtime.mjs is an adapter for the original engine, retaining its appearance,
|
|
|
16
14
|
materials and animations. It owns loading, selection, input, display scaling and
|
|
17
15
|
resource lifetime. There is no replacement mesh renderer in the product.
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
mipmapped RGBA8 assets and the 576×960 RGBA8 atlas. Mutation or framebuffer
|
|
28
|
-
attachment first gives that logical texture independent storage. Other textures,
|
|
29
|
-
mutable buffers and private render targets are not deduplicated. Small avatars
|
|
30
|
-
use compact meshes independent of device pixel ratio. Fur and original materials
|
|
31
|
-
remain intact. resolution.mjs selects backing size by CSS size and DPR, activating
|
|
32
|
-
the original engine's existing size-dependent fur LOD.
|
|
17
|
+
Beta characters share one engine per document and all avatars share a 30fps
|
|
18
|
+
clock. Legacy contours isolate rendering modules to keep native geometry caches
|
|
19
|
+
from returning another silhouette; one worker prepares their scenes. Unused
|
|
20
|
+
modules are released. Static portrait preparation is serialized, cached (up to 64 images), and
|
|
21
|
+
releases its graphics surfaces after painting. Offscreen/background characters
|
|
22
|
+
stop rendering; pause and reduced motion freeze a complete visible frame. The
|
|
23
|
+
binary's initial reduced-motion flag can produce transparent frames; the adapter
|
|
24
|
+
freezes its own clock after painting instead.
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
one context and no graphics errors. Median paint rates are 4.42/2.29 Hz per avatar;
|
|
38
|
-
all-ready latency is 14.85/24.80 seconds with warm HTTP caches. The 30 fps target
|
|
39
|
-
is not achieved. Earlier snapshots are retained for comparison; see
|
|
40
|
-
docs/agent-avatar.mdx for workload and measurement limitations.
|
|
41
|
-
|
|
42
|
-
Original and migrated contours share a rendering WASM module and one preparation
|
|
43
|
-
worker, which owns a separate WASM instance. Geometry identities include contour and attachment transforms. The adapter
|
|
44
|
-
scopes the recovered engine's deferred preparation dispatcher to its character;
|
|
45
|
-
that boundary is specific to the integrity-pinned glue. Its native global batch
|
|
46
|
-
can combine jobs from different characters, so wrapping callbacks alone is not
|
|
47
|
-
sufficient: the preparation lease spans mutation, deferred jobs and first paint. Cold preparation is
|
|
48
|
-
serialized; painted moving neighbours remain resident. Static portraits are
|
|
49
|
-
cached (up to 64 images), and release graphics surfaces after painting. Exact contour preparations use an independent 8 MiB/16-entry LRU cache, including appearance, quality, activity and contour and authored-part identity; returned buffers are copied. The preparation owner receives a render turn every batch until its first complete paint. Recent interactions receive alternate-batch priority without starving the remaining round-robin queue.
|
|
50
|
-
Offscreen/background characters release their leases. Pause and reduced motion
|
|
51
|
-
freeze a complete visible frame. The binary's initial reduced-motion flag can
|
|
52
|
-
produce transparent frames; the adapter freezes its clock after painting instead.
|
|
53
|
-
|
|
54
|
-
Shared submissions contain at most eight avatars and an 8 ms CPU allowance. A WebGL fence is polled asynchronously before error checks and presentation, allowing the page to process input while the GPU works. Lifecycle and native input operations wait for this boundary; DOM pointer capture remains synchronous. Diagnostics separate CPU submission/presentation from elapsed GPU waiting and task dispatch. This improves responsiveness without claiming faster GPU throughput.
|
|
55
|
-
|
|
56
|
-
React and Work retain one native Character, its prepared meshes and animation
|
|
57
|
-
clock. controller-mode.mjs verifies the original WASM SHA-256 before capturing
|
|
58
|
-
its memory through the supported instantiateWasm hook. A JS hash fallback keeps
|
|
59
|
-
this check working on insecure HTTP WebView origins. The adapter validates the
|
|
60
|
-
Embind handle, native type marker, live instance, bounds and boolean controller
|
|
61
|
-
field on every access; memory growth never leaves a stale typed view. Its ABI
|
|
62
|
-
layout is specific to the pinned WASM and must be re-proved for another binary.
|
|
63
|
-
Activity support prepares the original props up front. A constructor without
|
|
64
|
-
activity support rejects Restore/Start; incremental preparation is not assumed.
|
|
65
|
-
Stop completion reads the original current phase/activity/episode, since both
|
|
66
|
-
copyActivityRestore and hasPendingUpdate can misrepresent outro completion.
|
|
67
|
-
Appearance changes retain any simultaneous Work/React request until the new
|
|
68
|
-
scene is painted; pausing or disposal cancels those requests.
|
|
69
|
-
Queued reactions retain the original Busy semantics until the suspended reaction
|
|
70
|
-
finishes. verify-avatar-controller-continuity.mjs checks the complete runtime
|
|
71
|
-
switches, native identity, unchanged geometry, original outro and real pixels.
|
|
72
|
-
pose-transition.mjs interpolates reflected transform/skin uniform blocks and
|
|
73
|
-
camera for 180 ms from the last presented pose. It preserves material/discrete
|
|
74
|
-
bytes and original animation of newly added props. No bitmap crossfade or
|
|
75
|
-
replacement mesh renderer is involved.
|
|
76
|
-
|
|
77
|
-
authored-parts.mjs exposes eyes:todd and accessory:felipe_beret across all 21
|
|
78
|
-
shapes. The worker copies complete native records from lime_frog and blue_beret,
|
|
79
|
-
retaining materials and animation deltas, fits them after contour deformation,
|
|
80
|
-
and removes the generic fitting references. Original activity data remains intact; the aggregate scene bounds expand to
|
|
81
|
-
include the fitted parts. Virtual IDs never reach native catalog selection. Cache keys include
|
|
82
|
-
these parts; verify-avatar-authored-parts.mjs checks all 21 real rendered shapes,
|
|
83
|
-
original/migrated Work and React, generic selections and cleanup.
|
|
84
|
-
|
|
85
|
-
clippo-geometry.mjs adds a smooth open tube and an independently selectable
|
|
86
|
-
Clippo eye/brow set as native prepared records. It generates capped tube meshes,
|
|
87
|
-
retains the original eye deformation fields and uses the recovered smooth
|
|
88
|
-
material in the same renderer. No raster cutout or additional WebGL context is
|
|
89
|
-
used. character-recipe.mjs resolves the clippo preset to its virtual shape/eyes
|
|
90
|
-
and grey paint; explicit selections override those defaults. Runtime capabilities
|
|
91
|
-
retain the caller's raw saved key, including when an explicit default selection
|
|
92
|
-
leaves the prepared appearance unchanged. Editor chips are static SVG artwork.
|
|
93
|
-
|
|
94
|
-
catalog-parts.mjs fits actual original eye, eyewear and accessory meshes across
|
|
95
|
-
all bodies. Named presets supply editable defaults; changing a part retains the
|
|
96
|
-
original body. Opaque sunglasses recover their hidden-eye fitting references
|
|
97
|
-
without replacing the body. Donor records have an 8 MiB/24-entry bounded cache.
|
|
98
|
-
verify-avatar-catalog-parts.mjs checks 312 combinations, exact requested mesh
|
|
99
|
-
labels, preserved body vertices and the cache bound.
|
|
100
|
-
|
|
101
|
-
cyclops-geometry.mjs adds one native white eyeball, a teal iris, pupil and glint;
|
|
102
|
-
its layered meshes retain native blink/look deformation. Each shape owns eye
|
|
103
|
-
positions and size, shared by every eye style; historical character.eyeSpacing
|
|
104
|
-
values are ignored. Todd's actual body is also independently selectable
|
|
105
|
-
as shape:todd. verify-avatar-cyclops.mjs checks actual eye colors, movement and
|
|
106
|
-
cleanup; verify-avatar-customization.mjs exercises all eye styles on Todd in the
|
|
107
|
-
real editor, shape changes and accessories. appearance-codec.mjs
|
|
108
|
-
validates explicit RGB through the original engine. Untouched presets keep their
|
|
109
|
-
bytes; unnamed original paint is reported from its actual material.
|
|
26
|
+
Current editing supports the beta's original catalog combinations and actual
|
|
27
|
+
availability constraints. appearance-codec.mjs validates explicit RGB and optional eye
|
|
28
|
+
transform edits through the original engine. Untouched presets keep their bytes.
|
|
110
29
|
|
|
111
30
|
legacy-geometry.mjs transforms copies of prepared scene assemblies: existing
|
|
112
31
|
Bloom contours deform the body, pose deltas, normals and fur roots. The packaged
|
|
@@ -120,31 +39,17 @@ diamond and heart recipes reuse the original beta shapes instead of duplicates.
|
|
|
120
39
|
Alien avatars are removed from the visible catalog, with saved-data compatibility. The
|
|
121
40
|
migrated bodies use the original catalog eyes at their authored proportions and
|
|
122
41
|
animations; old expression/eye transform fields no longer alter the 3D face.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
body/part combinations, exact requested labels, unchanged body vertices and
|
|
129
|
-
cache bounds without creating a WebGL context. Intact presets retain authored
|
|
130
|
-
signature reactions. Independent piece edits retain the body's original
|
|
131
|
-
signature. Native shapes use their corresponding authored signature; distinct
|
|
132
|
-
migrated contours and Clippo use Todd's signature as the common default.
|
|
133
|
-
The adapter never substitutes the original Wave/maracas reaction. A pinned,
|
|
134
|
-
validated controller scope borrows only the reaction identity during the original
|
|
135
|
-
native dispatch and restores it immediately; saved appearance and materials
|
|
136
|
-
remain independent. Named bodies also retain their original fitted Work payload.
|
|
42
|
+
Migrated bodies support original eyewear and accessories. Headwear, Bulb, bow
|
|
43
|
+
and Tuft receive rigid contour-relative translations; eyewear and headphones
|
|
44
|
+
keep original placement. A bounded reference cache identifies attachment meshes
|
|
45
|
+
without changing eyes, materials or fur vectors. Intact presets retain authored
|
|
46
|
+
signature reactions; edited and migrated bodies fall back to the original Wave.
|
|
137
47
|
Mascots and hidden faces still use SVG.
|
|
138
48
|
Original material/grain effects become the beta's 3D surface.
|
|
139
49
|
|
|
140
50
|
Browser gates (with Storybook running) are scripts/verify-character-avatars.mjs
|
|
141
|
-
and scripts/verify-legacy-avatars.mjs
|
|
142
|
-
verify-avatar-shared-renderer.mjs for crowd lifetime and actual 24/48-avatar motion.
|
|
143
|
-
verify-avatar-shared-surface.mjs checks atlas pixels, MSAA and failed allocation;
|
|
144
|
-
verify-avatar-shared-programs.mjs and verify-avatar-shared-textures.mjs compare
|
|
145
|
-
actual frame pixels against the original commands and verify independent changes.
|
|
146
|
-
verify-avatar-runtime-errors.mjs injects a GL failure before publication. verify-avatar-deferred-input.mjs forces a delayed GPU fence and checks real mouse capture, reactions, appearance edits, resizing and disposal during that wait. They inspect painted pixels, interaction,
|
|
51
|
+
and scripts/verify-legacy-avatars.mjs. They inspect painted pixels, interaction,
|
|
147
52
|
activity, transitions and resource cleanup, not just preparation callbacks.
|
|
148
53
|
|
|
149
54
|
The optional native bridge uses separate WebViews, which cannot share the web
|
|
150
|
-
engine/context caches.
|
|
55
|
+
engine/context caches. Physical-device validation remains pending.
|
|
@@ -1,429 +1,76 @@
|
|
|
1
|
-
import {
|
|
2
|
-
NATIVE_PARTS,
|
|
3
|
-
ORIGINAL_PRESETS,
|
|
4
|
-
MIGRATED_SHAPE_IDS,
|
|
5
|
-
} from './character-recipe.mjs';
|
|
6
1
|
import createModule from './orbit-characters.mjs';
|
|
7
|
-
import { createControllerModeAdapter } from './controller-mode.mjs';
|
|
8
|
-
import {
|
|
9
|
-
createPreparationCache,
|
|
10
|
-
preparationKey,
|
|
11
|
-
} from './preparation-cache.mjs';
|
|
12
|
-
import { waitForSharedRender } from './shared-surface.mjs';
|
|
13
2
|
|
|
14
|
-
let controller;
|
|
15
3
|
const pool = new Map();
|
|
16
|
-
const authoredFacades = new Map();
|
|
17
4
|
const pending = new Map();
|
|
18
|
-
|
|
19
|
-
const originalScope = Object.freeze({ points: undefined });
|
|
20
|
-
let modulePromise,
|
|
21
|
-
originalFacade,
|
|
22
|
-
currentScope,
|
|
23
|
-
worker,
|
|
5
|
+
let worker,
|
|
24
6
|
idleTimer,
|
|
25
|
-
characters = 0,
|
|
26
7
|
sequence = 0;
|
|
27
|
-
|
|
28
|
-
const dispatchTimers = new Map();
|
|
29
|
-
const preparationQueue = [];
|
|
30
|
-
let activePreparation;
|
|
31
|
-
|
|
32
|
-
function pumpPreparationQueue() {
|
|
33
|
-
if (pending.size || dispatchTimers.size) return;
|
|
34
|
-
if (activePreparation && !activePreparation.released) return;
|
|
35
|
-
activePreparation = undefined;
|
|
36
|
-
const next = preparationQueue.shift();
|
|
37
|
-
if (!next) return;
|
|
38
|
-
next.signal?.removeEventListener('abort', next.abort);
|
|
39
|
-
const lease = { released: false };
|
|
40
|
-
activePreparation = lease;
|
|
41
|
-
next.resolve(() => {
|
|
42
|
-
if (lease.released) return;
|
|
43
|
-
lease.released = true;
|
|
44
|
-
pumpPreparationQueue();
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function scoped(scope, operation) {
|
|
49
|
-
const previous = currentScope;
|
|
50
|
-
const schedule = globalThis.setTimeout;
|
|
51
|
-
const cancel = globalThis.clearTimeout;
|
|
52
|
-
currentScope = scope;
|
|
53
|
-
// Emscripten dispatches preparation asynchronously. Keep the owning scope
|
|
54
|
-
// through its timer, but preserve the engine's timing and callback ordering.
|
|
55
|
-
// The preparation lease prevents other characters from joining that global
|
|
56
|
-
// native queue until this owner's preparation has settled.
|
|
57
|
-
globalThis.setTimeout = function (callback, delay, ...args) {
|
|
58
|
-
const nativeDispatcher =
|
|
59
|
-
typeof callback === 'function' &&
|
|
60
|
-
Number(delay) === 0 &&
|
|
61
|
-
Function.prototype.toString
|
|
62
|
-
.call(callback)
|
|
63
|
-
.includes(
|
|
64
|
-
'safeSetTimeout.mapping[id]=undefined;callUserCallback(func)',
|
|
65
|
-
);
|
|
66
|
-
let handle;
|
|
67
|
-
handle = schedule.call(
|
|
68
|
-
globalThis,
|
|
69
|
-
typeof callback === 'function'
|
|
70
|
-
? (...values) => {
|
|
71
|
-
if (nativeDispatcher) dispatchTimers.delete(handle);
|
|
72
|
-
try {
|
|
73
|
-
return scoped(scope, () => callback(...values));
|
|
74
|
-
} finally {
|
|
75
|
-
pumpPreparationQueue();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
: callback,
|
|
79
|
-
delay,
|
|
80
|
-
...args,
|
|
81
|
-
);
|
|
82
|
-
if (nativeDispatcher) dispatchTimers.set(handle, scope);
|
|
83
|
-
return handle;
|
|
84
|
-
};
|
|
85
|
-
globalThis.clearTimeout = function (handle) {
|
|
86
|
-
dispatchTimers.delete(handle);
|
|
87
|
-
return cancel.call(globalThis, handle);
|
|
88
|
-
};
|
|
89
|
-
try {
|
|
90
|
-
return operation();
|
|
91
|
-
} finally {
|
|
92
|
-
globalThis.setTimeout = schedule;
|
|
93
|
-
globalThis.clearTimeout = cancel;
|
|
94
|
-
currentScope = previous;
|
|
95
|
-
pumpPreparationQueue();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** Fair, cancelable setup lease for the native engine's global prepare queue.
|
|
100
|
-
* Acquire before constructing or changing a Character's geometry. Release
|
|
101
|
-
* after preparation/paint, or dispose/error. A released owner with a pending
|
|
102
|
-
* native callback retains its turn until that callback has completed.
|
|
103
|
-
*/
|
|
104
|
-
export function acquireCharacterPreparation(signal) {
|
|
105
|
-
return new Promise((resolve, reject) => {
|
|
106
|
-
const abort = () => {
|
|
107
|
-
const index = preparationQueue.indexOf(entry);
|
|
108
|
-
if (index >= 0) preparationQueue.splice(index, 1);
|
|
109
|
-
reject(new DOMException('Character preparation aborted', 'AbortError'));
|
|
110
|
-
pumpPreparationQueue();
|
|
111
|
-
};
|
|
112
|
-
const entry = { resolve, reject, signal, abort };
|
|
113
|
-
if (signal?.aborted) {
|
|
114
|
-
abort();
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
signal?.addEventListener('abort', abort, { once: true });
|
|
118
|
-
preparationQueue.push(entry);
|
|
119
|
-
pumpPreparationQueue();
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function stopIdleWorker() {
|
|
124
|
-
clearTimeout(idleTimer);
|
|
125
|
-
if (characters || pool.size || pending.size || dispatchTimers.size) return;
|
|
126
|
-
idleTimer = setTimeout(() => {
|
|
127
|
-
if (!characters && !pool.size && !pending.size && !dispatchTimers.size) {
|
|
128
|
-
worker?.terminate();
|
|
129
|
-
worker = undefined;
|
|
130
|
-
}
|
|
131
|
-
}, 0);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async function finishRequest(id, result, reused = false) {
|
|
135
|
-
const entry = pending.get(id);
|
|
136
|
-
if (!entry || entry.delivering) return;
|
|
137
|
-
entry.delivering = true;
|
|
138
|
-
try {
|
|
139
|
-
await entry.complete(result, reused);
|
|
140
|
-
} finally {
|
|
141
|
-
// Keep the owner's turn while the GPU boundary and native completion are
|
|
142
|
-
// still waiting, even if that owner has already been canceled or deleted.
|
|
143
|
-
pending.delete(id);
|
|
144
|
-
pumpPreparationQueue();
|
|
145
|
-
stopIdleWorker();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
8
|
function preparationWorker() {
|
|
150
|
-
clearTimeout(idleTimer);
|
|
151
9
|
if (worker) return worker;
|
|
152
10
|
worker = new Worker(new URL('./legacy-worker.mjs', import.meta.url), {
|
|
153
11
|
type: 'module',
|
|
154
12
|
});
|
|
155
13
|
worker.onmessage = ({ data }) => {
|
|
156
|
-
|
|
14
|
+
const entry = pending.get(data.id);
|
|
15
|
+
if (!entry) return;
|
|
16
|
+
pending.delete(data.id);
|
|
17
|
+
entry.complete(data);
|
|
157
18
|
};
|
|
158
19
|
worker.onerror = () => {
|
|
159
|
-
const failed = [...pending.
|
|
20
|
+
const failed = [...pending.values()];
|
|
21
|
+
pending.clear();
|
|
160
22
|
worker?.terminate();
|
|
161
23
|
worker = undefined;
|
|
162
|
-
for (const
|
|
163
|
-
|
|
164
|
-
error: '
|
|
24
|
+
for (const entry of failed)
|
|
25
|
+
entry.complete({
|
|
26
|
+
error: 'Legacy character preparation failed',
|
|
165
27
|
milliseconds: 0,
|
|
166
28
|
});
|
|
167
29
|
};
|
|
168
30
|
return worker;
|
|
169
31
|
}
|
|
170
32
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
cacheKey,
|
|
189
|
-
activities,
|
|
190
|
-
) => {
|
|
191
|
-
const scope = currentScope;
|
|
192
|
-
if (!scope) {
|
|
33
|
+
/** Separate geometry caches for different contours; one shared preparation worker.
|
|
34
|
+
* Unused rendering modules are released, never retained in an unbounded catalog.
|
|
35
|
+
*/
|
|
36
|
+
export async function acquireLegacyEngine(points) {
|
|
37
|
+
clearTimeout(idleTimer);
|
|
38
|
+
const key = JSON.stringify(points);
|
|
39
|
+
let entry = pool.get(key);
|
|
40
|
+
if (!entry) {
|
|
41
|
+
entry = { references: 0, module: null };
|
|
42
|
+
entry.module = createModule({
|
|
43
|
+
locateFile: (file) => new URL(file, import.meta.url).href,
|
|
44
|
+
}).then((module) => {
|
|
45
|
+
module.orbitPrepare = (id, appearance, quality, cacheKey, activities) => {
|
|
46
|
+
const request = ++sequence;
|
|
47
|
+
pending.set(request, {
|
|
48
|
+
owner: entry,
|
|
49
|
+
complete: (result) => {
|
|
193
50
|
module.orbitCompletePreparation(
|
|
194
51
|
id,
|
|
195
|
-
null,
|
|
196
|
-
|
|
197
|
-
0,
|
|
52
|
+
result.bytes ?? null,
|
|
53
|
+
result.error || '',
|
|
54
|
+
result.milliseconds || 0,
|
|
198
55
|
);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
try {
|
|
59
|
+
preparationWorker().postMessage({
|
|
60
|
+
id: request,
|
|
203
61
|
appearance,
|
|
204
62
|
quality,
|
|
205
63
|
key: cacheKey,
|
|
206
64
|
activities,
|
|
207
|
-
points
|
|
208
|
-
authoredParts: scope.authoredParts,
|
|
209
|
-
eyeSpacing: scope.authoredParts?.eyeSpacing,
|
|
210
|
-
});
|
|
211
|
-
const complete = async (result, reused = false) => {
|
|
212
|
-
await waitForSharedRender();
|
|
213
|
-
return scoped(scope, () => {
|
|
214
|
-
if (result.bytes && !result.error && !reused)
|
|
215
|
-
prepared.set(cacheKeyExact, result.bytes);
|
|
216
|
-
module.orbitCompletePreparation(
|
|
217
|
-
id,
|
|
218
|
-
result.bytes ?? null,
|
|
219
|
-
result.error || '',
|
|
220
|
-
result.milliseconds || 0,
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
};
|
|
224
|
-
pending.set(request, { complete });
|
|
225
|
-
const cached = prepared.get(cacheKeyExact);
|
|
226
|
-
if (cached) {
|
|
227
|
-
// Preserve asynchronous completion and the owner's preparation
|
|
228
|
-
// turn. Completing inside orbitPrepare would re-enter native
|
|
229
|
-
// dispatch while its job is still being registered.
|
|
230
|
-
queueMicrotask(() => {
|
|
231
|
-
void finishRequest(
|
|
232
|
-
request,
|
|
233
|
-
{ bytes: cached, milliseconds: 0 },
|
|
234
|
-
true,
|
|
235
|
-
);
|
|
236
|
-
});
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
try {
|
|
240
|
-
preparationWorker().postMessage({
|
|
241
|
-
id: request,
|
|
242
|
-
appearance,
|
|
243
|
-
quality,
|
|
244
|
-
key: cacheKey,
|
|
245
|
-
activities,
|
|
246
|
-
points: scope.points,
|
|
247
|
-
authoredParts: scope.authoredParts,
|
|
248
|
-
eyeSpacing: scope.authoredParts?.eyeSpacing,
|
|
249
|
-
});
|
|
250
|
-
} catch (error) {
|
|
251
|
-
void finishRequest(request, {
|
|
252
|
-
error: String(error),
|
|
253
|
-
milliseconds: 0,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
return module;
|
|
258
|
-
})
|
|
259
|
-
.catch((error) => {
|
|
260
|
-
modulePromise = undefined;
|
|
261
|
-
throw error;
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
return modulePromise;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function facade(module, scope) {
|
|
268
|
-
const result = Object.create(module);
|
|
269
|
-
const handles = new WeakMap();
|
|
270
|
-
function wrap(target, activities = false, source) {
|
|
271
|
-
controller.register(target, activities, source);
|
|
272
|
-
const methods = new Map();
|
|
273
|
-
let deleted = false;
|
|
274
|
-
characters++;
|
|
275
|
-
const proxy = new Proxy(target, {
|
|
276
|
-
get(instance, key) {
|
|
277
|
-
const value = Reflect.get(instance, key, instance);
|
|
278
|
-
if (typeof value !== 'function' || key === 'constructor') return value;
|
|
279
|
-
if (!methods.has(key))
|
|
280
|
-
methods.set(key, (...args) => {
|
|
281
|
-
const returned = scoped(scope, () => value.apply(instance, args));
|
|
282
|
-
if (key === 'applyActivity' && returned === 0 && activities)
|
|
283
|
-
controller.markBound(instance);
|
|
284
|
-
if (key === 'delete' && !deleted) {
|
|
285
|
-
controller.unregister(instance);
|
|
286
|
-
deleted = true;
|
|
287
|
-
characters--;
|
|
288
|
-
stopIdleWorker();
|
|
289
|
-
}
|
|
290
|
-
// Embind handle clones retain the same native character and scope.
|
|
291
|
-
if (returned !== instance && returned instanceof module.Character)
|
|
292
|
-
return wrap(returned, activities, instance);
|
|
293
|
-
return returned;
|
|
65
|
+
points,
|
|
294
66
|
});
|
|
295
|
-
|
|
296
|
-
|
|
67
|
+
} catch (error) {
|
|
68
|
+
pending.delete(request);
|
|
69
|
+
module.orbitCompletePreparation(id, null, String(error), 0);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return module;
|
|
297
73
|
});
|
|
298
|
-
handles.set(proxy, target);
|
|
299
|
-
return proxy;
|
|
300
|
-
}
|
|
301
|
-
result.controllerMode = (character, enabled) => {
|
|
302
|
-
const instance = handles.get(character);
|
|
303
|
-
if (!instance)
|
|
304
|
-
throw new Error(
|
|
305
|
-
'Character controller belongs to a different engine scope',
|
|
306
|
-
);
|
|
307
|
-
return scoped(scope, () => controller.controllerMode(instance, enabled));
|
|
308
|
-
};
|
|
309
|
-
result.controllerState = (character) => {
|
|
310
|
-
const instance = handles.get(character);
|
|
311
|
-
if (!instance)
|
|
312
|
-
throw new Error(
|
|
313
|
-
'Character controller belongs to a different engine scope',
|
|
314
|
-
);
|
|
315
|
-
return scoped(scope, () => controller.controllerState(instance));
|
|
316
|
-
};
|
|
317
|
-
result.controllerSignature = (character, preset) => {
|
|
318
|
-
const instance = handles.get(character);
|
|
319
|
-
if (!instance)
|
|
320
|
-
throw new Error(
|
|
321
|
-
'Character controller belongs to a different engine scope',
|
|
322
|
-
);
|
|
323
|
-
return scoped(scope, () =>
|
|
324
|
-
controller.controllerSignature(instance, preset),
|
|
325
|
-
);
|
|
326
|
-
};
|
|
327
|
-
result.controllerWithSignature = (character, preset, operation) => {
|
|
328
|
-
const instance = handles.get(character);
|
|
329
|
-
if (!instance)
|
|
330
|
-
throw new Error(
|
|
331
|
-
'Character controller belongs to a different engine scope',
|
|
332
|
-
);
|
|
333
|
-
return scoped(scope, () =>
|
|
334
|
-
controller.controllerWithSignature(instance, preset, operation),
|
|
335
|
-
);
|
|
336
|
-
};
|
|
337
|
-
result.Character = function Character(...args) {
|
|
338
|
-
clearTimeout(idleTimer);
|
|
339
|
-
return wrap(
|
|
340
|
-
scoped(scope, () => new module.Character(...args)),
|
|
341
|
-
args[3]?.activities,
|
|
342
|
-
);
|
|
343
|
-
};
|
|
344
|
-
result.Character.prototype = module.Character.prototype;
|
|
345
|
-
return result;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/** Original and custom bodies share one WASM instance and preparation worker.
|
|
349
|
-
* Prepared mesh identities distinguish contours inside the shared GPU cache.
|
|
350
|
-
*/
|
|
351
|
-
function normalizeAuthoredParts(value) {
|
|
352
|
-
if (!value || !Object.keys(value).length) return undefined;
|
|
353
|
-
const keys = [
|
|
354
|
-
'bodyPreset',
|
|
355
|
-
'paintBody',
|
|
356
|
-
'shape',
|
|
357
|
-
'eyes',
|
|
358
|
-
'eyewear',
|
|
359
|
-
'accessory',
|
|
360
|
-
'eyeSpacing',
|
|
361
|
-
'faceShape',
|
|
362
|
-
];
|
|
363
|
-
if (
|
|
364
|
-
Object.keys(value).some((key) => !keys.includes(key)) ||
|
|
365
|
-
(value.bodyPreset !== undefined &&
|
|
366
|
-
!ORIGINAL_PRESETS.includes(value.bodyPreset)) ||
|
|
367
|
-
(value.paintBody !== undefined && typeof value.paintBody !== 'boolean') ||
|
|
368
|
-
(value.shape !== undefined && value.shape !== 'clippo') ||
|
|
369
|
-
(value.faceShape !== undefined &&
|
|
370
|
-
![...MIGRATED_SHAPE_IDS, ...NATIVE_PARTS.shape].includes(
|
|
371
|
-
value.faceShape,
|
|
372
|
-
)) ||
|
|
373
|
-
(value.eyes !== undefined &&
|
|
374
|
-
![...NATIVE_PARTS.eyes, 'todd', 'clippo', 'cyclops'].includes(
|
|
375
|
-
value.eyes,
|
|
376
|
-
)) ||
|
|
377
|
-
(value.eyewear !== undefined &&
|
|
378
|
-
!NATIVE_PARTS.eyewear.includes(value.eyewear)) ||
|
|
379
|
-
(value.accessory !== undefined &&
|
|
380
|
-
![...NATIVE_PARTS.accessory, 'felipe_beret'].includes(value.accessory))
|
|
381
|
-
)
|
|
382
|
-
throw new Error('Unsupported authored character part');
|
|
383
|
-
return Object.freeze(
|
|
384
|
-
Object.fromEntries(
|
|
385
|
-
keys
|
|
386
|
-
.filter((key) => value[key] !== undefined && key !== 'eyeSpacing')
|
|
387
|
-
.map((key) => [key, value[key]]),
|
|
388
|
-
),
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
export async function getCharacterEngine(parts) {
|
|
392
|
-
const authoredParts = normalizeAuthoredParts(parts);
|
|
393
|
-
const module = await sharedModule();
|
|
394
|
-
if (!authoredParts) {
|
|
395
|
-
originalFacade ??= facade(module, originalScope);
|
|
396
|
-
return originalFacade;
|
|
397
|
-
}
|
|
398
|
-
// Retain a bounded set of recipe facades; live Characters own their scopes.
|
|
399
|
-
const key = JSON.stringify(authoredParts);
|
|
400
|
-
if (!authoredFacades.has(key))
|
|
401
|
-
authoredFacades.set(
|
|
402
|
-
key,
|
|
403
|
-
facade(module, { points: undefined, authoredParts }),
|
|
404
|
-
);
|
|
405
|
-
const result = authoredFacades.get(key);
|
|
406
|
-
authoredFacades.delete(key);
|
|
407
|
-
authoredFacades.set(key, result);
|
|
408
|
-
if (authoredFacades.size > 64)
|
|
409
|
-
authoredFacades.delete(authoredFacades.keys().next().value);
|
|
410
|
-
return result;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
export async function acquireLegacyEngine(points, parts) {
|
|
414
|
-
clearTimeout(idleTimer);
|
|
415
|
-
const authoredParts = normalizeAuthoredParts(parts);
|
|
416
|
-
const key = JSON.stringify([points, authoredParts]);
|
|
417
|
-
let entry = pool.get(key);
|
|
418
|
-
if (!entry) {
|
|
419
|
-
const scope = {
|
|
420
|
-
points: points.map((point) => point.slice()),
|
|
421
|
-
authoredParts,
|
|
422
|
-
};
|
|
423
|
-
entry = {
|
|
424
|
-
references: 0,
|
|
425
|
-
facade: sharedModule().then((module) => facade(module, scope)),
|
|
426
|
-
};
|
|
427
74
|
pool.set(key, entry);
|
|
428
75
|
}
|
|
429
76
|
entry.references++;
|
|
@@ -431,11 +78,20 @@ export async function acquireLegacyEngine(points, parts) {
|
|
|
431
78
|
const release = () => {
|
|
432
79
|
if (released) return;
|
|
433
80
|
released = true;
|
|
434
|
-
if (--entry.references
|
|
435
|
-
|
|
81
|
+
if (--entry.references !== 0) return;
|
|
82
|
+
pool.delete(key);
|
|
83
|
+
for (const [id, request] of pending)
|
|
84
|
+
if (request.owner === entry) pending.delete(id);
|
|
85
|
+
if (!pool.size)
|
|
86
|
+
idleTimer = setTimeout(() => {
|
|
87
|
+
if (!pool.size) {
|
|
88
|
+
worker?.terminate();
|
|
89
|
+
worker = undefined;
|
|
90
|
+
}
|
|
91
|
+
}, 0);
|
|
436
92
|
};
|
|
437
93
|
try {
|
|
438
|
-
return { module: await entry.
|
|
94
|
+
return { module: await entry.module, release };
|
|
439
95
|
} catch (error) {
|
|
440
96
|
release();
|
|
441
97
|
throw error;
|
|
@@ -443,15 +99,7 @@ export async function acquireLegacyEngine(points, parts) {
|
|
|
443
99
|
}
|
|
444
100
|
|
|
445
101
|
export const legacyEngineStats = () => ({
|
|
446
|
-
// Historical field counts leased contour entries; sharedModules is the
|
|
447
|
-
// actual WASM count, including the instance used by original characters.
|
|
448
102
|
modules: pool.size,
|
|
449
|
-
sharedModules: modulePromise ? 1 : 0,
|
|
450
|
-
characters,
|
|
451
|
-
preparationWaiters: preparationQueue.length,
|
|
452
|
-
preparationActive: !!activePreparation,
|
|
453
|
-
dispatchTimers: dispatchTimers.size,
|
|
454
103
|
pending: pending.size,
|
|
455
104
|
worker: !!worker,
|
|
456
|
-
preparationCache: prepared.stats(),
|
|
457
105
|
});
|