mudra-skills 3.0.2 → 3.0.4

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.
Files changed (146) hide show
  1. package/package.json +1 -1
  2. package/skills/mudra-master/SKILL.md +0 -196
  3. package/skills/mudra-master/mudra-preview/SKILL.md +0 -150
  4. package/skills/mudra-master/mudra-preview/assets/ar-menu.html +0 -382
  5. package/skills/mudra-master/mudra-preview/assets/document-scroller.html +0 -468
  6. package/skills/mudra-master/mudra-preview/assets/drum-machine.html +0 -788
  7. package/skills/mudra-master/mudra-preview/assets/emg-visualizer.html +0 -390
  8. package/skills/mudra-master/mudra-preview/assets/generative-art.html +0 -408
  9. package/skills/mudra-master/mudra-preview/assets/gesture-assistant.html +0 -342
  10. package/skills/mudra-master/mudra-preview/assets/gesture-speech.html +0 -444
  11. package/skills/mudra-master/mudra-preview/assets/hands-free-desktop.html +0 -376
  12. package/skills/mudra-master/mudra-preview/assets/model-rotator.html +0 -365
  13. package/skills/mudra-master/mudra-preview/assets/mudra-duel.html +0 -3200
  14. package/skills/mudra-master/mudra-preview/assets/mudra-monitor.html +0 -1451
  15. package/skills/mudra-master/mudra-preview/assets/mudra-ultimate-template.html +0 -891
  16. package/skills/mudra-master/mudra-preview/assets/music-sequencer.html +0 -455
  17. package/skills/mudra-master/mudra-preview/assets/neural-pong.html +0 -380
  18. package/skills/mudra-master/mudra-preview/assets/neural-snake.html +0 -364
  19. package/skills/mudra-master/mudra-preview/assets/presentation-controller.html +0 -345
  20. package/skills/mudra-master/mudra-preview/assets/pressure-painter.html +0 -285
  21. package/skills/mudra-master/mudra-preview/assets/runner.html +0 -1812
  22. package/skills/mudra-master/mudra-preview/assets/smart-home.html +0 -461
  23. package/skills/mudra-master/mudra-preview/assets/space-invaders.html +0 -1154
  24. package/skills/mudra-master/mudra-preview/assets/waterful-ring-toss.html +0 -1624
  25. package/skills/mudra-master/mudra-preview/references/agent_protocol.json +0 -634
  26. package/skills/mudra-master/mudra-preview/references/prompt.md +0 -16746
  27. package/skills/mudra-master/mudra-xr/SKILL.md +0 -245
  28. package/skills/mudra-master/mudra-xr/assets/demos/3dgs-walkthrough.html +0 -242
  29. package/skills/mudra-master/mudra-xr/assets/demos/aisimulator.html +0 -792
  30. package/skills/mudra-master/mudra-xr/assets/demos/balloonpop.html +0 -422
  31. package/skills/mudra-master/mudra-xr/assets/demos/ballpit.html +0 -284
  32. package/skills/mudra-master/mudra-xr/assets/demos/drone.html +0 -41
  33. package/skills/mudra-master/mudra-xr/assets/demos/gemini-icebreakers.html +0 -338
  34. package/skills/mudra-master/mudra-xr/assets/demos/gemini-xrobject.html +0 -302
  35. package/skills/mudra-master/mudra-xr/assets/demos/math3d.html +0 -188
  36. package/skills/mudra-master/mudra-xr/assets/demos/measure.html +0 -247
  37. package/skills/mudra-master/mudra-xr/assets/demos/occlusion.html +0 -251
  38. package/skills/mudra-master/mudra-xr/assets/demos/rain.html +0 -498
  39. package/skills/mudra-master/mudra-xr/assets/demos/screenwiper.html +0 -432
  40. package/skills/mudra-master/mudra-xr/assets/demos/splash.html +0 -519
  41. package/skills/mudra-master/mudra-xr/assets/demos/webcam_gestures.html +0 -253
  42. package/skills/mudra-master/mudra-xr/assets/demos/xremoji.html +0 -833
  43. package/skills/mudra-master/mudra-xr/assets/demos/xrpoet.html +0 -151
  44. package/skills/mudra-master/mudra-xr/assets/samples/depthmap.html +0 -266
  45. package/skills/mudra-master/mudra-xr/assets/samples/depthmesh.html +0 -100
  46. package/skills/mudra-master/mudra-xr/assets/samples/game_rps.html +0 -1099
  47. package/skills/mudra-master/mudra-xr/assets/samples/gestures_custom.html +0 -467
  48. package/skills/mudra-master/mudra-xr/assets/samples/gestures_heuristic.html +0 -256
  49. package/skills/mudra-master/mudra-xr/assets/samples/lighting.html +0 -163
  50. package/skills/mudra-master/mudra-xr/assets/samples/mesh_detection.html +0 -46
  51. package/skills/mudra-master/mudra-xr/assets/samples/modelviewer.html +0 -183
  52. package/skills/mudra-master/mudra-xr/assets/samples/paint.html +0 -133
  53. package/skills/mudra-master/mudra-xr/assets/samples/planar-vst.html +0 -45
  54. package/skills/mudra-master/mudra-xr/assets/samples/reticle.html +0 -95
  55. package/skills/mudra-master/mudra-xr/assets/samples/skybox_agent.html +0 -384
  56. package/skills/mudra-master/mudra-xr/assets/samples/sound.html +0 -390
  57. package/skills/mudra-master/mudra-xr/assets/samples/ui.html +0 -496
  58. package/skills/mudra-master/mudra-xr/assets/samples/virtual-screens.html +0 -808
  59. package/skills/mudra-master/mudra-xr/assets/templates/0_basic.html +0 -64
  60. package/skills/mudra-master/mudra-xr/assets/templates/1_ui.html +0 -107
  61. package/skills/mudra-master/mudra-xr/assets/templates/2_hands.html +0 -183
  62. package/skills/mudra-master/mudra-xr/assets/templates/3_depth.html +0 -89
  63. package/skills/mudra-master/mudra-xr/assets/templates/4_stereo.html +0 -84
  64. package/skills/mudra-master/mudra-xr/assets/templates/5_camera.html +0 -117
  65. package/skills/mudra-master/mudra-xr/assets/templates/6_ai.html +0 -154
  66. package/skills/mudra-master/mudra-xr/assets/templates/7_ai_live.html +0 -253
  67. package/skills/mudra-master/mudra-xr/assets/templates/8_objects.html +0 -95
  68. package/skills/mudra-master/mudra-xr/assets/templates/9_xr-toggle.html +0 -90
  69. package/skills/mudra-master/mudra-xr/assets/templates/heuristic_hand_gestures.html +0 -102
  70. package/skills/mudra-master/mudra-xr/assets/templates/meshes.html +0 -47
  71. package/skills/mudra-master/mudra-xr/assets/templates/planes.html +0 -47
  72. package/skills/mudra-master/mudra-xr/assets/templates/uikit.html +0 -187
  73. package/skills/mudra-master/mudra-xr/references/agent_protocol.json +0 -865
  74. package/skills/mudra-master/mudra-xr/references/prompt.md +0 -1605
  75. package/skills/mudra-preview/SKILL.md +0 -159
  76. package/skills/mudra-preview/assets/ar-menu.html +0 -382
  77. package/skills/mudra-preview/assets/document-scroller.html +0 -468
  78. package/skills/mudra-preview/assets/drum-machine.html +0 -788
  79. package/skills/mudra-preview/assets/emg-visualizer.html +0 -390
  80. package/skills/mudra-preview/assets/generative-art.html +0 -408
  81. package/skills/mudra-preview/assets/gesture-assistant.html +0 -342
  82. package/skills/mudra-preview/assets/gesture-speech.html +0 -444
  83. package/skills/mudra-preview/assets/hands-free-desktop.html +0 -376
  84. package/skills/mudra-preview/assets/model-rotator.html +0 -365
  85. package/skills/mudra-preview/assets/mudra-duel.html +0 -3200
  86. package/skills/mudra-preview/assets/mudra-monitor.html +0 -1451
  87. package/skills/mudra-preview/assets/mudra-ultimate-template.html +0 -997
  88. package/skills/mudra-preview/assets/music-sequencer.html +0 -455
  89. package/skills/mudra-preview/assets/neural-pong.html +0 -380
  90. package/skills/mudra-preview/assets/neural-snake.html +0 -364
  91. package/skills/mudra-preview/assets/presentation-controller.html +0 -345
  92. package/skills/mudra-preview/assets/pressure-painter.html +0 -285
  93. package/skills/mudra-preview/assets/runner.html +0 -1812
  94. package/skills/mudra-preview/assets/smart-home.html +0 -461
  95. package/skills/mudra-preview/assets/space-invaders.html +0 -1154
  96. package/skills/mudra-preview/assets/waterful-ring-toss.html +0 -1624
  97. package/skills/mudra-preview/references/agent_protocol.json +0 -701
  98. package/skills/mudra-preview/references/prompt.md +0 -16731
  99. package/skills/mudra-xr/SKILL.md +0 -245
  100. package/skills/mudra-xr/assets/demos/3dgs-walkthrough.html +0 -242
  101. package/skills/mudra-xr/assets/demos/aisimulator.html +0 -792
  102. package/skills/mudra-xr/assets/demos/balloonpop.html +0 -422
  103. package/skills/mudra-xr/assets/demos/ballpit.html +0 -284
  104. package/skills/mudra-xr/assets/demos/drone.html +0 -41
  105. package/skills/mudra-xr/assets/demos/gemini-icebreakers.html +0 -338
  106. package/skills/mudra-xr/assets/demos/gemini-xrobject.html +0 -302
  107. package/skills/mudra-xr/assets/demos/math3d.html +0 -188
  108. package/skills/mudra-xr/assets/demos/measure.html +0 -247
  109. package/skills/mudra-xr/assets/demos/occlusion.html +0 -251
  110. package/skills/mudra-xr/assets/demos/rain.html +0 -498
  111. package/skills/mudra-xr/assets/demos/screenwiper.html +0 -432
  112. package/skills/mudra-xr/assets/demos/splash.html +0 -519
  113. package/skills/mudra-xr/assets/demos/webcam_gestures.html +0 -253
  114. package/skills/mudra-xr/assets/demos/xremoji.html +0 -833
  115. package/skills/mudra-xr/assets/demos/xrpoet.html +0 -151
  116. package/skills/mudra-xr/assets/samples/depthmap.html +0 -266
  117. package/skills/mudra-xr/assets/samples/depthmesh.html +0 -100
  118. package/skills/mudra-xr/assets/samples/game_rps.html +0 -1099
  119. package/skills/mudra-xr/assets/samples/gestures_custom.html +0 -467
  120. package/skills/mudra-xr/assets/samples/gestures_heuristic.html +0 -256
  121. package/skills/mudra-xr/assets/samples/lighting.html +0 -163
  122. package/skills/mudra-xr/assets/samples/mesh_detection.html +0 -46
  123. package/skills/mudra-xr/assets/samples/modelviewer.html +0 -183
  124. package/skills/mudra-xr/assets/samples/paint.html +0 -133
  125. package/skills/mudra-xr/assets/samples/planar-vst.html +0 -45
  126. package/skills/mudra-xr/assets/samples/reticle.html +0 -95
  127. package/skills/mudra-xr/assets/samples/skybox_agent.html +0 -384
  128. package/skills/mudra-xr/assets/samples/sound.html +0 -390
  129. package/skills/mudra-xr/assets/samples/ui.html +0 -496
  130. package/skills/mudra-xr/assets/samples/virtual-screens.html +0 -808
  131. package/skills/mudra-xr/assets/templates/0_basic.html +0 -64
  132. package/skills/mudra-xr/assets/templates/1_ui.html +0 -107
  133. package/skills/mudra-xr/assets/templates/2_hands.html +0 -183
  134. package/skills/mudra-xr/assets/templates/3_depth.html +0 -89
  135. package/skills/mudra-xr/assets/templates/4_stereo.html +0 -84
  136. package/skills/mudra-xr/assets/templates/5_camera.html +0 -117
  137. package/skills/mudra-xr/assets/templates/6_ai.html +0 -154
  138. package/skills/mudra-xr/assets/templates/7_ai_live.html +0 -253
  139. package/skills/mudra-xr/assets/templates/8_objects.html +0 -95
  140. package/skills/mudra-xr/assets/templates/9_xr-toggle.html +0 -90
  141. package/skills/mudra-xr/assets/templates/heuristic_hand_gestures.html +0 -102
  142. package/skills/mudra-xr/assets/templates/meshes.html +0 -47
  143. package/skills/mudra-xr/assets/templates/planes.html +0 -47
  144. package/skills/mudra-xr/assets/templates/uikit.html +0 -187
  145. package/skills/mudra-xr/references/agent_protocol.json +0 -865
  146. package/skills/mudra-xr/references/prompt.md +0 -1605
