@glassly/engine 0.4.0-beta.1025 → 0.4.0-beta.1045

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 (168) hide show
  1. package/build/engine.d.ts +2 -1
  2. package/build/engine.d.ts.map +1 -1
  3. package/build/engine.js +6 -4
  4. package/build/engine.js.map +1 -1
  5. package/build/facades/glasses.js +1 -1
  6. package/build/facades/glasses.js.map +1 -1
  7. package/build/facades/providerKeys.d.ts +1 -1
  8. package/build/facades/providerKeys.js +1 -1
  9. package/build/facades/providerKeys.js.map +1 -1
  10. package/build/facades/reports.d.ts +15 -0
  11. package/build/facades/reports.d.ts.map +1 -1
  12. package/build/facades/reports.js +37 -0
  13. package/build/facades/reports.js.map +1 -1
  14. package/build/generated/releaseMetadata.js +3 -3
  15. package/build/generated/releaseMetadata.js.map +1 -1
  16. package/build/react/useMentraLiveOta.d.ts.map +1 -1
  17. package/build/react/useMentraLiveOta.js.map +1 -1
  18. package/build/runtime/config.d.ts.map +1 -1
  19. package/build/runtime/config.js.map +1 -1
  20. package/build/services/AiTierResolution.d.ts +1 -1
  21. package/build/services/AiTierResolution.d.ts.map +1 -1
  22. package/build/services/AiTierResolution.js.map +1 -1
  23. package/build/services/AutomaticReportResult.d.ts.map +1 -1
  24. package/build/services/AutomaticReportResult.js.map +1 -1
  25. package/build/services/CloudClientService.d.ts +7 -5
  26. package/build/services/CloudClientService.d.ts.map +1 -1
  27. package/build/services/CloudClientService.js +17 -14
  28. package/build/services/CloudClientService.js.map +1 -1
  29. package/build/services/DisplayProcessor.d.ts.map +1 -1
  30. package/build/services/DisplayProcessor.js +2 -1
  31. package/build/services/DisplayProcessor.js.map +1 -1
  32. package/build/services/GestureDotsService.js +1 -1
  33. package/build/services/GestureDotsService.js.map +1 -1
  34. package/build/services/HotspotOtaTransport.d.ts.map +1 -1
  35. package/build/services/HotspotOtaTransport.js +0 -1
  36. package/build/services/HotspotOtaTransport.js.map +1 -1
  37. package/build/services/LocalMiniappRuntime.d.ts +5 -2
  38. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  39. package/build/services/LocalMiniappRuntime.js +54 -23
  40. package/build/services/LocalMiniappRuntime.js.map +1 -1
  41. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  42. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  43. package/build/services/NativeNavigationService.d.ts.map +1 -1
  44. package/build/services/NativeNavigationService.js.map +1 -1
  45. package/build/services/NavigationHandlers.d.ts +1 -1
  46. package/build/services/NavigationHandlers.js +2 -2
  47. package/build/services/NavigationHandlers.js.map +1 -1
  48. package/build/services/NavigationService.d.ts +2 -2
  49. package/build/services/NavigationService.d.ts.map +1 -1
  50. package/build/services/NavigationService.js +11 -11
  51. package/build/services/NavigationService.js.map +1 -1
  52. package/build/services/PairingIdentity.d.ts.map +1 -1
  53. package/build/services/PairingIdentity.js.map +1 -1
  54. package/build/services/PhoneCalendarService.d.ts.map +1 -1
  55. package/build/services/PhoneCalendarService.js.map +1 -1
  56. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  57. package/build/services/PhoneNotificationsSync.js +2 -1
  58. package/build/services/PhoneNotificationsSync.js.map +1 -1
  59. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  60. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  61. package/build/services/ProviderKeyValidation.d.ts +1 -1
  62. package/build/services/ProviderKeyValidation.js +1 -1
  63. package/build/services/ProviderKeyValidation.js.map +1 -1
  64. package/build/services/STTModelManager.d.ts.map +1 -1
  65. package/build/services/STTModelManager.js +1 -6
  66. package/build/services/STTModelManager.js.map +1 -1
  67. package/build/services/SupportProfileSync.d.ts.map +1 -1
  68. package/build/services/SupportProfileSync.js +3 -0
  69. package/build/services/SupportProfileSync.js.map +1 -1
  70. package/build/services/TranscriptionRouting.d.ts +3 -0
  71. package/build/services/TranscriptionRouting.d.ts.map +1 -1
  72. package/build/services/TranscriptionRouting.js +14 -0
  73. package/build/services/TranscriptionRouting.js.map +1 -1
  74. package/build/services/UIRouter.d.ts.map +1 -1
  75. package/build/services/UIRouter.js.map +1 -1
  76. package/build/services/controllers.d.ts.map +1 -1
  77. package/build/services/controllers.js +1 -0
  78. package/build/services/controllers.js.map +1 -1
  79. package/build/services/effectiveCapabilities.js +3 -2
  80. package/build/services/effectiveCapabilities.js.map +1 -1
  81. package/build/services/gestureDotGlyphs.d.ts.map +1 -1
  82. package/build/services/gestureDotGlyphs.js.map +1 -1
  83. package/build/services/manifestActions.d.ts.map +1 -1
  84. package/build/services/manifestActions.js.map +1 -1
  85. package/build/services/notificationAppPayload.d.ts +14 -0
  86. package/build/services/notificationAppPayload.d.ts.map +1 -0
  87. package/build/services/notificationAppPayload.js +15 -0
  88. package/build/services/notificationAppPayload.js.map +1 -0
  89. package/build/services/settingsBridge.d.ts.map +1 -1
  90. package/build/services/settingsBridge.js.map +1 -1
  91. package/build/stores/appVisibility.d.ts.map +1 -1
  92. package/build/stores/appVisibility.js.map +1 -1
  93. package/build/stores/gallerySync.d.ts.map +1 -1
  94. package/build/stores/gallerySync.js.map +1 -1
  95. package/build/stores/glasses.d.ts.map +1 -1
  96. package/build/stores/glasses.js +1 -0
  97. package/build/stores/glasses.js.map +1 -1
  98. package/build/stores/settings.d.ts.map +1 -1
  99. package/build/stores/settings.js +5 -3
  100. package/build/stores/settings.js.map +1 -1
  101. package/build/types/capabilities/nimo.d.ts.map +1 -1
  102. package/build/types/capabilities/nimo.js +19 -7
  103. package/build/types/capabilities/nimo.js.map +1 -1
  104. package/build/types/enums.d.ts +2 -1
  105. package/build/types/enums.d.ts.map +1 -1
  106. package/build/types/enums.js +1 -0
  107. package/build/types/enums.js.map +1 -1
  108. package/build/utils/display/index.d.ts +1 -0
  109. package/build/utils/display/index.d.ts.map +1 -1
  110. package/build/utils/display/index.js +2 -2
  111. package/build/utils/display/index.js.map +1 -1
  112. package/build/utils/display/profiles/index.d.ts +1 -0
  113. package/build/utils/display/profiles/index.d.ts.map +1 -1
  114. package/build/utils/display/profiles/index.js +1 -0
  115. package/build/utils/display/profiles/index.js.map +1 -1
  116. package/build/utils/display/profiles/nimo.d.ts +2 -0
  117. package/build/utils/display/profiles/nimo.d.ts.map +1 -0
  118. package/build/utils/display/profiles/nimo.js +3 -0
  119. package/build/utils/display/profiles/nimo.js.map +1 -0
  120. package/build/utils/display/scene/svgPath.js.map +1 -1
  121. package/build/utils/memory/search.d.ts.map +1 -1
  122. package/build/utils/memory/search.js +17 -7
  123. package/build/utils/memory/search.js.map +1 -1
  124. package/package.json +7 -7
  125. package/src/engine.ts +9 -7
  126. package/src/facades/glasses.ts +1 -1
  127. package/src/facades/providerKeys.ts +1 -1
  128. package/src/facades/reports.ts +41 -0
  129. package/src/generated/releaseMetadata.ts +3 -3
  130. package/src/react/useMentraLiveOta.ts +1 -4
  131. package/src/runtime/config.ts +1 -6
  132. package/src/services/AiTierResolution.ts +1 -1
  133. package/src/services/AutomaticReportResult.ts +1 -3
  134. package/src/services/CloudClientService.ts +17 -11
  135. package/src/services/DisplayProcessor.ts +2 -0
  136. package/src/services/GestureDotsService.ts +1 -1
  137. package/src/services/HotspotOtaTransport.ts +1 -5
  138. package/src/services/LocalMiniappRuntime.ts +66 -24
  139. package/src/services/LocalSttFallbackCoordinator.ts +1 -5
  140. package/src/services/NativeNavigationService.ts +1 -2
  141. package/src/services/NavigationHandlers.ts +2 -2
  142. package/src/services/NavigationService.ts +12 -11
  143. package/src/services/PairingIdentity.ts +1 -3
  144. package/src/services/PhoneCalendarService.ts +1 -3
  145. package/src/services/PhoneNotificationsSync.ts +2 -1
  146. package/src/services/PhoneStreamCoordinator.ts +1 -2
  147. package/src/services/ProviderKeyValidation.ts +1 -1
  148. package/src/services/STTModelManager.ts +1 -6
  149. package/src/services/SupportProfileSync.ts +2 -0
  150. package/src/services/TranscriptionRouting.ts +18 -0
  151. package/src/services/UIRouter.ts +3 -9
  152. package/src/services/controllers.ts +1 -0
  153. package/src/services/effectiveCapabilities.ts +3 -2
  154. package/src/services/gestureDotGlyphs.ts +10 -5
  155. package/src/services/manifestActions.ts +2 -1
  156. package/src/services/notificationAppPayload.ts +15 -0
  157. package/src/services/settingsBridge.ts +1 -2
  158. package/src/stores/appVisibility.ts +2 -5
  159. package/src/stores/gallerySync.ts +1 -7
  160. package/src/stores/glasses.ts +1 -0
  161. package/src/stores/settings.ts +5 -3
  162. package/src/types/capabilities/nimo.ts +20 -7
  163. package/src/types/enums.ts +1 -0
  164. package/src/utils/display/index.ts +2 -2
  165. package/src/utils/display/profiles/index.ts +2 -0
  166. package/src/utils/display/profiles/nimo.ts +2 -0
  167. package/src/utils/display/scene/svgPath.ts +1 -1
  168. package/src/utils/memory/search.ts +17 -7