@@ -1,245 +0,0 @@
1
- ---
2
- name: mudra-xr
3
- version: 3.0.0
4
- description: Generate a single-file Mudra-controlled 3D/XR app using XR Blocks. Use when the user describes a 3D, XR, VR, or AR experience controlled by the Mudra Band.
5
- ---
6
-
7
- # Mudra XR Skill
8
-
9
- Generate a complete, working single-file HTML 3D/XR app controlled by Mudra Band signals.
10
- The output runs in any modern Chromium browser — no build step, no server, no headset required.
11
-
12
- **Mandatory feature:** Every generated app MUST include a
13
- Manual/Mudra **Mode toggle** as defined in `references/promt.md`
14
- § Section 15 "Mode Toggle (Manual / Mudra) — Required". Manual is the
15
- default; Mudra opens a single WebSocket lazily and disables the
16
- simulator panel so signals come only from the band.
17
-
18
- **Mandatory feature:** Connection state MUST reflect the
19
- **band**, not the WebSocket. The Companion service accepts socket
20
- connections even when no band is paired, so flipping to "Connected" on
21
- `ws.onopen` is a lie. Every generated app MUST send
22
- `{command:"get_status"}` on open and poll it every 2 s while in Mudra
23
- mode, and only show "Connected" when the response has
24
- `data.device.state === "connected"`. See `references/promt.md`
25
- § "Disconnect detection — band state via `get_status` polling (mandatory)".
26
-
27
- **No disconnect overlay:** Do **not** render a "Band disconnected"
28
- overlay, toast, or any other separate disconnect alert. Connection
29
- state is communicated **only** through the existing connection-status
30
- pill (`Manual` / `Connecting…` / `Connected` / `Disconnected`).
31
-
32
- **Branding:** The footer/badge text MUST be exactly
33
- **"Created by Mudra"** — never "Created with Mudra Studio",
34
- "Powered by Mudra", or any other variant. See § Section 16.
35
-
36
- **Simulator panel buttons must be contextual.** Render only the
37
- sub-actions the app actually handles. If the app maps `nav_direction` to
38
- Up/Down only, omit Left/Right/Roll L/Roll R. If `gesture` only handles
39
- `tap`, omit Twist/2Twist/2Tap. See § Section 5.
40
-
41
- The canonical protocol rules are in `references/prompt.md` Section 1 (signals, commands, error frames) and Section 15 (state machine, hand chip). See also `specs/001-mudra-xr-connection-update/contracts/websocket-protocol.md` for the wire-protocol contract.
42
-
43
- ## Invocation
44
-
45
- This skill activates when the user:
46
- - Explicitly runs `/mudra-xr <prompt>`
47
- - Describes a 3D, XR, VR, or AR experience involving the Mudra Band
48
- - Uses trigger phrases: "3D with Mudra", "XR Mudra app", "WebXR + Mudra",
49
- "Mudra in VR / AR", "XR Blocks + band", or close paraphrases
50
- - Mentions depth, stereo, hand tracking, or spatial context alongside Mudra
51
-
52
- Prefer this skill over `mudra-preview` (2D) when the prompt mentions 3D, XR, VR, AR,
53
- a headset, depth, stereo, or spatial hand tracking.
54
-
55
- ## Steps
56
-
57
- ### 1. Read build rules
58
-
59
- Read the complete `references/promt.md` from the skill base directory.
60
- That file is the source of truth for signal protocol, dependency pins, MudraClient
61
- implementation, simulator panel, keyboard shortcuts, pre-write checklist, and binding patterns.
62
- Follow every rule in it.
63
-
64
- ### 2. Parse input
65
-
66
- Extract from the user's prompt:
67
- - **`templateOverride`**: an inline `[template=<id>]` tag (e.g., `[template=2_hands]`)
68
- - **`motionModeHint`**: an inline `[mode=pointer|direction|imu]` tag
69
-
70
- If neither tag is present, infer them from the prompt language (Step 3).
71
-
72
- ### 3. Infer Mudra signals
73
-
74
- Map the user's intent to the required Mudra signals using the Signal Inference Reference
75
- in `references/promt.md`. Enforce all grouping rules (Section 8 of promt.md):
76
-
77
- - Discrete actions → `gesture` OR `button` (never both gesture+pressure)
78
- - Analog control → `pressure` OR `button` (never both gesture+pressure)
79
- - Continuous directional movement → `navigation` + `button` (Pointer mode)
80
- - Discrete directional swipes → `nav_direction` (Direction mode)
81
- - Tilt / orientation / biometrics → `imu_acc` + `imu_gyro` + `snc` (always all three together — IMU+Biometric bundle)
82
-
83
- **Critical grouping rules:**
84
- 1. `gesture` and `pressure` are mutually exclusive — pick one.
85
- 2. `navigation` and `nav_direction` are mutually exclusive — pick one.
86
- 3. The IMU+Biometric bundle (`imu_acc` + `imu_gyro` + `snc`) cannot combine with `navigation` or `nav_direction`.
87
- 4. `imu_acc`, `imu_gyro`, and `snc` are always subscribed together — using any one requires all three.
88
- 5. **Tap exclusivity** (within `gesture`): use `tap` OR `double_tap` —
89
- **never both together** unless the user explicitly names both. `tap` is
90
- the default; `double_tap` is only used when the user explicitly requests
91
- it by name. When two distinct gesture actions are needed (e.g., forward +
92
- backward), pair `tap` with `twist` — not with `double_tap`. Generic
93
- synonyms ("tap", "click", "press") → `tap`.
94
-
95
- If the prompt maps to two incompatible groups, ask one disambiguation question — do not
96
- auto-pick silently. If no motion mode is needed, use mode = none.
97
-
98
- ### 4. Pick motion mode
99
-
100
- Exactly one of: `pointer`, `direction`, `imu`, or `none`.
101
- If `motionModeHint` is present, use it. If the inference step above is unambiguous, use that.
102
- Default to `direction` if there is motion-language in the prompt but no clear winner.
103
-
104
- ### 5. Select seed template
105
-
106
- **If `templateOverride` is present**: use the named template directly.
107
- Resolve the id against the selection table in Section 12 of `references/promt.md`.
108
- If the id does not match any row, reject with:
109
- ```
110
- Unknown template id: "<id>". Valid ids: 0_basic, 1_ui, 2_hands, 3_depth, 4_stereo,
111
- 5_camera, 6_ai, 7_ai_live, 8_objects, 9_xr-toggle, heuristic_hand_gestures, meshes,
112
- planes, uikit, depthmap, depthmesh, game_rps, gestures_custom, gestures_heuristic,
113
- lighting, mesh_detection, modelviewer, paint, planar-vst, reticle, skybox_agent,
114
- sound, ui, virtual-screens, 3dgs-walkthrough, aisimulator, balloonpop, ballpit,
115
- drone, gemini-icebreakers, gemini-xrobject, math3d, measure, occlusion, rain,
116
- screenwiper, splash, webcam_gestures, xremoji, xrpoet
117
- ```
118
-
119
- **Keyword-based selection (no override)**:
120
-
121
- Score every row in Section 12's table against the user's prompt using this algorithm:
122
-
123
- 1. **Signal overlap** (+3 per matching subscribed signal name found in `keywords`)
124
- 2. **Motion mode match** (+5 if inferred motion mode is in `motionModesSupported`, +2 if `"none"` is in `motionModesSupported`)
125
- 3. **XR feature match** (+2 per matching XR feature keyword from the prompt in `xrFeatures`)
126
- 4. **Keyword overlap** (+1 per keyword from the `keywords` array that appears in the lowercased prompt)
127
-
128
- Pick the highest-scoring row. Ties resolved by:
129
- 1. Prefer `direction` motion mode over others (most app-agnostic)
130
- 2. Prefer templates over samples, samples over demos (simpler baseline)
131
- 3. If still tied, pick `0_basic` as the universal fallback
132
-
133
- **Examples**:
134
- - Prompt with "hands" + "gesture" + no motion mode → `2_hands` or `heuristic_hand_gestures`
135
- - Prompt with "ui" + "panel" + "button" → `1_ui` or `uikit`
136
- - Prompt with "depth" → `3_depth` or `depthmap`
137
- - Prompt with "ai" + "gemini" + "photo" → `6_ai`
138
- - No clear match → `0_basic` (universal fallback)
139
-
140
- ### 5b. Background — locked to XR Blocks default
141
-
142
- **Forbidden:** custom backgrounds. Every generated app uses the XR Blocks
143
- default room and nothing else. There is no catalog, no `applyBackground_*`
144
- helper, no `[bg=...]` override, no `scenePath` override.
145
-
146
- Rules — apply unconditionally:
147
-
148
- 1. Do NOT add any `applyBackground_*` method to the `xb.Script` subclass.
149
- 2. Do NOT call any background helper from `init()`. `init()` starts with
150
- scene content (lights, meshes, Mudra wiring).
151
- 3. Do NOT set `options.simulator.scenePath` (neither to `null` nor to a path).
152
- Leave it alone — XR Blocks renders its default room.
153
- 4. Ignore the prompt's vibe, theme, or mood. Phrases like "in space",
154
- "starfield", "sunset sky", "cyberpunk vibe", "with a forest backdrop",
155
- "[bg=...]" — all are ignored for background purposes. They may still
156
- inform template / motion-mode selection, but NEVER a custom background.
157
-
158
- If a user explicitly insists on a custom background, decline politely and
159
- remind them that the skill is locked to the XR Blocks default room.
160
-
161
- ### 6. Adapt the template with Mudra bindings
162
-
163
- Starting from the seed template HTML:
164
- 1. Add the `MudraClient` class (Section 4 of promt.md, with the Section 15
165
- extensions: no auto-connect; `setMode()`-driven; passive mock; 2 s
166
- `get_status` poll in Mudra mode) verbatim inside the `<script type="module">`.
167
- 2. Instantiate `mudra` at module scope. Do NOT auto-connect — Manual is the default.
168
- 3. **No background helper.** Do NOT add any `applyBackground_*` method.
169
- 4. **No background call from `init()`.** `init()` starts with lights,
170
- meshes, and Mudra wiring — never a background helper.
171
- 4a. **No `scenePath` override.** Do NOT set `options.simulator.scenePath`.
172
- XR Blocks renders its default room — this is the only allowed environment.
173
- 5. Call `mudra.subscribe('<signal>')` for every required signal inside `init()`.
174
- 6. Wire `mudra.on('<signal>', handler)` for each subscribed signal using the binding
175
- patterns from Section 11 of promt.md.
176
- 7. Add the **Mode toggle** `<div id="mode-toggle">` (Section 15) with
177
- **Manual** + **Mudra** buttons. Manual is the default. Wire both
178
- buttons to atomically switch via `mudra.setMode(...)`.
179
- 8. Add the simulator panel `<div id="mudra-sim">` (Section 5) with one
180
- button group **only for the sub-actions actually handled by the app**
181
- (e.g., omit `Roll L`/`Roll R` if `nav_direction` only handles
182
- Up/Down; omit `Twist`/`2Twist` if `gesture` only handles `tap`). The
183
- panel is greyed and `pointer-events: none` while in Mudra mode.
184
- 9. Add the status indicator `<div id="mudra-status">` (Section 15)
185
- wired to `mudra.on('_status', …)` with the four states `Manual` /
186
- `Connecting…` / `Connected` / `Disconnected`. **Never render a
187
- separate disconnect overlay/banner/toast.**
188
- 10. Add the keyboard handler `window.addEventListener('keydown', …, { capture: true })`
189
- (Section 6) for every subscribed signal.
190
- 11. Add the footer badge `<div id="mudra-badge">` (Section 16) with the
191
- literal text **`Created by Mudra`** — no variants.
192
- 12. Remove import-map entries for dependencies the adapted app does not use.
193
- 13. **If the app uses AI** (Gemini / LLM): apply Section 9 + Section 18:
194
- - Add the AI-Setup fragment (`<div class="mudra-onb__ai">`) and its
195
- CSS into the onboarding modal block (Section 9).
196
- - Extend the onboarding IIFE with the gating snippet that disables
197
- `Got it` until the input matches `/^AIza[\w-]{30,}$/` and writes
198
- the validated key to `sessionStorage` under `mudra.gemini.apiKey`.
199
- - Block `Escape`, `×`, and backdrop dismissal while the key is
200
- missing.
201
- - In the `xb.Script` subclass, read the key once via
202
- `sessionStorage.getItem('mudra.gemini.apiKey')`. If `null`,
203
- render `Set up AI in the welcome panel` in the response slot and
204
- never call Gemini.
205
- - Render visible chat I/O per Section 18: a fixed bespoke
206
- one-sentence **Purpose** line, the user input echo, the AI
207
- response (`xb.ScrollingTroikaTextView` or equivalent), and a
208
- Listening/Thinking indicator. TTS is optional; visible text is
209
- mandatory.
210
- - Author the Purpose line from the user's original prompt — never
211
- a placeholder like "AI Chat".
212
-
213
- ### 7. Run the pre-write checklist
214
-
215
- Verify all 10 items from Section 10 of promt.md before writing.
216
- If any item fails: regenerate once and re-check.
217
- If the second attempt also fails: surface the failing items to the user; do not write.
218
-
219
- ### 8. Write the output file
220
-
221
- Target path: `preview/<concept-name>.html` (short kebab-case derived from the concept).
222
- If that file exists: try `preview/<concept-name>-2.html`, then `-3.html`, etc.
223
- Never overwrite. Create `preview/` if it does not exist.
224
-
225
- ### 9. Report
226
-
227
- Print the absolute path to the written file and a one-line summary:
228
- - Template used
229
- - Motion mode
230
- - Subscribed signals
231
-
232
- ## Quick reference
233
-
234
- - WebSocket endpoint: `ws://127.0.0.1:8766`
235
- - Always use `MudraClient` — never raw `new WebSocket(...)`
236
- - Subscribe one signal per command: `{ command: 'subscribe', signal: '<name>' }`
237
- - Motion modes are mutually exclusive: Pointer (`navigation`+`button`) / Direction (`nav_direction`) / IMU+Biometric (`imu_acc`+`imu_gyro`+`snc`)
238
- - IMU+Biometric bundle: `imu_acc`, `imu_gyro`, `snc` always subscribed together — never partially
239
- - `gesture` and `pressure` are mutually exclusive — never combine them
240
- - Free-combining signals (one or the other, not both): `gesture` OR `pressure`, plus `button`
241
- - **Navigation sensitivity is gentle by default**: sim button + keyboard `I`/`J`/`K`/`L` emit `±3` per event; cursor multiplier on inbound `delta_x`/`delta_y` is `0.002`. Raise only when the prompt explicitly asks for fast/snappy movement. See Section 6 + Section 11 of `references/promt.md`.
242
- - **Reserved for XR Blocks desktop simulator** — Mudra never claims these: `W`/`A`/`S`/`D` and arrow keys (camera walk), `Q`/`E` (roll/vertical), `R` (reset), right-click drag (orbit), mouse wheel (zoom). Mudra navigation uses `I`/`J`/`K`/`L`; Mudra IMU uses `U`/`O`/`M`/`N`. See Section 6 of `references/promt.md`.
243
- - Keyboard handlers: `{ capture: true }` + `stopPropagation()` on Mudra-claimed keys
244
- - Import map: exact pinned versions only — no `@latest`
245
- - Output: one `.html` file in `preview/`, zero external local references
@@ -1,242 +0,0 @@
1
- <!doctype html>
2
- <!-- reference: demos/3dgs-walkthrough -->
3
- <html lang="en">
4
- <head>
5
- <title>3DGS Scene Walkthrough</title>
6
-
7
- <meta
8
- name="viewport"
9
- content="width=device-width, initial-scale=1.0, user-scalable=no"
10
- />
11
- <link type="text/css" rel="stylesheet" href="https://xrblocks.github.io/css/xr.css" />
12
- <script>
13
- window.litDisableBundleWarning = true;
14
- </script>
15
- <script type="importmap">
16
- {
17
- "imports": {
18
- "three": "https://cdn.jsdelivr.net/npm/three@0.182.0/build/three.module.js",
19
- "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.182.0/examples/jsm/",
20
- "@sparkjsdev/spark": "https://sparkjs.dev/releases/spark/0.1.10/spark.module.js",
21
- "xrblocks": "https://cdn.jsdelivr.net/npm/xrblocks@0.11.0/build/xrblocks.js",
22
- "xrblocks/addons/": "https://cdn.jsdelivr.net/npm/xrblocks@0.11.0/build/addons/"
23
- }
24
- }
25
- </script>
26
- </head>
27
-
28
- <body>
29
- <script type="module">
30
- import {LongSelectHandler} from 'xrblocks/addons/ui/LongSelectHandler.js';
31
-
32
- import {SplatMesh, SparkRenderer} from '@sparkjsdev/spark';
33
- import * as THREE from 'three';
34
- import * as xb from 'xrblocks';
35
-
36
- const PROPRIETARY_ASSETS_BASE_URL =
37
- 'https://cdn.jsdelivr.net/gh/xrblocks/proprietary-assets@main/';
38
-
39
- const SPLAT_ASSETS = [
40
- {
41
- url: PROPRIETARY_ASSETS_BASE_URL + '3dgs_scenes/nyc.spz',
42
- scale: new THREE.Vector3(1.3, 1.3, 1.3),
43
- position: new THREE.Vector3(0, -0.15, 0),
44
- quaternion: new THREE.Quaternion(1, 0, 0, 0),
45
- },
46
- {
47
- url: PROPRIETARY_ASSETS_BASE_URL + '3dgs_scenes/alameda.spz',
48
- scale: new THREE.Vector3(1.3, 1.3, 1.3),
49
- position: new THREE.Vector3(0, 0, 0),
50
- quaternion: new THREE.Quaternion(1, 0, 0, 0),
51
- },
52
- ];
53
-
54
- const FADE_DURATION_S = 1.0; // seconds
55
- const MOVE_SPEED = 0.05;
56
-
57
- function easeInOutSine(x) {
58
- return -(Math.cos(Math.PI * x) - 1) / 2;
59
- }
60
-
61
- const forward = new THREE.Vector3();
62
- const right = new THREE.Vector3();
63
- const moveDirection = new THREE.Vector3();
64
-
65
- /**
66
- * An XR-Blocks demo that displays room-scale 3DGS models, allowing smooth
67
- * transitions via number keys (1, 2) or a 1.5 s long-pinch.
68
- */
69
- class WalkthroughManager extends xb.Script {
70
- async init() {
71
- this.add(new THREE.HemisphereLight(0xffffff, 0x666666, 3));
72
-
73
- // Load all splat meshes in parallel.
74
- this.splatMeshes = await Promise.all(
75
- SPLAT_ASSETS.map(async (asset) => {
76
- const mesh = new SplatMesh({url: asset.url});
77
- await mesh.initialized;
78
- mesh.position.copy(asset.position);
79
- mesh.quaternion.copy(asset.quaternion);
80
- mesh.scale.copy(asset.scale);
81
- return mesh;
82
- })
83
- );
84
-
85
- // Create a SparkRenderer for gaussian splat rendering and register it so
86
- // the simulator can toggle encodeLinear for correct color space.
87
- const sparkRenderer = new SparkRenderer({
88
- renderer: xb.core.renderer,
89
- maxStdDev: Math.sqrt(5),
90
- });
91
- xb.core.registry.register(new xb.SparkRendererHolder(sparkRenderer));
92
- xb.add(sparkRenderer);
93
-
94
- // Show the first splat.
95
- this.currentIndex = 0;
96
- xb.add(this.splatMeshes[this.currentIndex]);
97
-
98
- // fadeProgress tracks animation time: null = idle, 0‥FADE_DURATION_S =
99
- // fading out, FADE_DURATION_S‥2×FADE_DURATION_S = fading in.
100
- this.fadeProgress = null;
101
- this.nextIndex = null;
102
-
103
- // Locomotion state.
104
- this.locomotionOffset = new THREE.Vector3();
105
- this.baseReferenceSpace = null;
106
- this.keys = {w: false, a: false, s: false, d: false};
107
-
108
- document.addEventListener('keydown', this.onKeyDown.bind(this));
109
- document.addEventListener('keyup', this.onKeyUp.bind(this));
110
-
111
- xb.add(
112
- new LongSelectHandler(this.cycleSplat.bind(this), {
113
- triggerDelay: 1500,
114
- triggerCooldownDuration: 1500,
115
- })
116
- );
117
- }
118
-
119
- /** Starts a crossfade to the next splat (wrapping around). */
120
- cycleSplat() {
121
- if (this.fadeProgress !== null) return;
122
- this.nextIndex = (this.currentIndex + 1) % this.splatMeshes.length;
123
- this.fadeProgress = 0;
124
- }
125
-
126
- onKeyDown(event) {
127
- const key = event.key.toLowerCase();
128
- if (key in this.keys) this.keys[key] = true;
129
-
130
- // Number key → jump to that splat (1-indexed).
131
- const idx = parseInt(key, 10) - 1;
132
- if (
133
- idx >= 0 &&
134
- idx < this.splatMeshes.length &&
135
- idx !== this.currentIndex &&
136
- this.fadeProgress === null
137
- ) {
138
- this.nextIndex = idx;
139
- this.fadeProgress = 0;
140
- }
141
- }
142
-
143
- onKeyUp(event) {
144
- const key = event.key.toLowerCase();
145
- if (key in this.keys) this.keys[key] = false;
146
- }
147
-
148
- onXRSessionEnded() {
149
- super.onXRSessionEnded();
150
- this.baseReferenceSpace = null;
151
- this.locomotionOffset.set(0, 0, 0);
152
- }
153
-
154
- update() {
155
- super.update();
156
- const dt = xb.getDeltaTime();
157
-
158
- this.updateFade(dt);
159
- this.updateLocomotion();
160
- }
161
-
162
- /** Handles the fade-out → fade-in crossfade between splats. */
163
- updateFade(dt) {
164
- if (this.fadeProgress === null) return;
165
-
166
- this.fadeProgress += dt;
167
- const currentMesh = this.splatMeshes[this.currentIndex];
168
-
169
- if (this.fadeProgress < FADE_DURATION_S) {
170
- // Fading out the current splat.
171
- currentMesh.opacity =
172
- 1 - easeInOutSine(this.fadeProgress / FADE_DURATION_S);
173
- } else if (this.fadeProgress < 2 * FADE_DURATION_S) {
174
- // Swap on the first frame of the fade-in phase.
175
- if (currentMesh.parent) {
176
- xb.scene.remove(currentMesh);
177
- this.currentIndex = this.nextIndex;
178
- const nextMesh = this.splatMeshes[this.currentIndex];
179
- nextMesh.opacity = 0;
180
- xb.add(nextMesh);
181
- }
182
- // Fading in the new splat.
183
- const inProgress =
184
- (this.fadeProgress - FADE_DURATION_S) / FADE_DURATION_S;
185
- this.splatMeshes[this.currentIndex].opacity = easeInOutSine(inProgress);
186
- } else {
187
- // Fade complete.
188
- this.splatMeshes[this.currentIndex].opacity = 1;
189
- this.fadeProgress = null;
190
- this.nextIndex = null;
191
- }
192
- }
193
-
194
- /** WASD locomotion via XR reference space offset. */
195
- updateLocomotion() {
196
- const xr = xb.core.renderer?.xr;
197
- if (!xr?.isPresenting) return;
198
-
199
- const camera = xr.getCamera();
200
- if (!camera) return;
201
-
202
- camera.getWorldDirection(forward);
203
- forward.y = 0;
204
- forward.normalize();
205
- right.crossVectors(forward, THREE.Object3D.DEFAULT_UP).normalize();
206
-
207
- moveDirection.set(0, 0, 0);
208
- if (this.keys.w) moveDirection.add(forward);
209
- if (this.keys.s) moveDirection.sub(forward);
210
- if (this.keys.a) moveDirection.sub(right);
211
- if (this.keys.d) moveDirection.add(right);
212
- if (moveDirection.lengthSq() === 0) return;
213
- moveDirection.normalize();
214
-
215
- if (!this.baseReferenceSpace) {
216
- this.baseReferenceSpace = xr.getReferenceSpace();
217
- }
218
-
219
- this.locomotionOffset.addScaledVector(moveDirection, -MOVE_SPEED);
220
- const transform = new XRRigidTransform(this.locomotionOffset);
221
- xr.setReferenceSpace(
222
- this.baseReferenceSpace.getOffsetReferenceSpace(transform)
223
- );
224
- }
225
- }
226
-
227
- document.addEventListener('DOMContentLoaded', function () {
228
- const options = new xb.Options();
229
- options.simulator.instructions.enabled = false;
230
- options.reticles.enabled = false;
231
- options.hands.enabled = true;
232
- options.hands.visualization = true;
233
- options.hands.visualizeMeshes = true;
234
- options.simulator.scenePath = null; // Prevent simulator scene from loading.
235
-
236
- xb.add(new WalkthroughManager());
237
- xb.init(options);
238
- });
239
-
240
- </script>
241
- </body>
242
- </html>