@@ -61,8 +61,9 @@ function glassesCapabilities(model: DeviceTypes): Capabilities {
61
61
  // Glassly CFW supports the complete vector contract, including SVG and rotation.
62
62
  // Upstream g2flash publishes a raster canvas with sceneVector=false.
63
63
  const vector = useGlassesStore.getState().sceneVector === true
64
- // Depth is a disparity between the lenses; one panel (MemoMind One) draws every element flat.
65
- const stereo = (base.display.count ?? 1) >= 2
64
+ // Depth is a disparity between the eyes: a lens per eye, or firmware that
65
+ // presents a separate raster to each eye's panel (MemoMind One CFW 22+).
66
+ const stereo = (base.display.count ?? 1) >= 2 || useGlassesStore.getState().sceneStereo === true
66
67
  return {
67
68
  ...(volumeGate ? withVolumeGate(base) : base),
68
69
  hasNativeNavigation: resolveNativeNavigation(base.hasNativeNavigation, true, forceNativeNavigationOnCfw()),
@@ -4,18 +4,23 @@
4
4
  */
5
5
  export const GESTURE_DOT_GLYPH_SIZE = 24
6
6
 
7
- export type GestureDotGlyph = "dot" | "double" | "ring" | "doubleRing" | "up" | "down" | "left" | "right" | "hold" | "holdRing" | "blank"
7
+ export type GestureDotGlyph =
8
+ "dot" | "double" | "ring" | "doubleRing" | "up" | "down" | "left" | "right" | "hold" | "holdRing" | "blank"
8
9
 
9
10
  export const GESTURE_DOT_GLYPHS: Record<GestureDotGlyph, string> = {
10
11
  dot: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAALklEQVR4nM2QsQ0AAAjC/P/pmrhqZ+xIF6DqBQyWbwO3gduAmKjQuj7QL/ETEzQmMptl7Q9NBAAAAABJRU5ErkJggg==",
11
- double: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAG0lEQVR4nGNgGD7gPxjgYkN4yOyBlcDp3GEBAB3sd4lPaQxDAAAAAElFTkSuQmCC",
12
+ double:
13
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAG0lEQVR4nGNgGD7gPxjgYkN4yOyBlcDp3GEBAB3sd4lPaQxDAAAAAElFTkSuQmCC",
12
14
  ring: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAANElEQVR4nGNgGBTgPxjgEseUgQphyCD4qDL/kSX+Y9WApoWqEjgsx+lc3B7EHSS4A3EgAAC+cEu1JTNREQAAAABJRU5ErkJggg==",
13
- doubleRing: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAIklEQVR4nGNgGD7gPxjgYkN4yGwGmBA6SV0JHJbjdO6wAADBMlep8zl7TAAAAABJRU5ErkJggg==",
15
+ doubleRing:
16
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAIklEQVR4nGNgGD7gPxjgYkN4yGwGmBA6SV0JHJbjdO6wAADBMlep8zl7TAAAAABJRU5ErkJggg==",
14
17
  up: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAMElEQVR4nGNgoCv4////f1zi2GT+/4ciTHE4RhdHIlDFUUhkcTQKQx9WBw8PCVoBAIcbOcf3xeeBAAAAAElFTkSuQmCC",
15
18
  down: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAALUlEQVR4nGNgoC/4/3+4SkBFUCkkNjKJIoMg0GRgGEMGgrC4CQSwuxanR2gEAO1/Ocfgp8uvAAAAAElFTkSuQmCC",
16
19
  left: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAI0lEQVR4nGNgoCv4j0sch8RAiTP8RwPESOAwajDI4JKgGQAAKO05x7DqJxIAAAAASUVORK5CYII=",
17
- right: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAIElEQVR4nGNgoDf4j1NiMMn8RwOEJYizZKDEcQc7bQAAS7w5x+ro2lsAAAAASUVORK5CYII=",
20
+ right:
21
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAIElEQVR4nGNgoDf4j1NiMMn8RwOEJYizZKDEcQc7bQAAS7w5x+ro2lsAAAAASUVORK5CYII=",
18
22
  hold: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAR0lEQVR4nGNgIAj+gwF2UUy5//+xyyDzcLGRedjMhTEwXAKl0Z0Lof7DKbgMhBpQCZzOxedBHEGCMxAJBTXhKGRAA9hFMQEANr7jHQU9fO0AAAAASUVORK5CYII=",
19
- holdRing: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAQ0lEQVR4nGNgIAj+gwF2UUy5//+xyyDzcLGRedjMhTEwXAKlMd2IVQNMaEAlcDoXnwdxBAnOQCQU1ISjEIvjsYhiAgAo9KdZzePY3AAAAABJRU5ErkJggg==",
23
+ holdRing:
24
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAQ0lEQVR4nGNgIAj+gwF2UUy5//+xyyDzcLGRedjMhTEwXAKlMd2IVQNMaEAlcDoXnwdxBAnOQCQU1ISjEIvjsYhiAgAo9KdZzePY3AAAAABJRU5ErkJggg==",
20
25
  blank: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAD0lEQVR4nGNgGAWjgPoAAAJYAAGgxYwDAAAAAElFTkSuQmCC",
21
26
  }
@@ -80,7 +80,8 @@ export function normalizeManifestActions(raw: unknown): DeclaredAction[] {
80
80
  }
81
81
 
82
82
  const WIDGET_SIZES: readonly DeclaredWidgetSize[] = ["XS", "XSM", "SM", "MD", "LG"]
83
- const isWidgetSize = (value: unknown): value is DeclaredWidgetSize => (WIDGET_SIZES as readonly unknown[]).includes(value)
83
+ const isWidgetSize = (value: unknown): value is DeclaredWidgetSize =>
84
+ (WIDGET_SIZES as readonly unknown[]).includes(value)
84
85
 
85
86
  /**
86
87
  * Normalize manifest widgets for installed and dev-sideloaded bundles: an
@@ -0,0 +1,15 @@
1
+ /** Keep installed-app icons from exhausting the miniapp's 32 MiB JS heap.
2
+ * Icons are optional; clients already render a fallback when one is absent.
3
+ * Bound both individual icons and their total before JSON crosses the bridge.
4
+ */
5
+ export function notificationAppPayload(
6
+ apps: Array<{packageName: string; appName: string; icon: string | null}>,
7
+ ): Array<{packageName: string; appName: string; icon: string | null}> {
8
+ let remaining = 128 * 1024
9
+ return apps.map(({packageName, appName, icon}) => {
10
+ const size = icon?.length ?? 0
11
+ const keep = size <= 8 * 1024 && size <= remaining
12
+ if (keep) remaining -= size
13
+ return {packageName, appName, icon: keep ? icon : null}
14
+ })
15
+ }
@@ -82,8 +82,7 @@ export function selectSettingsBridgeKeys(requested: unknown): string[] {
82
82
  }
83
83
 
84
84
  export type SettingsSetValidation =
85
- | {ok: true; key: string; value: unknown}
86
- | {ok: false; code: "INVALID_ARGUMENT" | "NOT_PERMITTED"; message: string}
85
+ {ok: true; key: string; value: unknown} | {ok: false; code: "INVALID_ARGUMENT" | "NOT_PERMITTED"; message: string}
87
86
 
88
87
  /** A SETTINGS_SET payload: a writable key and a JSON value (undefined is not a value). */
89
88
  export function validateSettingsSet(payload: Record<string, unknown>): SettingsSetValidation {
@@ -44,8 +44,5 @@ export const isGatedByDevTools = (packageName: string, devToolsEnabled: boolean)
44
44
  export const PAIRED_GLASSES_PACKAGES: ReadonlySet<string> = new Set(["com.glassly.store"])
45
45
 
46
46
  /** True when the app waits on a pairing that hasn't happened and dev tools are off. */
47
- export const isGatedUntilPaired = (
48
- packageName: string,
49
- devToolsEnabled: boolean,
50
- hasPairedGlasses: boolean,
51
- ): boolean => !devToolsEnabled && !hasPairedGlasses && PAIRED_GLASSES_PACKAGES.has(packageName)
47
+ export const isGatedUntilPaired = (packageName: string, devToolsEnabled: boolean, hasPairedGlasses: boolean): boolean =>
48
+ !devToolsEnabled && !hasPairedGlasses && PAIRED_GLASSES_PACKAGES.has(packageName)
@@ -29,13 +29,7 @@ export interface PhotoInfo {
29
29
 
30
30
  // Sync state machine states
31
31
  export type SyncState =
32
- | "idle"
33
- | "requesting_hotspot"
34
- | "connecting_wifi"
35
- | "syncing"
36
- | "complete"
37
- | "error"
38
- | "cancelled"
32
+ "idle" | "requesting_hotspot" | "connecting_wifi" | "syncing" | "complete" | "error" | "cancelled"
39
33
 
40
34
  export interface HotspotInfo {
41
35
  ssid: string
@@ -144,6 +144,7 @@ const initialState: GlassesStore = {
144
144
  sceneCanvasWidth: 0,
145
145
  sceneCanvasHeight: 0,
146
146
  sceneVector: false,
147
+ sceneStereo: false,
147
148
  sceneSettle: false,
148
149
  volumeGate: false,
149
150
  firmwareUpdateAvailable: false,
@@ -134,7 +134,7 @@ export const SETTINGS: Record<string, Setting> = {
134
134
  },
135
135
  memomind_accessory_picker: {
136
136
  key: "memomind_accessory_picker",
137
- defaultValue: () => false,
137
+ defaultValue: () => true,
138
138
  writable: true,
139
139
  saveOnServer: false,
140
140
  persist: true,
@@ -333,7 +333,7 @@ export const SETTINGS: Record<string, Setting> = {
333
333
  saveOnServer: false,
334
334
  persist: true,
335
335
  },
336
- // User-supplied AI/voice provider keys (Settings > API Keys). Not consumed
336
+ // User-supplied AI/voice provider keys (Settings > Privacy > API Keys). Not consumed
337
337
  // by the app itself — they exist so miniapps declaring the API_KEYS manifest
338
338
  // permission can read them via session.keys.get() (see
339
339
  // MINIAPP_READABLE_API_KEYS in LocalMiniappRuntime; mapbox is also readable
@@ -762,12 +762,14 @@ export const SETTINGS: Record<string, Setting> = {
762
762
  saveOnServer: true,
763
763
  persist: true,
764
764
  },
765
+ // Session-only: Position settings holds it on for stock G1, and a persisted
766
+ // true (app killed on that screen) blanks every glasses' display at boot.
765
767
  screen_disabled: {
766
768
  key: "screen_disabled",
767
769
  defaultValue: () => false,
768
770
  writable: true,
769
771
  saveOnServer: false,
770
- persist: true,
772
+ persist: false,
771
773
  },
772
774
  // glasses settings:
773
775
  contextual_dashboard: {
@@ -18,21 +18,34 @@ export const nimo: Capabilities = {
18
18
  hasCamera: false,
19
19
  camera: null,
20
20
 
21
- // Display capabilities - monochrome binocular display
21
+ // Display capabilities - monochrome binocular display. Firmware 0.1.1.1+
22
+ // has a phone-drawn page (app 0xFD): a 500x220 canvas of positioned text,
23
+ // rectangles, circles, lines and bitmaps that the drivers render scene
24
+ // frames onto (NimoDynamicLayout.kt / .swift). Older firmware shows the
25
+ // frame's text on the ASR note page instead.
22
26
  hasDisplay: true,
23
27
  display: {
24
28
  count: 2,
25
29
  isColor: false,
26
30
  color: "green",
27
31
  canDisplayBitmap: true,
28
- // Bitmaps render into the nav mini-map widget (appId 0x01, 160x160 2bpp);
29
- // see displayBitmap in Nimo.kt / Nimo.swift. The resolution below is the
30
- // text-display placeholder, not the bitmap target.
31
- // TODO: placeholder - verify against hardware screen info
32
- resolution: {width: 640, height: 400},
33
- maxTextLines: 5,
32
+ resolution: {width: 540, height: 280},
33
+ maxTextLines: 10,
34
34
  adjustBrightness: true,
35
35
  positionRange: {height: {min: 0, max: 10}, depth: {min: 0, max: 10}},
36
+
37
+ // Scene display API - the Dynamic Layout canvas.
38
+ width: 500,
39
+ height: 220,
40
+ canPosition: true,
41
+ // One page holds 64 objects; the text pool is shared with rectangles.
42
+ maxTextElements: 32,
43
+ maxImageElements: 4,
44
+ maxImagePx: {width: 500, height: 220},
45
+ shapes: ["rect", "circle", "line"],
46
+ intensityLevels: 16,
47
+ // Every frame replaces the page; the firmware has no per-object update.
48
+ partialUpdate: false,
36
49
  },
37
50
 
38
51
  // Microphone capabilities - Nimo streams Opus audio from both arms
@@ -25,4 +25,5 @@ export enum ControllerTypes {
25
25
  IINE_ANANKE = "IINE Ananke Gen 2",
26
26
  ZERO2 = "8BitDo Zero 2",
27
27
  MICRO = "8BitDo Micro",
28
+ CRKD_ATOM_PLUS = "CRKD ATOM+",
28
29
  }
@@ -36,7 +36,7 @@
36
36
  // =============================================================================
37
37
 
38
38
  // Import for factory functions
39
- import {G1_PROFILE_LEGACY, G2_PROFILE, Z100_PROFILE, NEX_PROFILE} from "./profiles"
39
+ import {G1_PROFILE_LEGACY, G2_PROFILE, Z100_PROFILE, NEX_PROFILE, G1_PROFILE} from "./profiles"
40
40
 
41
41
  // =============================================================================
42
42
  // Convenience factory functions
@@ -46,7 +46,6 @@ import {TextMeasurer} from "./measurer"
46
46
  import {TextWrapper} from "./wrapper"
47
47
  import {DisplayHelpers} from "./helpers"
48
48
  import {ColumnComposer} from "./composer"
49
- import {G1_PROFILE} from "./profiles"
50
49
  import type {DisplayProfile} from "./profiles"
51
50
  import type {WrapOptions} from "./wrapper"
52
51
 
@@ -276,3 +275,4 @@ export function createNexToolkit(): {
276
275
  }
277
276
 
278
277
  export {MEMOMIND_ONE_PROFILE} from "./profiles"
278
+ export {NIMO_PROFILE} from "./profiles"
@@ -36,3 +36,5 @@ export {
36
36
  } from "./rayneo-io"
37
37
 
38
38
  export {MEMOMIND_ONE_PROFILE} from "@glassly/miniapp/display"
39
+
40
+ export {NIMO_PROFILE} from "./nimo"
@@ -0,0 +1,2 @@
1
+ // Moved into the SDK (@glassly/miniapp/display) so miniapps lay text out the way the host measures it; this path re-exports it for the engine.
2
+ export {NIMO_PROFILE} from "@glassly/miniapp/display"
@@ -128,7 +128,7 @@ export function compileSvgPath(d: string): {commands: number[]; edges: number} {
128
128
  curve(a, depth + 1)
129
129
  curve(b, depth + 1)
130
130
  }
131
- for (let i = 0; i < commands.length; ) {
131
+ for (let i = 0; i < commands.length;) {
132
132
  const op = commands[i++],
133
133
  pairs = op === 4 ? 0 : op === 3 ? 3 : op === 2 ? 2 : 1
134
134
  if (++count > 1024) throw new Error("SVG path exceeds 1024 commands")
@@ -66,9 +66,7 @@ export function searchMemoryEntries<T extends MemorySearchableEntry>(
66
66
  const windowCount = Math.max(0, hi - lo)
67
67
 
68
68
  const needle = q.contains?.trim().toLowerCase() || null
69
- const termWords = (q.terms ?? [])
70
- .map((t) => tokenize(t))
71
- .filter((words) => words.length > 0)
69
+ const termWords = (q.terms ?? []).map((t) => tokenize(t)).filter((words) => words.length > 0)
72
70
 
73
71
  const picked: T[] = []
74
72
  for (let i = hi - 1; i >= lo && picked.length < q.limit; i--) {
@@ -154,11 +152,23 @@ export function editDistanceAtMost(a: string, b: string, max: number): boolean {
154
152
  }
155
153
 
156
154
  const SOUNDEX_CODES: Record<string, string> = {
157
- b: "1", f: "1", p: "1", v: "1",
158
- c: "2", g: "2", j: "2", k: "2", q: "2", s: "2", x: "2", z: "2",
159
- d: "3", t: "3",
155
+ b: "1",
156
+ f: "1",
157
+ p: "1",
158
+ v: "1",
159
+ c: "2",
160
+ g: "2",
161
+ j: "2",
162
+ k: "2",
163
+ q: "2",
164
+ s: "2",
165
+ x: "2",
166
+ z: "2",
167
+ d: "3",
168
+ t: "3",
160
169
  l: "4",
161
- m: "5", n: "5",
170
+ m: "5",
171
+ n: "5",
162
172
  r: "6",
163
173
  }
164
174