@glassly/engine 0.4.0 → 0.4.1-dev.1137

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 (230) hide show
  1. package/build/engine.d.ts +3 -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/display.d.ts +1 -1
  6. package/build/facades/display.d.ts.map +1 -1
  7. package/build/facades/display.js +1 -1
  8. package/build/facades/display.js.map +1 -1
  9. package/build/facades/glasses.js +1 -1
  10. package/build/facades/glasses.js.map +1 -1
  11. package/build/facades/permissions.d.ts.map +1 -1
  12. package/build/facades/permissions.js +0 -2
  13. package/build/facades/permissions.js.map +1 -1
  14. package/build/facades/phoneNotifications.d.ts +7 -0
  15. package/build/facades/phoneNotifications.d.ts.map +1 -1
  16. package/build/facades/phoneNotifications.js +6 -0
  17. package/build/facades/phoneNotifications.js.map +1 -1
  18. package/build/facades/providerKeys.d.ts +1 -1
  19. package/build/facades/providerKeys.js +1 -1
  20. package/build/facades/providerKeys.js.map +1 -1
  21. package/build/facades/reports.d.ts +15 -0
  22. package/build/facades/reports.d.ts.map +1 -1
  23. package/build/facades/reports.js +37 -0
  24. package/build/facades/reports.js.map +1 -1
  25. package/build/facades/settings.js +1 -1
  26. package/build/facades/settings.js.map +1 -1
  27. package/build/generated/releaseMetadata.js +4 -4
  28. package/build/generated/releaseMetadata.js.map +1 -1
  29. package/build/index.d.ts +2 -1
  30. package/build/index.d.ts.map +1 -1
  31. package/build/index.js +1 -1
  32. package/build/index.js.map +1 -1
  33. package/build/react/useMentraLiveOta.d.ts.map +1 -1
  34. package/build/react/useMentraLiveOta.js.map +1 -1
  35. package/build/runtime/config.d.ts.map +1 -1
  36. package/build/runtime/config.js.map +1 -1
  37. package/build/services/AiTierResolution.d.ts +1 -1
  38. package/build/services/AiTierResolution.d.ts.map +1 -1
  39. package/build/services/AiTierResolution.js.map +1 -1
  40. package/build/services/AppRegistry.d.ts +12 -1
  41. package/build/services/AppRegistry.d.ts.map +1 -1
  42. package/build/services/AppRegistry.js +33 -0
  43. package/build/services/AppRegistry.js.map +1 -1
  44. package/build/services/AutomaticReportResult.d.ts.map +1 -1
  45. package/build/services/AutomaticReportResult.js.map +1 -1
  46. package/build/services/CloudClientService.d.ts +7 -5
  47. package/build/services/CloudClientService.d.ts.map +1 -1
  48. package/build/services/CloudClientService.js +17 -14
  49. package/build/services/CloudClientService.js.map +1 -1
  50. package/build/services/DisplayProcessor.d.ts.map +1 -1
  51. package/build/services/DisplayProcessor.js +2 -1
  52. package/build/services/DisplayProcessor.js.map +1 -1
  53. package/build/services/GestureDotsService.js +1 -1
  54. package/build/services/GestureDotsService.js.map +1 -1
  55. package/build/services/HotspotOtaTransport.d.ts.map +1 -1
  56. package/build/services/HotspotOtaTransport.js +0 -1
  57. package/build/services/HotspotOtaTransport.js.map +1 -1
  58. package/build/services/JSRouter.js +2 -2
  59. package/build/services/JSRouter.js.map +1 -1
  60. package/build/services/LocalLlmModelManager.d.ts.map +1 -1
  61. package/build/services/LocalLlmModelManager.js +4 -3
  62. package/build/services/LocalLlmModelManager.js.map +1 -1
  63. package/build/services/LocalLlmProvider.d.ts.map +1 -1
  64. package/build/services/LocalLlmProvider.js +5 -6
  65. package/build/services/LocalLlmProvider.js.map +1 -1
  66. package/build/services/LocalMiniappRuntime.d.ts +10 -3
  67. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  68. package/build/services/LocalMiniappRuntime.js +142 -30
  69. package/build/services/LocalMiniappRuntime.js.map +1 -1
  70. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  71. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  72. package/build/services/NativeNavigationService.d.ts.map +1 -1
  73. package/build/services/NativeNavigationService.js.map +1 -1
  74. package/build/services/NavigationHandlers.d.ts +1 -1
  75. package/build/services/NavigationHandlers.js +2 -2
  76. package/build/services/NavigationHandlers.js.map +1 -1
  77. package/build/services/NavigationService.d.ts +2 -2
  78. package/build/services/NavigationService.d.ts.map +1 -1
  79. package/build/services/NavigationService.js +11 -11
  80. package/build/services/NavigationService.js.map +1 -1
  81. package/build/services/PairingIdentity.d.ts.map +1 -1
  82. package/build/services/PairingIdentity.js.map +1 -1
  83. package/build/services/PhoneCalendarService.d.ts.map +1 -1
  84. package/build/services/PhoneCalendarService.js.map +1 -1
  85. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  86. package/build/services/PhoneNotificationsSync.js +2 -1
  87. package/build/services/PhoneNotificationsSync.js.map +1 -1
  88. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  89. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  90. package/build/services/ProviderKeyValidation.d.ts +1 -1
  91. package/build/services/ProviderKeyValidation.js +1 -1
  92. package/build/services/ProviderKeyValidation.js.map +1 -1
  93. package/build/services/STTModelManager.d.ts.map +1 -1
  94. package/build/services/STTModelManager.js +1 -6
  95. package/build/services/STTModelManager.js.map +1 -1
  96. package/build/services/SupportProfileSync.d.ts.map +1 -1
  97. package/build/services/SupportProfileSync.js +3 -0
  98. package/build/services/SupportProfileSync.js.map +1 -1
  99. package/build/services/TranscriptionRouting.d.ts +3 -0
  100. package/build/services/TranscriptionRouting.d.ts.map +1 -1
  101. package/build/services/TranscriptionRouting.js +14 -0
  102. package/build/services/TranscriptionRouting.js.map +1 -1
  103. package/build/services/UIRouter.d.ts.map +1 -1
  104. package/build/services/UIRouter.js.map +1 -1
  105. package/build/services/controllers.d.ts.map +1 -1
  106. package/build/services/controllers.js +1 -0
  107. package/build/services/controllers.js.map +1 -1
  108. package/build/services/effectiveCapabilities.js +3 -2
  109. package/build/services/effectiveCapabilities.js.map +1 -1
  110. package/build/services/gestureDotGlyphs.d.ts.map +1 -1
  111. package/build/services/gestureDotGlyphs.js.map +1 -1
  112. package/build/services/manifestActions.d.ts.map +1 -1
  113. package/build/services/manifestActions.js.map +1 -1
  114. package/build/services/neuralBand/MetaAuth.d.ts +1 -0
  115. package/build/services/neuralBand/MetaAuth.d.ts.map +1 -1
  116. package/build/services/neuralBand/MetaAuth.js +36 -8
  117. package/build/services/neuralBand/MetaAuth.js.map +1 -1
  118. package/build/services/notificationAppPayload.d.ts +14 -0
  119. package/build/services/notificationAppPayload.d.ts.map +1 -0
  120. package/build/services/notificationAppPayload.js +15 -0
  121. package/build/services/notificationAppPayload.js.map +1 -0
  122. package/build/services/notifications/miniappNotifications.d.ts +31 -0
  123. package/build/services/notifications/miniappNotifications.d.ts.map +1 -0
  124. package/build/services/notifications/miniappNotifications.js +24 -0
  125. package/build/services/notifications/miniappNotifications.js.map +1 -0
  126. package/build/services/pages/pageEligibility.d.ts +1 -2
  127. package/build/services/pages/pageEligibility.d.ts.map +1 -1
  128. package/build/services/pages/pageEligibility.js +4 -2
  129. package/build/services/pages/pageEligibility.js.map +1 -1
  130. package/build/services/settingsBridge.d.ts.map +1 -1
  131. package/build/services/settingsBridge.js +0 -2
  132. package/build/services/settingsBridge.js.map +1 -1
  133. package/build/services/uiShim.d.ts.map +1 -1
  134. package/build/services/uiShim.js +14 -0
  135. package/build/services/uiShim.js.map +1 -1
  136. package/build/stores/appVisibility.d.ts.map +1 -1
  137. package/build/stores/appVisibility.js.map +1 -1
  138. package/build/stores/gallerySync.d.ts.map +1 -1
  139. package/build/stores/gallerySync.js.map +1 -1
  140. package/build/stores/glasses.d.ts.map +1 -1
  141. package/build/stores/glasses.js +1 -0
  142. package/build/stores/glasses.js.map +1 -1
  143. package/build/stores/settings.d.ts.map +1 -1
  144. package/build/stores/settings.js +27 -28
  145. package/build/stores/settings.js.map +1 -1
  146. package/build/types/capabilities/even-realities-g1.d.ts.map +1 -1
  147. package/build/types/capabilities/even-realities-g1.js +4 -0
  148. package/build/types/capabilities/even-realities-g1.js.map +1 -1
  149. package/build/types/capabilities/nimo.d.ts.map +1 -1
  150. package/build/types/capabilities/nimo.js +21 -7
  151. package/build/types/capabilities/nimo.js.map +1 -1
  152. package/build/types/enums.d.ts +2 -1
  153. package/build/types/enums.d.ts.map +1 -1
  154. package/build/types/enums.js +1 -0
  155. package/build/types/enums.js.map +1 -1
  156. package/build/utils/display/index.d.ts +1 -0
  157. package/build/utils/display/index.d.ts.map +1 -1
  158. package/build/utils/display/index.js +2 -2
  159. package/build/utils/display/index.js.map +1 -1
  160. package/build/utils/display/profiles/index.d.ts +1 -0
  161. package/build/utils/display/profiles/index.d.ts.map +1 -1
  162. package/build/utils/display/profiles/index.js +1 -0
  163. package/build/utils/display/profiles/index.js.map +1 -1
  164. package/build/utils/display/profiles/nimo.d.ts +2 -0
  165. package/build/utils/display/profiles/nimo.d.ts.map +1 -0
  166. package/build/utils/display/profiles/nimo.js +3 -0
  167. package/build/utils/display/profiles/nimo.js.map +1 -0
  168. package/build/utils/display/scene/svgPath.js.map +1 -1
  169. package/build/utils/memory/search.d.ts.map +1 -1
  170. package/build/utils/memory/search.js +17 -7
  171. package/build/utils/memory/search.js.map +1 -1
  172. package/package.json +15 -15
  173. package/src/engine.ts +9 -7
  174. package/src/facades/display.ts +1 -1
  175. package/src/facades/glasses.ts +1 -1
  176. package/src/facades/permissions.ts +0 -2
  177. package/src/facades/phoneNotifications.ts +10 -0
  178. package/src/facades/providerKeys.ts +1 -1
  179. package/src/facades/reports.ts +41 -0
  180. package/src/facades/settings.ts +1 -1
  181. package/src/generated/releaseMetadata.ts +4 -4
  182. package/src/index.ts +2 -0
  183. package/src/react/useMentraLiveOta.ts +1 -4
  184. package/src/runtime/config.ts +1 -6
  185. package/src/services/AiTierResolution.ts +1 -1
  186. package/src/services/AppRegistry.ts +38 -1
  187. package/src/services/AutomaticReportResult.ts +1 -3
  188. package/src/services/CloudClientService.ts +17 -11
  189. package/src/services/DisplayProcessor.ts +2 -0
  190. package/src/services/GestureDotsService.ts +1 -1
  191. package/src/services/HotspotOtaTransport.ts +1 -5
  192. package/src/services/JSRouter.ts +2 -2
  193. package/src/services/LocalLlmModelManager.ts +4 -3
  194. package/src/services/LocalLlmProvider.ts +6 -7
  195. package/src/services/LocalMiniappRuntime.ts +170 -40
  196. package/src/services/LocalSttFallbackCoordinator.ts +1 -5
  197. package/src/services/NativeNavigationService.ts +1 -2
  198. package/src/services/NavigationHandlers.ts +2 -2
  199. package/src/services/NavigationService.ts +12 -11
  200. package/src/services/PairingIdentity.ts +1 -3
  201. package/src/services/PhoneCalendarService.ts +1 -3
  202. package/src/services/PhoneNotificationsSync.ts +2 -1
  203. package/src/services/PhoneStreamCoordinator.ts +1 -2
  204. package/src/services/ProviderKeyValidation.ts +1 -1
  205. package/src/services/STTModelManager.ts +1 -6
  206. package/src/services/SupportProfileSync.ts +2 -0
  207. package/src/services/TranscriptionRouting.ts +18 -0
  208. package/src/services/UIRouter.ts +3 -9
  209. package/src/services/controllers.ts +1 -0
  210. package/src/services/effectiveCapabilities.ts +3 -2
  211. package/src/services/gestureDotGlyphs.ts +10 -5
  212. package/src/services/manifestActions.ts +2 -1
  213. package/src/services/neuralBand/MetaAuth.ts +37 -8
  214. package/src/services/notificationAppPayload.ts +15 -0
  215. package/src/services/notifications/miniappNotifications.ts +53 -0
  216. package/src/services/pages/pageEligibility.ts +3 -2
  217. package/src/services/settingsBridge.ts +1 -4
  218. package/src/services/uiShim.ts +14 -0
  219. package/src/stores/appVisibility.ts +2 -5
  220. package/src/stores/gallerySync.ts +1 -7
  221. package/src/stores/glasses.ts +1 -0
  222. package/src/stores/settings.ts +27 -28
  223. package/src/types/capabilities/even-realities-g1.ts +5 -0
  224. package/src/types/capabilities/nimo.ts +23 -7
  225. package/src/types/enums.ts +1 -0
  226. package/src/utils/display/index.ts +2 -2
  227. package/src/utils/display/profiles/index.ts +2 -0
  228. package/src/utils/display/profiles/nimo.ts +2 -0
  229. package/src/utils/display/scene/svgPath.ts +1 -1
  230. package/src/utils/memory/search.ts +17 -7
@@ -13,21 +13,33 @@ export const nimo = {
13
13
  // Camera capabilities - Nimo does not have a camera
14
14
  hasCamera: false,
15
15
  camera: null,
16
- // Display capabilities - monochrome binocular display
16
+ // Display capabilities - monochrome binocular display. Firmware 0.1.1.1+
17
+ // has a phone-drawn page (app 0xFD): a 500x220 canvas of positioned text,
18
+ // rectangles, circles, lines and bitmaps that the drivers render scene
19
+ // frames onto (NimoDynamicLayout.kt / .swift). Older firmware shows the
20
+ // frame's text on the ASR note page instead.
17
21
  hasDisplay: true,
18
22
  display: {
19
23
  count: 2,
20
24
  isColor: false,
21
25
  color: "green",
22
26
  canDisplayBitmap: true,
23
- // Bitmaps render into the nav mini-map widget (appId 0x01, 160x160 2bpp);
24
- // see displayBitmap in Nimo.kt / Nimo.swift. The resolution below is the
25
- // text-display placeholder, not the bitmap target.
26
- // TODO: placeholder - verify against hardware screen info
27
- resolution: { width: 640, height: 400 },
28
- maxTextLines: 5,
27
+ resolution: { width: 540, height: 280 },
28
+ maxTextLines: 10,
29
29
  adjustBrightness: true,
30
30
  positionRange: { height: { min: 0, max: 10 }, depth: { min: 0, max: 10 } },
31
+ // Scene display API - the Dynamic Layout canvas.
32
+ width: 500,
33
+ height: 220,
34
+ canPosition: true,
35
+ // One page holds 64 objects; the text pool is shared with rectangles.
36
+ maxTextElements: 32,
37
+ maxImageElements: 4,
38
+ maxImagePx: { width: 500, height: 220 },
39
+ shapes: ["rect", "circle", "line"],
40
+ intensityLevels: 16,
41
+ // Every frame replaces the page; the firmware has no per-object update.
42
+ partialUpdate: false,
31
43
  },
32
44
  // Microphone capabilities - Nimo streams Opus audio from both arms
33
45
  hasMicrophone: true,
@@ -69,5 +81,7 @@ export const nimo = {
69
81
  hasWifi: false,
70
82
  // OTA capabilities - Nimo firmware updates are not driven by the ASG OTA flow
71
83
  hasOta: false,
84
+ // The drivers flash a bundled Glassly CFW over the GATT OTA characteristics.
85
+ hasCustomFirmware: true,
72
86
  };
73
87
  //# sourceMappingURL=nimo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nimo.js","sourceRoot":"","sources":["../../../src/types/capabilities/nimo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAiB;IAChC,SAAS,EAAE,MAAM;IAEjB,oDAAoD;IACpD,SAAS,EAAE,KAAK;IAChB,MAAM,EAAE,IAAI;IAEZ,sDAAsD;IACtD,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE;QACP,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,OAAO;QACd,gBAAgB,EAAE,IAAI;QACtB,0EAA0E;QAC1E,yEAAyE;QACzE,mDAAmD;QACnD,0DAA0D;QAC1D,UAAU,EAAE,EAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAC;QACrC,YAAY,EAAE,CAAC;QACf,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,EAAC,MAAM,EAAE,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC,EAAE,KAAK,EAAE,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC,EAAC;KACrE;IAED,mEAAmE;IACnE,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE;QACV,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,KAAK;KACd;IAED,4DAA4D;IAC5D,UAAU,EAAE,KAAK;IACjB,OAAO,EAAE,IAAI;IAEb,mDAAmD;IACnD,MAAM,EAAE,IAAI;IACZ,GAAG,EAAE,IAAI;IAET,4DAA4D;IAC5D,SAAS,EAAE,IAAI;IACf,MAAM,EAAE;QACN,KAAK,EAAE,CAAC;QACR,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,YAAY,CAAC;gBAC/C,YAAY,EAAE,IAAI;aACnB;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,YAAY,CAAC;gBAC/C,YAAY,EAAE,IAAI;aACnB;SACF;KACF;IAED,iCAAiC;IACjC,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE,IAAI;IAEX,qBAAqB;IACrB,KAAK,EAAE;QACL,kBAAkB,EAAE,KAAK;KAC1B;IAED,8BAA8B;IAC9B,OAAO,EAAE,KAAK;IAEd,8EAA8E;IAC9E,MAAM,EAAE,KAAK;CACd,CAAA","sourcesContent":["/**\n * @fileoverview Nimo Glasses Hardware Capabilities\n *\n * Capability profile for the Nimo smart glasses model.\n * Nimo uses a framed UART-over-BLE protocol with widget/app-based content\n * updates and a separate Opus microphone channel.\n */\n\nimport type {Capabilities} from \"../hardware\"\n\n/**\n * Nimo Glasses capability profile\n */\nexport const nimo: Capabilities = {\n modelName: \"NIMO\",\n\n // Camera capabilities - Nimo does not have a camera\n hasCamera: false,\n camera: null,\n\n // Display capabilities - monochrome binocular display\n hasDisplay: true,\n display: {\n count: 2,\n isColor: false,\n color: \"green\",\n canDisplayBitmap: true,\n // Bitmaps render into the nav mini-map widget (appId 0x01, 160x160 2bpp);\n // see displayBitmap in Nimo.kt / Nimo.swift. The resolution below is the\n // text-display placeholder, not the bitmap target.\n // TODO: placeholder - verify against hardware screen info\n resolution: {width: 640, height: 400},\n maxTextLines: 5,\n adjustBrightness: true,\n positionRange: {height: {min: 0, max: 10}, depth: {min: 0, max: 10}},\n },\n\n // Microphone capabilities - Nimo streams Opus audio from both arms\n hasMicrophone: true,\n microphone: {\n count: 2,\n hasVAD: false,\n },\n\n // Speaker capabilities - no speaker channel in the protocol\n hasSpeaker: false,\n speaker: null,\n\n // IMU capabilities - head-up/head-down events only\n hasIMU: true,\n imu: null,\n\n // Button capabilities - capacitive touch areas on both arms\n hasButton: true,\n button: {\n count: 2,\n buttons: [\n {\n type: \"press\",\n events: [\"press\", \"double_press\", \"long_press\"],\n isCapacitive: true,\n },\n {\n type: \"press\",\n events: [\"press\", \"double_press\", \"long_press\"],\n isCapacitive: true,\n },\n ],\n },\n\n // Light capabilities - no lights\n hasLight: false,\n light: null,\n\n // Power capabilities\n power: {\n hasExternalBattery: false,\n },\n\n // WiFi capabilities - no WiFi\n hasWifi: false,\n\n // OTA capabilities - Nimo firmware updates are not driven by the ASG OTA flow\n hasOta: false,\n}\n"]}
1
+ {"version":3,"file":"nimo.js","sourceRoot":"","sources":["../../../src/types/capabilities/nimo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAiB;IAChC,SAAS,EAAE,MAAM;IAEjB,oDAAoD;IACpD,SAAS,EAAE,KAAK;IAChB,MAAM,EAAE,IAAI;IAEZ,yEAAyE;IACzE,0EAA0E;IAC1E,uEAAuE;IACvE,wEAAwE;IACxE,6CAA6C;IAC7C,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE;QACP,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,OAAO;QACd,gBAAgB,EAAE,IAAI;QACtB,UAAU,EAAE,EAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAC;QACrC,YAAY,EAAE,EAAE;QAChB,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,EAAC,MAAM,EAAE,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC,EAAE,KAAK,EAAE,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC,EAAC;QAEpE,iDAAiD;QACjD,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,GAAG;QACX,WAAW,EAAE,IAAI;QACjB,sEAAsE;QACtE,eAAe,EAAE,EAAE;QACnB,gBAAgB,EAAE,CAAC;QACnB,UAAU,EAAE,EAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAC;QACrC,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC;QAClC,eAAe,EAAE,EAAE;QACnB,wEAAwE;QACxE,aAAa,EAAE,KAAK;KACrB;IAED,mEAAmE;IACnE,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE;QACV,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,KAAK;KACd;IAED,4DAA4D;IAC5D,UAAU,EAAE,KAAK;IACjB,OAAO,EAAE,IAAI;IAEb,mDAAmD;IACnD,MAAM,EAAE,IAAI;IACZ,GAAG,EAAE,IAAI;IAET,4DAA4D;IAC5D,SAAS,EAAE,IAAI;IACf,MAAM,EAAE;QACN,KAAK,EAAE,CAAC;QACR,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,YAAY,CAAC;gBAC/C,YAAY,EAAE,IAAI;aACnB;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,YAAY,CAAC;gBAC/C,YAAY,EAAE,IAAI;aACnB;SACF;KACF;IAED,iCAAiC;IACjC,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE,IAAI;IAEX,qBAAqB;IACrB,KAAK,EAAE;QACL,kBAAkB,EAAE,KAAK;KAC1B;IAED,8BAA8B;IAC9B,OAAO,EAAE,KAAK;IAEd,8EAA8E;IAC9E,MAAM,EAAE,KAAK;IAEb,6EAA6E;IAC7E,iBAAiB,EAAE,IAAI;CACxB,CAAA","sourcesContent":["/**\n * @fileoverview Nimo Glasses Hardware Capabilities\n *\n * Capability profile for the Nimo smart glasses model.\n * Nimo uses a framed UART-over-BLE protocol with widget/app-based content\n * updates and a separate Opus microphone channel.\n */\n\nimport type {Capabilities} from \"../hardware\"\n\n/**\n * Nimo Glasses capability profile\n */\nexport const nimo: Capabilities = {\n modelName: \"NIMO\",\n\n // Camera capabilities - Nimo does not have a camera\n hasCamera: false,\n camera: null,\n\n // Display capabilities - monochrome binocular display. Firmware 0.1.1.1+\n // has a phone-drawn page (app 0xFD): a 500x220 canvas of positioned text,\n // rectangles, circles, lines and bitmaps that the drivers render scene\n // frames onto (NimoDynamicLayout.kt / .swift). Older firmware shows the\n // frame's text on the ASR note page instead.\n hasDisplay: true,\n display: {\n count: 2,\n isColor: false,\n color: \"green\",\n canDisplayBitmap: true,\n resolution: {width: 540, height: 280},\n maxTextLines: 10,\n adjustBrightness: true,\n positionRange: {height: {min: 0, max: 10}, depth: {min: 0, max: 10}},\n\n // Scene display API - the Dynamic Layout canvas.\n width: 500,\n height: 220,\n canPosition: true,\n // One page holds 64 objects; the text pool is shared with rectangles.\n maxTextElements: 32,\n maxImageElements: 4,\n maxImagePx: {width: 500, height: 220},\n shapes: [\"rect\", \"circle\", \"line\"],\n intensityLevels: 16,\n // Every frame replaces the page; the firmware has no per-object update.\n partialUpdate: false,\n },\n\n // Microphone capabilities - Nimo streams Opus audio from both arms\n hasMicrophone: true,\n microphone: {\n count: 2,\n hasVAD: false,\n },\n\n // Speaker capabilities - no speaker channel in the protocol\n hasSpeaker: false,\n speaker: null,\n\n // IMU capabilities - head-up/head-down events only\n hasIMU: true,\n imu: null,\n\n // Button capabilities - capacitive touch areas on both arms\n hasButton: true,\n button: {\n count: 2,\n buttons: [\n {\n type: \"press\",\n events: [\"press\", \"double_press\", \"long_press\"],\n isCapacitive: true,\n },\n {\n type: \"press\",\n events: [\"press\", \"double_press\", \"long_press\"],\n isCapacitive: true,\n },\n ],\n },\n\n // Light capabilities - no lights\n hasLight: false,\n light: null,\n\n // Power capabilities\n power: {\n hasExternalBattery: false,\n },\n\n // WiFi capabilities - no WiFi\n hasWifi: false,\n\n // OTA capabilities - Nimo firmware updates are not driven by the ASG OTA flow\n hasOta: false,\n\n // The drivers flash a bundled Glassly CFW over the GATT OTA characteristics.\n hasCustomFirmware: true,\n}\n"]}
@@ -22,6 +22,7 @@ export declare enum ControllerTypes {
22
22
  GAMEBRICK = "IINE Gamebrick",
23
23
  IINE_ANANKE = "IINE Ananke Gen 2",
24
24
  ZERO2 = "8BitDo Zero 2",
25
- MICRO = "8BitDo Micro"
25
+ MICRO = "8BitDo Micro",
26
+ CRKD_ATOM_PLUS = "CRKD ATOM+"
26
27
  }
27
28
  //# sourceMappingURL=enums.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../src/types/enums.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAC,MAAM,2BAA2B,CAAA;AAEhF,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,SAAS,sBAAsB;IAC/B,IAAI,SAAS;IACb,EAAE,sBAAsB;IACxB,EAAE,sBAAsB;IACxB,IAAI,gBAAgB;IACpB,KAAK,iBAAiB;IACtB,IAAI,eAAe;IACnB,GAAG,mBAAmB;IACtB,IAAI,SAAS;IACb,KAAK,oBAAoB;IACzB,SAAS,cAAc;IACvB,YAAY,iBAAiB;CAC9B;AAED,oBAAY,eAAe;IACzB,EAAE,sBAAsB;IACxB,WAAW,qBAAqB;IAChC,WAAW,gBAAgB;IAC3B,OAAO,kBAAkB;IACzB,SAAS,mBAAmB;IAC5B,WAAW,sBAAsB;IACjC,KAAK,kBAAkB;IACvB,KAAK,iBAAiB;CACvB"}
1
+ {"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../src/types/enums.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAC,MAAM,2BAA2B,CAAA;AAEhF,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,SAAS,sBAAsB;IAC/B,IAAI,SAAS;IACb,EAAE,sBAAsB;IACxB,EAAE,sBAAsB;IACxB,IAAI,gBAAgB;IACpB,KAAK,iBAAiB;IACtB,IAAI,eAAe;IACnB,GAAG,mBAAmB;IACtB,IAAI,SAAS;IACb,KAAK,oBAAoB;IACzB,SAAS,cAAc;IACvB,YAAY,iBAAiB;CAC9B;AAED,oBAAY,eAAe;IACzB,EAAE,sBAAsB;IACxB,WAAW,qBAAqB;IAChC,WAAW,gBAAgB;IAC3B,OAAO,kBAAkB;IACzB,SAAS,mBAAmB;IAC5B,WAAW,sBAAsB;IACjC,KAAK,kBAAkB;IACvB,KAAK,iBAAiB;IACtB,cAAc,eAAe;CAC9B"}
@@ -25,5 +25,6 @@ export var ControllerTypes;
25
25
  ControllerTypes["IINE_ANANKE"] = "IINE Ananke Gen 2";
26
26
  ControllerTypes["ZERO2"] = "8BitDo Zero 2";
27
27
  ControllerTypes["MICRO"] = "8BitDo Micro";
28
+ ControllerTypes["CRKD_ATOM_PLUS"] = "CRKD ATOM+";
28
29
  })(ControllerTypes || (ControllerTypes = {}));
29
30
  //# sourceMappingURL=enums.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"enums.js","sourceRoot":"","sources":["../../src/types/enums.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAC,MAAM,2BAA2B,CAAA;AAEhF,MAAM,CAAN,IAAY,WAcX;AAdD,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,8CAA+B,CAAA;IAC/B,4BAAa,CAAA;IACb,uCAAwB,CAAA;IACxB,uCAAwB,CAAA;IACxB,mCAAoB,CAAA;IACpB,qCAAsB,CAAA;IACtB,kCAAmB,CAAA;IACnB,qCAAsB,CAAA;IACtB,4BAAa,CAAA;IACb,wCAAyB,CAAA;IACzB,sCAAuB,CAAA;IACvB,4CAA6B,CAAA;AAC/B,CAAC,EAdW,WAAW,KAAX,WAAW,QActB;AAED,MAAM,CAAN,IAAY,eASX;AATD,WAAY,eAAe;IACzB,2CAAwB,CAAA;IACxB,mDAAgC,CAAA;IAChC,8CAA2B,CAAA;IAC3B,4CAAyB,CAAA;IACzB,+CAA4B,CAAA;IAC5B,oDAAiC,CAAA;IACjC,0CAAuB,CAAA;IACvB,yCAAsB,CAAA;AACxB,CAAC,EATW,eAAe,KAAf,eAAe,QAS1B","sourcesContent":["export {HardwareType, HardwareRequirementLevel} from \"@glassly/miniapp/hardware\"\n\nexport enum DeviceTypes {\n NONE = \"None\",\n SIMULATED = \"Simulated Glasses\",\n AR99 = \"AR99\",\n G1 = \"Even Realities G1\",\n G2 = \"Even Realities G2\",\n LIVE = \"Mentra Live\",\n MACH1 = \"Mentra Mach1\",\n Z100 = \"Vuzix Z100\",\n NEX = \"Mentra Display\",\n NIMO = \"NIMO\",\n FRAME = \"Brilliant Frame\",\n RAYNEO_IO = \"RayNeo iO\",\n MEMOMIND_ONE = \"MemoMind One\",\n}\n\nexport enum ControllerTypes {\n R1 = \"Even Realities R1\",\n NEURAL_BAND = \"Meta Neural Band\",\n APPLE_WATCH = \"Apple Watch\",\n WEAR_OS = \"Wear OS Watch\",\n GAMEBRICK = \"IINE Gamebrick\",\n IINE_ANANKE = \"IINE Ananke Gen 2\",\n ZERO2 = \"8BitDo Zero 2\",\n MICRO = \"8BitDo Micro\",\n}\n"]}
1
+ {"version":3,"file":"enums.js","sourceRoot":"","sources":["../../src/types/enums.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAC,MAAM,2BAA2B,CAAA;AAEhF,MAAM,CAAN,IAAY,WAcX;AAdD,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,8CAA+B,CAAA;IAC/B,4BAAa,CAAA;IACb,uCAAwB,CAAA;IACxB,uCAAwB,CAAA;IACxB,mCAAoB,CAAA;IACpB,qCAAsB,CAAA;IACtB,kCAAmB,CAAA;IACnB,qCAAsB,CAAA;IACtB,4BAAa,CAAA;IACb,wCAAyB,CAAA;IACzB,sCAAuB,CAAA;IACvB,4CAA6B,CAAA;AAC/B,CAAC,EAdW,WAAW,KAAX,WAAW,QActB;AAED,MAAM,CAAN,IAAY,eAUX;AAVD,WAAY,eAAe;IACzB,2CAAwB,CAAA;IACxB,mDAAgC,CAAA;IAChC,8CAA2B,CAAA;IAC3B,4CAAyB,CAAA;IACzB,+CAA4B,CAAA;IAC5B,oDAAiC,CAAA;IACjC,0CAAuB,CAAA;IACvB,yCAAsB,CAAA;IACtB,gDAA6B,CAAA;AAC/B,CAAC,EAVW,eAAe,KAAf,eAAe,QAU1B","sourcesContent":["export {HardwareType, HardwareRequirementLevel} from \"@glassly/miniapp/hardware\"\n\nexport enum DeviceTypes {\n NONE = \"None\",\n SIMULATED = \"Simulated Glasses\",\n AR99 = \"AR99\",\n G1 = \"Even Realities G1\",\n G2 = \"Even Realities G2\",\n LIVE = \"Mentra Live\",\n MACH1 = \"Mentra Mach1\",\n Z100 = \"Vuzix Z100\",\n NEX = \"Mentra Display\",\n NIMO = \"NIMO\",\n FRAME = \"Brilliant Frame\",\n RAYNEO_IO = \"RayNeo iO\",\n MEMOMIND_ONE = \"MemoMind One\",\n}\n\nexport enum ControllerTypes {\n R1 = \"Even Realities R1\",\n NEURAL_BAND = \"Meta Neural Band\",\n APPLE_WATCH = \"Apple Watch\",\n WEAR_OS = \"Wear OS Watch\",\n GAMEBRICK = \"IINE Gamebrick\",\n IINE_ANANKE = \"IINE Ananke Gen 2\",\n ZERO2 = \"8BitDo Zero 2\",\n MICRO = \"8BitDo Micro\",\n CRKD_ATOM_PLUS = \"CRKD ATOM+\",\n}\n"]}
@@ -173,4 +173,5 @@ export declare function createNexToolkit(): {
173
173
  profile: DisplayProfile;
174
174
  };
175
175
  export { MEMOMIND_ONE_PROFILE } from "./profiles";
176
+ export { NIMO_PROFILE } from "./profiles";
176
177
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/display/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/display/index.ts"],"names":[],"mappings":"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"}
@@ -34,7 +34,7 @@
34
34
  // Profiles - Hardware configurations for different glasses
35
35
  // =============================================================================
36
36
  // Import for factory functions
37
- import { G1_PROFILE_LEGACY, G2_PROFILE, Z100_PROFILE, NEX_PROFILE } from "./profiles";
37
+ import { G1_PROFILE_LEGACY, G2_PROFILE, Z100_PROFILE, NEX_PROFILE, G1_PROFILE } from "./profiles";
38
38
  // =============================================================================
39
39
  // Convenience factory functions
40
40
  // =============================================================================
@@ -42,7 +42,6 @@ import { TextMeasurer } from "./measurer";
42
42
  import { TextWrapper } from "./wrapper";
43
43
  import { DisplayHelpers } from "./helpers";
44
44
  import { ColumnComposer } from "./composer";
45
- import { G1_PROFILE } from "./profiles";
46
45
  export { G1_PROFILE, G1_PROFILE_LEGACY, G1_HYPHEN_WIDTH_PX, G1_SPACE_WIDTH_PX } from "./profiles";
47
46
  // G2 Profile
48
47
  export { G2_PROFILE, G2_HYPHEN_WIDTH_PX, G2_SPACE_WIDTH_PX } from "./profiles";
@@ -188,4 +187,5 @@ export function createNexToolkit() {
188
187
  });
189
188
  }
190
189
  export { MEMOMIND_ONE_PROFILE } from "./profiles";
190
+ export { NIMO_PROFILE } from "./profiles";
191
191
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/display/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @glassly/display-utils\n *\n * Glasses-agnostic, pixel-accurate text measurement and wrapping library\n * for smart glasses displays.\n *\n * Key features:\n * - Pixel-perfect measurement (no abstract units or averages)\n * - Multiple break modes (character, word, strict-word)\n * - Full script support (Latin, CJK, Korean, Cyrillic)\n * - Configurable display profiles for different glasses hardware\n *\n * @example\n * ```typescript\n * import {\n * TextMeasurer,\n * TextWrapper,\n * DisplayHelpers,\n * G1_PROFILE\n * } from '@glassly/display-utils'\n *\n * // Create measurer and wrapper for G1 glasses\n * const measurer = new TextMeasurer(G1_PROFILE)\n * const wrapper = new TextWrapper(measurer, { breakMode: 'character' })\n * const helpers = new DisplayHelpers(measurer, wrapper)\n *\n * // Wrap text for display\n * const result = wrapper.wrap(\"Hello, world! This is a long text.\")\n * console.log(result.lines)\n * // [\"Hello, world! This is a long text th-\", \"at needs wrapping.\"]\n * ```\n */\n\n// =============================================================================\n// Profiles - Hardware configurations for different glasses\n// =============================================================================\n\n// Import for factory functions\nimport {G1_PROFILE_LEGACY, G2_PROFILE, Z100_PROFILE, NEX_PROFILE} from \"./profiles\"\n\n// =============================================================================\n// Convenience factory functions\n// =============================================================================\n\nimport {TextMeasurer} from \"./measurer\"\nimport {TextWrapper} from \"./wrapper\"\nimport {DisplayHelpers} from \"./helpers\"\nimport {ColumnComposer} from \"./composer\"\nimport {G1_PROFILE} from \"./profiles\"\nimport type {DisplayProfile} from \"./profiles\"\nimport type {WrapOptions} from \"./wrapper\"\n\nexport type {\n DisplayProfile,\n FontMetrics,\n UniformScriptWidths,\n FallbackConfig,\n DisplayConstraints,\n ScriptType,\n} from \"./profiles\"\n\nexport {G1_PROFILE, G1_PROFILE_LEGACY, G1_HYPHEN_WIDTH_PX, G1_SPACE_WIDTH_PX} from \"./profiles\"\n\n// G2 Profile\nexport {G2_PROFILE, G2_HYPHEN_WIDTH_PX, G2_SPACE_WIDTH_PX} from \"./profiles\"\n\n// Z100 Profile\nexport {Z100_PROFILE, Z100_HYPHEN_WIDTH_PX, Z100_SPACE_WIDTH_PX} from \"./profiles\"\n\n// Mentra Nex Profile (a.k.a. Mentra Display)\nexport {NEX_PROFILE, NEX_HYPHEN_WIDTH_PX, NEX_SPACE_WIDTH_PX} from \"./profiles\"\n\n// RayNeo iO Profiles (stock subtitle page, Glassly CFW scene page)\nexport {RAYNEO_IO_PROFILE, RAYNEO_IO_CFW_PROFILE, RAYNEO_IO_HYPHEN_WIDTH_PX, RAYNEO_IO_SPACE_WIDTH_PX} from \"./profiles\"\n\n// =============================================================================\n// Measurer - Pixel-accurate text measurement\n// =============================================================================\n\nexport {TextMeasurer} from \"./measurer\"\nexport type {CharMeasurement, TextMeasurement} from \"./measurer\"\n\n// Script detection utilities\nexport {\n detectScript,\n isCJKCharacter,\n isKoreanCharacter,\n isUniformWidthScript,\n isUnsupportedScript,\n needsHyphenForBreak,\n SCRIPT_RANGES,\n} from \"./measurer\"\n\n// =============================================================================\n// Wrapper - Text wrapping with multiple break modes\n// =============================================================================\n\nexport {TextWrapper} from \"./wrapper\"\nexport type {WrapOptions, WrapResult, LineMetrics, BreakMode} from \"./wrapper\"\nexport {DEFAULT_WRAP_OPTIONS} from \"./wrapper\"\n\n// =============================================================================\n// Helpers - Optional convenience utilities\n// =============================================================================\n\nexport {DisplayHelpers, ScrollView} from \"./helpers\"\nexport type {TruncateResult, Page, Chunk, ScrollPosition, ScrollViewport} from \"./helpers\"\n\n// =============================================================================\n// Composer - Multi-column layout composition\n// =============================================================================\n\nexport {ColumnComposer, createColumnComposer} from \"./composer\"\nexport type {ColumnConfig, ComposeOptions, ComposeResult} from \"./composer\"\n\n/**\n * Create a complete display toolkit for a given profile.\n *\n * @param profile - Display profile (defaults to G1)\n * @param wrapOptions - Default wrap options\n * @returns Object with measurer, wrapper, and helpers\n *\n * @example\n * ```typescript\n * const { measurer, wrapper, helpers } = createDisplayToolkit()\n * const lines = wrapper.wrapToLines(\"Hello, world!\")\n * ```\n */\nexport function createDisplayToolkit(\n profile: DisplayProfile = G1_PROFILE,\n wrapOptions?: WrapOptions,\n): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n const measurer = new TextMeasurer(profile)\n const wrapper = new TextWrapper(measurer, wrapOptions)\n const helpers = new DisplayHelpers(measurer, wrapper)\n const composer = new ColumnComposer(profile, wrapOptions?.breakMode || \"word\")\n\n return {\n measurer,\n wrapper,\n helpers,\n composer,\n profile,\n }\n}\n\n/**\n * Create a G1-configured display toolkit with character breaking.\n * This is the recommended setup for captions and similar high-utilization use cases.\n *\n * @returns Object with measurer, wrapper, and helpers configured for G1\n *\n * @example\n * ```typescript\n * const { wrapper, composer } = createG1Toolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * const columns = composer.composeDoubleTextWall(\"Left\", \"Right\")\n * ```\n */\nexport function createG1Toolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(G1_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a G1-configured display toolkit for LEGACY mobile clients.\n *\n * Use this when the mobile client has old wrapping logic that re-wraps\n * text received from the cloud. This profile uses a reduced display width\n * (~522px instead of 576px) to prevent double-wrapping overflow.\n *\n * @returns Object with measurer, wrapper, and helpers configured for legacy G1 clients\n *\n * @example\n * ```typescript\n * // For old mobile clients that double-wrap\n * const { wrapper } = createG1LegacyToolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * // Lines will be shorter to account for mobile re-wrapping\n * ```\n */\nexport function createG1LegacyToolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(G1_PROFILE_LEGACY, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a G2-configured display toolkit with character breaking.\n * G2 uses EvenHub protocol with the same display hardware as G1.\n *\n * @returns Object with measurer, wrapper, and helpers configured for Even G2\n *\n * @example\n * ```typescript\n * const { wrapper } = createG2Toolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * ```\n */\nexport function createG2Toolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(G2_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a Z100-configured display toolkit with character breaking.\n *\n * @returns Object with measurer, wrapper, and helpers configured for Vuzix Z100\n *\n * @example\n * ```typescript\n * const { wrapper } = createZ100Toolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * ```\n */\nexport function createZ100Toolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(Z100_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a Mentra Nex-configured display toolkit with character breaking.\n * Also known as \"Mentra Display\".\n *\n * @returns Object with measurer, wrapper, and helpers configured for Mentra Nex\n *\n * @example\n * ```typescript\n * const { wrapper } = createNexToolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * ```\n */\nexport function createNexToolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(NEX_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\nexport {MEMOMIND_ONE_PROFILE} from \"./profiles\"\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/display/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @glassly/display-utils\n *\n * Glasses-agnostic, pixel-accurate text measurement and wrapping library\n * for smart glasses displays.\n *\n * Key features:\n * - Pixel-perfect measurement (no abstract units or averages)\n * - Multiple break modes (character, word, strict-word)\n * - Full script support (Latin, CJK, Korean, Cyrillic)\n * - Configurable display profiles for different glasses hardware\n *\n * @example\n * ```typescript\n * import {\n * TextMeasurer,\n * TextWrapper,\n * DisplayHelpers,\n * G1_PROFILE\n * } from '@glassly/display-utils'\n *\n * // Create measurer and wrapper for G1 glasses\n * const measurer = new TextMeasurer(G1_PROFILE)\n * const wrapper = new TextWrapper(measurer, { breakMode: 'character' })\n * const helpers = new DisplayHelpers(measurer, wrapper)\n *\n * // Wrap text for display\n * const result = wrapper.wrap(\"Hello, world! This is a long text.\")\n * console.log(result.lines)\n * // [\"Hello, world! This is a long text th-\", \"at needs wrapping.\"]\n * ```\n */\n\n// =============================================================================\n// Profiles - Hardware configurations for different glasses\n// =============================================================================\n\n// Import for factory functions\nimport {G1_PROFILE_LEGACY, G2_PROFILE, Z100_PROFILE, NEX_PROFILE, G1_PROFILE} from \"./profiles\"\n\n// =============================================================================\n// Convenience factory functions\n// =============================================================================\n\nimport {TextMeasurer} from \"./measurer\"\nimport {TextWrapper} from \"./wrapper\"\nimport {DisplayHelpers} from \"./helpers\"\nimport {ColumnComposer} from \"./composer\"\nimport type {DisplayProfile} from \"./profiles\"\nimport type {WrapOptions} from \"./wrapper\"\n\nexport type {\n DisplayProfile,\n FontMetrics,\n UniformScriptWidths,\n FallbackConfig,\n DisplayConstraints,\n ScriptType,\n} from \"./profiles\"\n\nexport {G1_PROFILE, G1_PROFILE_LEGACY, G1_HYPHEN_WIDTH_PX, G1_SPACE_WIDTH_PX} from \"./profiles\"\n\n// G2 Profile\nexport {G2_PROFILE, G2_HYPHEN_WIDTH_PX, G2_SPACE_WIDTH_PX} from \"./profiles\"\n\n// Z100 Profile\nexport {Z100_PROFILE, Z100_HYPHEN_WIDTH_PX, Z100_SPACE_WIDTH_PX} from \"./profiles\"\n\n// Mentra Nex Profile (a.k.a. Mentra Display)\nexport {NEX_PROFILE, NEX_HYPHEN_WIDTH_PX, NEX_SPACE_WIDTH_PX} from \"./profiles\"\n\n// RayNeo iO Profiles (stock subtitle page, Glassly CFW scene page)\nexport {RAYNEO_IO_PROFILE, RAYNEO_IO_CFW_PROFILE, RAYNEO_IO_HYPHEN_WIDTH_PX, RAYNEO_IO_SPACE_WIDTH_PX} from \"./profiles\"\n\n// =============================================================================\n// Measurer - Pixel-accurate text measurement\n// =============================================================================\n\nexport {TextMeasurer} from \"./measurer\"\nexport type {CharMeasurement, TextMeasurement} from \"./measurer\"\n\n// Script detection utilities\nexport {\n detectScript,\n isCJKCharacter,\n isKoreanCharacter,\n isUniformWidthScript,\n isUnsupportedScript,\n needsHyphenForBreak,\n SCRIPT_RANGES,\n} from \"./measurer\"\n\n// =============================================================================\n// Wrapper - Text wrapping with multiple break modes\n// =============================================================================\n\nexport {TextWrapper} from \"./wrapper\"\nexport type {WrapOptions, WrapResult, LineMetrics, BreakMode} from \"./wrapper\"\nexport {DEFAULT_WRAP_OPTIONS} from \"./wrapper\"\n\n// =============================================================================\n// Helpers - Optional convenience utilities\n// =============================================================================\n\nexport {DisplayHelpers, ScrollView} from \"./helpers\"\nexport type {TruncateResult, Page, Chunk, ScrollPosition, ScrollViewport} from \"./helpers\"\n\n// =============================================================================\n// Composer - Multi-column layout composition\n// =============================================================================\n\nexport {ColumnComposer, createColumnComposer} from \"./composer\"\nexport type {ColumnConfig, ComposeOptions, ComposeResult} from \"./composer\"\n\n/**\n * Create a complete display toolkit for a given profile.\n *\n * @param profile - Display profile (defaults to G1)\n * @param wrapOptions - Default wrap options\n * @returns Object with measurer, wrapper, and helpers\n *\n * @example\n * ```typescript\n * const { measurer, wrapper, helpers } = createDisplayToolkit()\n * const lines = wrapper.wrapToLines(\"Hello, world!\")\n * ```\n */\nexport function createDisplayToolkit(\n profile: DisplayProfile = G1_PROFILE,\n wrapOptions?: WrapOptions,\n): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n const measurer = new TextMeasurer(profile)\n const wrapper = new TextWrapper(measurer, wrapOptions)\n const helpers = new DisplayHelpers(measurer, wrapper)\n const composer = new ColumnComposer(profile, wrapOptions?.breakMode || \"word\")\n\n return {\n measurer,\n wrapper,\n helpers,\n composer,\n profile,\n }\n}\n\n/**\n * Create a G1-configured display toolkit with character breaking.\n * This is the recommended setup for captions and similar high-utilization use cases.\n *\n * @returns Object with measurer, wrapper, and helpers configured for G1\n *\n * @example\n * ```typescript\n * const { wrapper, composer } = createG1Toolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * const columns = composer.composeDoubleTextWall(\"Left\", \"Right\")\n * ```\n */\nexport function createG1Toolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(G1_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a G1-configured display toolkit for LEGACY mobile clients.\n *\n * Use this when the mobile client has old wrapping logic that re-wraps\n * text received from the cloud. This profile uses a reduced display width\n * (~522px instead of 576px) to prevent double-wrapping overflow.\n *\n * @returns Object with measurer, wrapper, and helpers configured for legacy G1 clients\n *\n * @example\n * ```typescript\n * // For old mobile clients that double-wrap\n * const { wrapper } = createG1LegacyToolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * // Lines will be shorter to account for mobile re-wrapping\n * ```\n */\nexport function createG1LegacyToolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(G1_PROFILE_LEGACY, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a G2-configured display toolkit with character breaking.\n * G2 uses EvenHub protocol with the same display hardware as G1.\n *\n * @returns Object with measurer, wrapper, and helpers configured for Even G2\n *\n * @example\n * ```typescript\n * const { wrapper } = createG2Toolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * ```\n */\nexport function createG2Toolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(G2_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a Z100-configured display toolkit with character breaking.\n *\n * @returns Object with measurer, wrapper, and helpers configured for Vuzix Z100\n *\n * @example\n * ```typescript\n * const { wrapper } = createZ100Toolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * ```\n */\nexport function createZ100Toolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(Z100_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\n/**\n * Create a Mentra Nex-configured display toolkit with character breaking.\n * Also known as \"Mentra Display\".\n *\n * @returns Object with measurer, wrapper, and helpers configured for Mentra Nex\n *\n * @example\n * ```typescript\n * const { wrapper } = createNexToolkit()\n * const result = wrapper.wrap(\"Your text here\")\n * ```\n */\nexport function createNexToolkit(): {\n measurer: TextMeasurer\n wrapper: TextWrapper\n helpers: DisplayHelpers\n composer: ColumnComposer\n profile: DisplayProfile\n} {\n return createDisplayToolkit(NEX_PROFILE, {\n breakMode: \"character-no-hyphen\",\n })\n}\n\nexport {MEMOMIND_ONE_PROFILE} from \"./profiles\"\nexport {NIMO_PROFILE} from \"./profiles\"\n"]}
@@ -11,4 +11,5 @@ export { G2_PROFILE, G2_HYPHEN_WIDTH_PX, G2_SPACE_WIDTH_PX } from "./g2";
11
11
  export { NEX_PROFILE, NEX_HYPHEN_WIDTH_PX, NEX_SPACE_WIDTH_PX } from "./nex";
12
12
  export { RAYNEO_IO_PROFILE, RAYNEO_IO_CFW_PROFILE, RAYNEO_IO_HYPHEN_WIDTH_PX, RAYNEO_IO_SPACE_WIDTH_PX, } from "./rayneo-io";
13
13
  export { MEMOMIND_ONE_PROFILE } from "@glassly/miniapp/display";
14
+ export { NIMO_PROFILE } from "./nimo";
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/display/profiles/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,UAAU,GACX,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAC,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAGzF,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAC,MAAM,QAAQ,CAAA;AAG9E,OAAO,EAAC,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAGtE,OAAO,EAAC,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,OAAO,CAAA;AAG1E,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAC,oBAAoB,EAAC,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/display/profiles/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,UAAU,GACX,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAC,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAGzF,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAC,MAAM,QAAQ,CAAA;AAG9E,OAAO,EAAC,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAGtE,OAAO,EAAC,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,OAAO,CAAA;AAG1E,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAC,oBAAoB,EAAC,MAAM,0BAA0B,CAAA;AAE7D,OAAO,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAA"}
@@ -15,4 +15,5 @@ export { NEX_PROFILE, NEX_HYPHEN_WIDTH_PX, NEX_SPACE_WIDTH_PX } from "./nex";
15
15
  // RayNeo iO Profiles (stock subtitle page, Glassly CFW scene page)
16
16
  export { RAYNEO_IO_PROFILE, RAYNEO_IO_CFW_PROFILE, RAYNEO_IO_HYPHEN_WIDTH_PX, RAYNEO_IO_SPACE_WIDTH_PX, } from "./rayneo-io";
17
17
  export { MEMOMIND_ONE_PROFILE } from "@glassly/miniapp/display";
18
+ export { NIMO_PROFILE } from "./nimo";
18
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/display/profiles/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,cAAc;AACd,OAAO,EAAC,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAEzF,eAAe;AACf,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAC,MAAM,QAAQ,CAAA;AAE9E,aAAa;AACb,OAAO,EAAC,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAEtE,6CAA6C;AAC7C,OAAO,EAAC,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,OAAO,CAAA;AAE1E,mEAAmE;AACnE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAC,oBAAoB,EAAC,MAAM,0BAA0B,CAAA","sourcesContent":["/**\n * Display Profiles\n *\n * Hardware-specific configurations for smart glasses displays.\n * Each profile defines display dimensions, font metrics, and constraints.\n */\n\n// Types\nexport type {\n DisplayProfile,\n FontMetrics,\n UniformScriptWidths,\n FallbackConfig,\n DisplayConstraints,\n ScriptType,\n} from \"./types\"\n\n// G1 Profiles\nexport {G1_PROFILE, G1_PROFILE_LEGACY, G1_HYPHEN_WIDTH_PX, G1_SPACE_WIDTH_PX} from \"./g1\"\n\n// Z100 Profile\nexport {Z100_PROFILE, Z100_HYPHEN_WIDTH_PX, Z100_SPACE_WIDTH_PX} from \"./z100\"\n\n// G2 Profile\nexport {G2_PROFILE, G2_HYPHEN_WIDTH_PX, G2_SPACE_WIDTH_PX} from \"./g2\"\n\n// Mentra Nex Profile (a.k.a. Mentra Display)\nexport {NEX_PROFILE, NEX_HYPHEN_WIDTH_PX, NEX_SPACE_WIDTH_PX} from \"./nex\"\n\n// RayNeo iO Profiles (stock subtitle page, Glassly CFW scene page)\nexport {\n RAYNEO_IO_PROFILE,\n RAYNEO_IO_CFW_PROFILE,\n RAYNEO_IO_HYPHEN_WIDTH_PX,\n RAYNEO_IO_SPACE_WIDTH_PX,\n} from \"./rayneo-io\"\n\nexport {MEMOMIND_ONE_PROFILE} from \"@glassly/miniapp/display\"\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/display/profiles/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,cAAc;AACd,OAAO,EAAC,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAEzF,eAAe;AACf,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAC,MAAM,QAAQ,CAAA;AAE9E,aAAa;AACb,OAAO,EAAC,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA;AAEtE,6CAA6C;AAC7C,OAAO,EAAC,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,OAAO,CAAA;AAE1E,mEAAmE;AACnE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAC,oBAAoB,EAAC,MAAM,0BAA0B,CAAA;AAE7D,OAAO,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAA","sourcesContent":["/**\n * Display Profiles\n *\n * Hardware-specific configurations for smart glasses displays.\n * Each profile defines display dimensions, font metrics, and constraints.\n */\n\n// Types\nexport type {\n DisplayProfile,\n FontMetrics,\n UniformScriptWidths,\n FallbackConfig,\n DisplayConstraints,\n ScriptType,\n} from \"./types\"\n\n// G1 Profiles\nexport {G1_PROFILE, G1_PROFILE_LEGACY, G1_HYPHEN_WIDTH_PX, G1_SPACE_WIDTH_PX} from \"./g1\"\n\n// Z100 Profile\nexport {Z100_PROFILE, Z100_HYPHEN_WIDTH_PX, Z100_SPACE_WIDTH_PX} from \"./z100\"\n\n// G2 Profile\nexport {G2_PROFILE, G2_HYPHEN_WIDTH_PX, G2_SPACE_WIDTH_PX} from \"./g2\"\n\n// Mentra Nex Profile (a.k.a. Mentra Display)\nexport {NEX_PROFILE, NEX_HYPHEN_WIDTH_PX, NEX_SPACE_WIDTH_PX} from \"./nex\"\n\n// RayNeo iO Profiles (stock subtitle page, Glassly CFW scene page)\nexport {\n RAYNEO_IO_PROFILE,\n RAYNEO_IO_CFW_PROFILE,\n RAYNEO_IO_HYPHEN_WIDTH_PX,\n RAYNEO_IO_SPACE_WIDTH_PX,\n} from \"./rayneo-io\"\n\nexport {MEMOMIND_ONE_PROFILE} from \"@glassly/miniapp/display\"\n\nexport {NIMO_PROFILE} from \"./nimo\"\n"]}
@@ -0,0 +1,2 @@
1
+ export { NIMO_PROFILE } from "@glassly/miniapp/display";
2
+ //# sourceMappingURL=nimo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nimo.d.ts","sourceRoot":"","sources":["../../../../src/utils/display/profiles/nimo.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,3 @@
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";
3
+ //# sourceMappingURL=nimo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nimo.js","sourceRoot":"","sources":["../../../../src/utils/display/profiles/nimo.ts"],"names":[],"mappings":"AAAA,+IAA+I;AAC/I,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAA","sourcesContent":["// 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.\nexport {NIMO_PROFILE} from \"@glassly/miniapp/display\"\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"svgPath.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/svgPath.ts"],"names":[],"mappings":"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","sourcesContent":["/** SVG path compiler shared by scene validation and native wire encoding.\n * Ported from g2flash revision 21; no DOM, Node or mobile-platform dependencies. */\nconst u16 = (v: number) => [v & 255, (v >>> 8) & 255]\nfunction integer(v: number, min: number, max: number, name: string): number {\n if (!Number.isInteger(v) || v < min || v > max) throw new Error(`${name} outside ${min}..${max}: ${v}`)\n return v\n}\n/** SVG d subset: absolute/relative M L H V Q C S T Z; implicit repetitions.\n * Unsupported syntax is rejected. Each filled contour must explicitly close. */\nexport function svgPath(d: string): number[] {\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g) ?? []\n const residue = d.replace(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g, \"\")\n if (/[^\\s,]/.test(residue)) throw new Error(\"Invalid SVG path syntax\")\n let i = 0,\n cmd = \"\",\n x = 0,\n y = 0,\n sx = 0,\n sy = 0,\n open = false,\n previous = \"\"\n let cx = 0,\n cy = 0\n const out: number[] = []\n const emit = (op: number, ...coords: number[]) => {\n out.push(op, ...coords.flatMap((v) => u16(integer(Math.round(v * 16), -32768, 32767, \"Q4 coordinate\"))))\n }\n const number = () => {\n if (i >= tokens.length || /^[a-z]$/i.test(tokens[i])) throw new Error(\"Missing SVG coordinate\")\n const v = Number(tokens[i++])\n if (!Number.isFinite(v)) throw new Error(\"Invalid number\")\n return v\n }\n while (i < tokens.length) {\n if (/^[a-z]$/i.test(tokens[i])) cmd = tokens[i++]\n if (!cmd || !/^[MLHVQCSTZ]$/i.test(cmd)) throw new Error(`Unsupported SVG command: ${cmd}`)\n const op = cmd.toUpperCase(),\n rel = cmd !== op\n const pair = (): [number, number] => [number() + (rel ? x : 0), number() + (rel ? y : 0)]\n if (op === \"Z\") {\n if (!open) throw new Error(\"Z without an open contour\")\n emit(4)\n x = sx\n y = sy\n open = false\n previous = \"Z\"\n cmd = \"\"\n continue\n }\n if (op !== \"M\" && !open) throw new Error(\"Path must start with M\")\n if (op === \"M\") {\n if (open) throw new Error(\"Filled contours must close with Z before another M\")\n ;[x, y] = pair()\n sx = x\n sy = y\n open = true\n emit(0, x, y)\n cmd = rel ? \"l\" : \"L\"\n } else if (op === \"L\" || op === \"H\" || op === \"V\") {\n if (op === \"L\") [x, y] = pair()\n else if (op === \"H\") x = number() + (rel ? x : 0)\n else y = number() + (rel ? y : 0)\n emit(1, x, y)\n } else if (op === \"Q\" || op === \"T\") {\n const c = op === \"Q\" ? pair() : previous === \"Q\" || previous === \"T\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const end = pair()\n emit(2, ...c, ...end)\n ;[cx, cy] = c\n ;[x, y] = end\n } else {\n const a = op === \"C\" ? pair() : previous === \"C\" || previous === \"S\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const b = pair(),\n end = pair()\n emit(3, ...a, ...b, ...end)\n ;[cx, cy] = b\n ;[x, y] = end\n }\n previous = op\n }\n if (open || !out.length) throw new Error(\"Expected explicitly closed filled path\")\n return out\n}\n\n/** Check the same fixed-point subdivision and budgets as revision 21 firmware. */\nexport function compileSvgPath(d: string): {commands: number[]; edges: number} {\n if (typeof d !== \"string\" || d.length > 65536) throw new Error(\"Invalid SVG path data\")\n const commands = svgPath(d)\n if (commands.length > 8192) throw new Error(\"SVG path exceeds 8192 command bytes\")\n let edges = 0,\n count = 0,\n x = 0,\n y = 0,\n sx = 0,\n sy = 0\n const edge = (ax: number, ay: number, bx: number, by: number) => {\n if ((ax !== bx || ay !== by) && ++edges > 512) throw new Error(\"SVG path exceeds 512 compiled edges\")\n }\n const curve = (p: number[], depth: number): void => {\n const u = [\n 3 * p[2] - 2 * p[0] - p[6],\n 3 * p[3] - 2 * p[1] - p[7],\n 3 * p[4] - 2 * p[6] - p[0],\n 3 * p[5] - 2 * p[7] - p[1],\n ]\n if (u.every((v) => Math.abs(v) <= 16)) {\n edge(p[0], p[1], p[6], p[7])\n return\n }\n if (depth === 8) throw new Error(\"SVG curve exceeds subdivision limit\")\n const a = new Array<number>(8),\n b = new Array<number>(8)\n for (let k = 0; k < 2; k++) {\n const ab = Math.trunc((p[k] + p[k + 2]) / 2),\n bc = Math.trunc((p[k + 2] + p[k + 4]) / 2),\n cd = Math.trunc((p[k + 4] + p[k + 6]) / 2)\n const abc = Math.trunc((ab + bc) / 2),\n bcd = Math.trunc((bc + cd) / 2),\n mid = Math.trunc((abc + bcd) / 2)\n a[k] = p[k]\n a[k + 2] = ab\n a[k + 4] = abc\n a[k + 6] = mid\n b[k] = mid\n b[k + 2] = bcd\n b[k + 4] = cd\n b[k + 6] = p[k + 6]\n }\n curve(a, depth + 1)\n curve(b, depth + 1)\n }\n for (let i = 0; i < commands.length; ) {\n const op = commands[i++],\n pairs = op === 4 ? 0 : op === 3 ? 3 : op === 2 ? 2 : 1\n if (++count > 1024) throw new Error(\"SVG path exceeds 1024 commands\")\n const p = [x, y]\n for (let k = 0; k < pairs * 2; k++, i += 2) p.push(((commands[i] | (commands[i + 1] << 8)) << 16) >> 16)\n if (op === 0) {\n x = sx = p[2]\n y = sy = p[3]\n } else if (op === 4) {\n edge(x, y, sx, sy)\n x = sx\n y = sy\n } else if (op === 1) {\n edge(x, y, p[2], p[3])\n x = p[2]\n y = p[3]\n } else {\n if (op === 2) {\n p[6] = p[4]\n p[7] = p[5]\n for (let k = 0; k < 2; k++) {\n p[k + 4] = Math.trunc((p[k + 6] + 2 * p[k + 2]) / 3)\n p[k + 2] = Math.trunc((p[k] + 2 * p[k + 2]) / 3)\n }\n }\n curve(p, 0)\n x = p[6]\n y = p[7]\n }\n }\n return {commands, edges}\n}\n"]}
1
+ {"version":3,"file":"svgPath.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/svgPath.ts"],"names":[],"mappings":"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","sourcesContent":["/** SVG path compiler shared by scene validation and native wire encoding.\n * Ported from g2flash revision 21; no DOM, Node or mobile-platform dependencies. */\nconst u16 = (v: number) => [v & 255, (v >>> 8) & 255]\nfunction integer(v: number, min: number, max: number, name: string): number {\n if (!Number.isInteger(v) || v < min || v > max) throw new Error(`${name} outside ${min}..${max}: ${v}`)\n return v\n}\n/** SVG d subset: absolute/relative M L H V Q C S T Z; implicit repetitions.\n * Unsupported syntax is rejected. Each filled contour must explicitly close. */\nexport function svgPath(d: string): number[] {\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g) ?? []\n const residue = d.replace(/[a-zA-Z]|[-+]?(?:\\d*\\.\\d+|\\d+\\.?\\d*)(?:[eE][-+]?\\d+)?/g, \"\")\n if (/[^\\s,]/.test(residue)) throw new Error(\"Invalid SVG path syntax\")\n let i = 0,\n cmd = \"\",\n x = 0,\n y = 0,\n sx = 0,\n sy = 0,\n open = false,\n previous = \"\"\n let cx = 0,\n cy = 0\n const out: number[] = []\n const emit = (op: number, ...coords: number[]) => {\n out.push(op, ...coords.flatMap((v) => u16(integer(Math.round(v * 16), -32768, 32767, \"Q4 coordinate\"))))\n }\n const number = () => {\n if (i >= tokens.length || /^[a-z]$/i.test(tokens[i])) throw new Error(\"Missing SVG coordinate\")\n const v = Number(tokens[i++])\n if (!Number.isFinite(v)) throw new Error(\"Invalid number\")\n return v\n }\n while (i < tokens.length) {\n if (/^[a-z]$/i.test(tokens[i])) cmd = tokens[i++]\n if (!cmd || !/^[MLHVQCSTZ]$/i.test(cmd)) throw new Error(`Unsupported SVG command: ${cmd}`)\n const op = cmd.toUpperCase(),\n rel = cmd !== op\n const pair = (): [number, number] => [number() + (rel ? x : 0), number() + (rel ? y : 0)]\n if (op === \"Z\") {\n if (!open) throw new Error(\"Z without an open contour\")\n emit(4)\n x = sx\n y = sy\n open = false\n previous = \"Z\"\n cmd = \"\"\n continue\n }\n if (op !== \"M\" && !open) throw new Error(\"Path must start with M\")\n if (op === \"M\") {\n if (open) throw new Error(\"Filled contours must close with Z before another M\")\n ;[x, y] = pair()\n sx = x\n sy = y\n open = true\n emit(0, x, y)\n cmd = rel ? \"l\" : \"L\"\n } else if (op === \"L\" || op === \"H\" || op === \"V\") {\n if (op === \"L\") [x, y] = pair()\n else if (op === \"H\") x = number() + (rel ? x : 0)\n else y = number() + (rel ? y : 0)\n emit(1, x, y)\n } else if (op === \"Q\" || op === \"T\") {\n const c = op === \"Q\" ? pair() : previous === \"Q\" || previous === \"T\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const end = pair()\n emit(2, ...c, ...end)\n ;[cx, cy] = c\n ;[x, y] = end\n } else {\n const a = op === \"C\" ? pair() : previous === \"C\" || previous === \"S\" ? [2 * x - cx, 2 * y - cy] : [x, y]\n const b = pair(),\n end = pair()\n emit(3, ...a, ...b, ...end)\n ;[cx, cy] = b\n ;[x, y] = end\n }\n previous = op\n }\n if (open || !out.length) throw new Error(\"Expected explicitly closed filled path\")\n return out\n}\n\n/** Check the same fixed-point subdivision and budgets as revision 21 firmware. */\nexport function compileSvgPath(d: string): {commands: number[]; edges: number} {\n if (typeof d !== \"string\" || d.length > 65536) throw new Error(\"Invalid SVG path data\")\n const commands = svgPath(d)\n if (commands.length > 8192) throw new Error(\"SVG path exceeds 8192 command bytes\")\n let edges = 0,\n count = 0,\n x = 0,\n y = 0,\n sx = 0,\n sy = 0\n const edge = (ax: number, ay: number, bx: number, by: number) => {\n if ((ax !== bx || ay !== by) && ++edges > 512) throw new Error(\"SVG path exceeds 512 compiled edges\")\n }\n const curve = (p: number[], depth: number): void => {\n const u = [\n 3 * p[2] - 2 * p[0] - p[6],\n 3 * p[3] - 2 * p[1] - p[7],\n 3 * p[4] - 2 * p[6] - p[0],\n 3 * p[5] - 2 * p[7] - p[1],\n ]\n if (u.every((v) => Math.abs(v) <= 16)) {\n edge(p[0], p[1], p[6], p[7])\n return\n }\n if (depth === 8) throw new Error(\"SVG curve exceeds subdivision limit\")\n const a = new Array<number>(8),\n b = new Array<number>(8)\n for (let k = 0; k < 2; k++) {\n const ab = Math.trunc((p[k] + p[k + 2]) / 2),\n bc = Math.trunc((p[k + 2] + p[k + 4]) / 2),\n cd = Math.trunc((p[k + 4] + p[k + 6]) / 2)\n const abc = Math.trunc((ab + bc) / 2),\n bcd = Math.trunc((bc + cd) / 2),\n mid = Math.trunc((abc + bcd) / 2)\n a[k] = p[k]\n a[k + 2] = ab\n a[k + 4] = abc\n a[k + 6] = mid\n b[k] = mid\n b[k + 2] = bcd\n b[k + 4] = cd\n b[k + 6] = p[k + 6]\n }\n curve(a, depth + 1)\n curve(b, depth + 1)\n }\n for (let i = 0; i < commands.length;) {\n const op = commands[i++],\n pairs = op === 4 ? 0 : op === 3 ? 3 : op === 2 ? 2 : 1\n if (++count > 1024) throw new Error(\"SVG path exceeds 1024 commands\")\n const p = [x, y]\n for (let k = 0; k < pairs * 2; k++, i += 2) p.push(((commands[i] | (commands[i + 1] << 8)) << 16) >> 16)\n if (op === 0) {\n x = sx = p[2]\n y = sy = p[3]\n } else if (op === 4) {\n edge(x, y, sx, sy)\n x = sx\n y = sy\n } else if (op === 1) {\n edge(x, y, p[2], p[3])\n x = p[2]\n y = p[3]\n } else {\n if (op === 2) {\n p[6] = p[4]\n p[7] = p[5]\n for (let k = 0; k < 2; k++) {\n p[k + 4] = Math.trunc((p[k + 6] + 2 * p[k + 2]) / 3)\n p[k + 2] = Math.trunc((p[k] + 2 * p[k + 2]) / 3)\n }\n }\n curve(p, 0)\n x = p[6]\n y = p[7]\n }\n }\n return {commands, edges}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,qEAAqE;IACrE,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;AAKD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,qBAAqB,EACjE,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,CAAC,EAAE,iBAAiB,GACnB,kBAAkB,CAAC,CAAC,CAAC,CAqBvB;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAO/C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAqB7E;AAWD,+CAA+C;AAC/C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAc5C"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,qEAAqE;IACrE,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;AAKD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,qBAAqB,EACjE,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,CAAC,EAAE,iBAAiB,GACnB,kBAAkB,CAAC,CAAC,CAAC,CAmBvB;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAO/C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAqB7E;AAuBD,+CAA+C;AAC/C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAc5C"}
@@ -31,9 +31,7 @@ export function searchMemoryEntries(entries, q) {
31
31
  const hi = upperBound(entries, until); // exclusive
32
32
  const windowCount = Math.max(0, hi - lo);
33
33
  const needle = q.contains?.trim().toLowerCase() || null;
34
- const termWords = (q.terms ?? [])
35
- .map((t) => tokenize(t))
36
- .filter((words) => words.length > 0);
34
+ const termWords = (q.terms ?? []).map((t) => tokenize(t)).filter((words) => words.length > 0);
37
35
  const picked = [];
38
36
  for (let i = hi - 1; i >= lo && picked.length < q.limit; i--) {
39
37
  const e = entries[i];
@@ -123,11 +121,23 @@ export function editDistanceAtMost(a, b, max) {
123
121
  return prev[b.length] <= max;
124
122
  }
125
123
  const SOUNDEX_CODES = {
126
- b: "1", f: "1", p: "1", v: "1",
127
- c: "2", g: "2", j: "2", k: "2", q: "2", s: "2", x: "2", z: "2",
128
- d: "3", t: "3",
124
+ b: "1",
125
+ f: "1",
126
+ p: "1",
127
+ v: "1",
128
+ c: "2",
129
+ g: "2",
130
+ j: "2",
131
+ k: "2",
132
+ q: "2",
133
+ s: "2",
134
+ x: "2",
135
+ z: "2",
136
+ d: "3",
137
+ t: "3",
129
138
  l: "4",
130
- m: "5", n: "5",
139
+ m: "5",
140
+ n: "5",
131
141
  r: "6",
132
142
  };
133
143
  /** Classic Soundex. Empty input returns "". */
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure memory-timeline search — the matching engine behind MemoryStore.query\n * and the assistant's get_transcripts tool.\n *\n * Lives outside MemoryStore so it is unit-testable and importable by the\n * assistant's eval harness (which replays the exact host semantics against a\n * mock corpus). Keep it dependency-free and runtime-neutral: it also runs\n * under bun for tests.\n *\n * TWO MATCH MODES, deliberately different:\n * - `contains`: exact case-insensitive substring — the pre-existing contract,\n * kept verbatim for callers that need precision (codes, URLs, exact phrases).\n * - `terms`: ANY-of term matching with per-word fuzziness. Speech-to-text\n * mangles proper nouns (\"Sompo\" for \"Sampo\", \"Korwin\" for \"Corwin\"), so a\n * term word matches a transcript token on exact/substring, small edit\n * distance, OR same Soundex key. A multi-word term (\"ring size\") requires\n * all of its words to match somewhere in the entry.\n *\n * The scan walks BACKWARDS from the newest in-window entry and stops at\n * `limit` matches: the caller keeps the most recent matches anyway, and the\n * common \"last 90 minutes\" query then touches dozens of entries instead of\n * the full 4000-entry timeline. Window bounds are found by binary search on\n * `at` (the timeline is maintained time-sorted).\n */\n\nexport interface MemorySearchableEntry {\n text: string\n at: number\n}\n\nexport interface MemorySearchQuery {\n /** Epoch ms lower bound (inclusive). */\n sinceMs?: number\n /** Epoch ms upper bound (inclusive). */\n untilMs?: number\n /** Exact case-insensitive substring filter. */\n contains?: string\n /** Fuzzy any-of terms (see file header). Combined with `contains` as AND. */\n terms?: string[]\n /** Max matches kept (newest win). Caller enforces its own cap. */\n limit: number\n}\n\nexport interface MemorySearchResult<T> {\n /** Matches in chronological order (newest last), at most `limit`. */\n entries: T[]\n /**\n * Entries inside the TIME window before keyword filtering. Lets the caller\n * tell \"keyword matched nothing\" apart from \"window itself is empty\" — the\n * distinction that saves an LLM a blind retry round.\n */\n windowCount: number\n}\n\n/** Tokenized lowercase text per entry, cached for the entry object's lifetime. */\nconst tokenCache = new WeakMap<object, string[]>()\n\nexport function searchMemoryEntries<T extends MemorySearchableEntry>(\n entries: readonly T[],\n q: MemorySearchQuery,\n): MemorySearchResult<T> {\n const since = q.sinceMs ?? 0\n const until = q.untilMs ?? Number.MAX_SAFE_INTEGER\n const lo = lowerBound(entries, since)\n const hi = upperBound(entries, until) // exclusive\n const windowCount = Math.max(0, hi - lo)\n\n const needle = q.contains?.trim().toLowerCase() || null\n const termWords = (q.terms ?? [])\n .map((t) => tokenize(t))\n .filter((words) => words.length > 0)\n\n const picked: T[] = []\n for (let i = hi - 1; i >= lo && picked.length < q.limit; i--) {\n const e = entries[i]\n if (needle && !e.text.toLowerCase().includes(needle)) continue\n if (termWords.length > 0 && !matchesAnyTerm(e, termWords)) continue\n picked.push(e)\n }\n picked.reverse()\n return {entries: picked, windowCount}\n}\n\n/** True when any term matches — a term matches iff ALL its words match a token. */\nfunction matchesAnyTerm(entry: MemorySearchableEntry, termWords: string[][]): boolean {\n let tokens = tokenCache.get(entry)\n if (!tokens) {\n tokens = tokenize(entry.text)\n tokenCache.set(entry, tokens)\n }\n outer: for (const words of termWords) {\n for (const word of words) {\n if (!tokens.some((tok) => fuzzyWordMatch(word, tok))) continue outer\n }\n return true\n }\n return false\n}\n\n/**\n * Does query word `w` match transcript token `t`?\n * - exact, or substring for w of 3+ chars (\"kestrel\" in \"kestrels\")\n * - for words of 5+ chars: bounded edit distance (1, or 2 for 7+ chars)\n * — catches one-vowel STT swaps (\"sompo\"/\"sampo\", \"korwin\"/\"corwin\").\n * 5 is the floor because at 4 chars a one-edit radius swallows unrelated\n * common words (\"code\"→\"mode\"); mistranscribed NAMES are almost always 5+.\n * - same Soundex key with similar length — catches phonetic respellings that\n * edit distance misses (\"warryn\"/\"warren\" style doublings)\n */\nexport function fuzzyWordMatch(w: string, t: string): boolean {\n if (w === t) return true\n if (w.length >= 3 && t.includes(w)) return true\n if (w.length < 5 || t.length < 4) return false\n const maxDist = w.length >= 7 ? 2 : 1\n if (Math.abs(w.length - t.length) <= maxDist && editDistanceAtMost(w, t, maxDist)) return true\n return Math.abs(w.length - t.length) <= 2 && soundex(w) === soundex(t)\n}\n\n/** Lowercase, strip diacritics, split on non-alphanumerics. */\nexport function tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 0)\n}\n\n/**\n * Optimal-string-alignment edit distance, early-exited: returns whether\n * dist(a, b) <= max. Transpositions count as one edit (common in STT output).\n */\nexport function editDistanceAtMost(a: string, b: string, max: number): boolean {\n if (Math.abs(a.length - b.length) > max) return false\n let prev2: number[] | null = null\n let prev = Array.from({length: b.length + 1}, (_, j) => j)\n for (let i = 1; i <= a.length; i++) {\n const cur = [i]\n let rowMin = i\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n let v = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost)\n if (prev2 && i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n v = Math.min(v, prev2[j - 2] + 1)\n }\n cur.push(v)\n if (v < rowMin) rowMin = v\n }\n if (rowMin > max) return false\n prev2 = prev\n prev = cur\n }\n return prev[b.length] <= max\n}\n\nconst SOUNDEX_CODES: Record<string, string> = {\n b: \"1\", f: \"1\", p: \"1\", v: \"1\",\n c: \"2\", g: \"2\", j: \"2\", k: \"2\", q: \"2\", s: \"2\", x: \"2\", z: \"2\",\n d: \"3\", t: \"3\",\n l: \"4\",\n m: \"5\", n: \"5\",\n r: \"6\",\n}\n\n/** Classic Soundex. Empty input returns \"\". */\nexport function soundex(word: string): string {\n const w = word.toLowerCase().replace(/[^a-z]/g, \"\")\n if (!w) return \"\"\n let out = w[0].toUpperCase()\n let lastCode = SOUNDEX_CODES[w[0]] ?? \"\"\n for (let i = 1; i < w.length && out.length < 4; i++) {\n const ch = w[i]\n const code = SOUNDEX_CODES[ch] ?? \"\"\n // h/w are transparent: they don't reset the adjacent-duplicate rule.\n if (ch === \"h\" || ch === \"w\") continue\n if (code && code !== lastCode) out += code\n lastCode = code\n }\n return out.padEnd(4, \"0\")\n}\n\n/** First index with at >= value (entries time-sorted ascending). */\nfunction lowerBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at < value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\n/** First index with at > value (i.e. exclusive end for an inclusive bound). */\nfunction upperBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at <= value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n"]}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/utils/memory/search.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure memory-timeline search — the matching engine behind MemoryStore.query\n * and the assistant's get_transcripts tool.\n *\n * Lives outside MemoryStore so it is unit-testable and importable by the\n * assistant's eval harness (which replays the exact host semantics against a\n * mock corpus). Keep it dependency-free and runtime-neutral: it also runs\n * under bun for tests.\n *\n * TWO MATCH MODES, deliberately different:\n * - `contains`: exact case-insensitive substring — the pre-existing contract,\n * kept verbatim for callers that need precision (codes, URLs, exact phrases).\n * - `terms`: ANY-of term matching with per-word fuzziness. Speech-to-text\n * mangles proper nouns (\"Sompo\" for \"Sampo\", \"Korwin\" for \"Corwin\"), so a\n * term word matches a transcript token on exact/substring, small edit\n * distance, OR same Soundex key. A multi-word term (\"ring size\") requires\n * all of its words to match somewhere in the entry.\n *\n * The scan walks BACKWARDS from the newest in-window entry and stops at\n * `limit` matches: the caller keeps the most recent matches anyway, and the\n * common \"last 90 minutes\" query then touches dozens of entries instead of\n * the full 4000-entry timeline. Window bounds are found by binary search on\n * `at` (the timeline is maintained time-sorted).\n */\n\nexport interface MemorySearchableEntry {\n text: string\n at: number\n}\n\nexport interface MemorySearchQuery {\n /** Epoch ms lower bound (inclusive). */\n sinceMs?: number\n /** Epoch ms upper bound (inclusive). */\n untilMs?: number\n /** Exact case-insensitive substring filter. */\n contains?: string\n /** Fuzzy any-of terms (see file header). Combined with `contains` as AND. */\n terms?: string[]\n /** Max matches kept (newest win). Caller enforces its own cap. */\n limit: number\n}\n\nexport interface MemorySearchResult<T> {\n /** Matches in chronological order (newest last), at most `limit`. */\n entries: T[]\n /**\n * Entries inside the TIME window before keyword filtering. Lets the caller\n * tell \"keyword matched nothing\" apart from \"window itself is empty\" — the\n * distinction that saves an LLM a blind retry round.\n */\n windowCount: number\n}\n\n/** Tokenized lowercase text per entry, cached for the entry object's lifetime. */\nconst tokenCache = new WeakMap<object, string[]>()\n\nexport function searchMemoryEntries<T extends MemorySearchableEntry>(\n entries: readonly T[],\n q: MemorySearchQuery,\n): MemorySearchResult<T> {\n const since = q.sinceMs ?? 0\n const until = q.untilMs ?? Number.MAX_SAFE_INTEGER\n const lo = lowerBound(entries, since)\n const hi = upperBound(entries, until) // exclusive\n const windowCount = Math.max(0, hi - lo)\n\n const needle = q.contains?.trim().toLowerCase() || null\n const termWords = (q.terms ?? []).map((t) => tokenize(t)).filter((words) => words.length > 0)\n\n const picked: T[] = []\n for (let i = hi - 1; i >= lo && picked.length < q.limit; i--) {\n const e = entries[i]\n if (needle && !e.text.toLowerCase().includes(needle)) continue\n if (termWords.length > 0 && !matchesAnyTerm(e, termWords)) continue\n picked.push(e)\n }\n picked.reverse()\n return {entries: picked, windowCount}\n}\n\n/** True when any term matches — a term matches iff ALL its words match a token. */\nfunction matchesAnyTerm(entry: MemorySearchableEntry, termWords: string[][]): boolean {\n let tokens = tokenCache.get(entry)\n if (!tokens) {\n tokens = tokenize(entry.text)\n tokenCache.set(entry, tokens)\n }\n outer: for (const words of termWords) {\n for (const word of words) {\n if (!tokens.some((tok) => fuzzyWordMatch(word, tok))) continue outer\n }\n return true\n }\n return false\n}\n\n/**\n * Does query word `w` match transcript token `t`?\n * - exact, or substring for w of 3+ chars (\"kestrel\" in \"kestrels\")\n * - for words of 5+ chars: bounded edit distance (1, or 2 for 7+ chars)\n * — catches one-vowel STT swaps (\"sompo\"/\"sampo\", \"korwin\"/\"corwin\").\n * 5 is the floor because at 4 chars a one-edit radius swallows unrelated\n * common words (\"code\"→\"mode\"); mistranscribed NAMES are almost always 5+.\n * - same Soundex key with similar length — catches phonetic respellings that\n * edit distance misses (\"warryn\"/\"warren\" style doublings)\n */\nexport function fuzzyWordMatch(w: string, t: string): boolean {\n if (w === t) return true\n if (w.length >= 3 && t.includes(w)) return true\n if (w.length < 5 || t.length < 4) return false\n const maxDist = w.length >= 7 ? 2 : 1\n if (Math.abs(w.length - t.length) <= maxDist && editDistanceAtMost(w, t, maxDist)) return true\n return Math.abs(w.length - t.length) <= 2 && soundex(w) === soundex(t)\n}\n\n/** Lowercase, strip diacritics, split on non-alphanumerics. */\nexport function tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 0)\n}\n\n/**\n * Optimal-string-alignment edit distance, early-exited: returns whether\n * dist(a, b) <= max. Transpositions count as one edit (common in STT output).\n */\nexport function editDistanceAtMost(a: string, b: string, max: number): boolean {\n if (Math.abs(a.length - b.length) > max) return false\n let prev2: number[] | null = null\n let prev = Array.from({length: b.length + 1}, (_, j) => j)\n for (let i = 1; i <= a.length; i++) {\n const cur = [i]\n let rowMin = i\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n let v = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost)\n if (prev2 && i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n v = Math.min(v, prev2[j - 2] + 1)\n }\n cur.push(v)\n if (v < rowMin) rowMin = v\n }\n if (rowMin > max) return false\n prev2 = prev\n prev = cur\n }\n return prev[b.length] <= max\n}\n\nconst SOUNDEX_CODES: Record<string, string> = {\n b: \"1\",\n f: \"1\",\n p: \"1\",\n v: \"1\",\n c: \"2\",\n g: \"2\",\n j: \"2\",\n k: \"2\",\n q: \"2\",\n s: \"2\",\n x: \"2\",\n z: \"2\",\n d: \"3\",\n t: \"3\",\n l: \"4\",\n m: \"5\",\n n: \"5\",\n r: \"6\",\n}\n\n/** Classic Soundex. Empty input returns \"\". */\nexport function soundex(word: string): string {\n const w = word.toLowerCase().replace(/[^a-z]/g, \"\")\n if (!w) return \"\"\n let out = w[0].toUpperCase()\n let lastCode = SOUNDEX_CODES[w[0]] ?? \"\"\n for (let i = 1; i < w.length && out.length < 4; i++) {\n const ch = w[i]\n const code = SOUNDEX_CODES[ch] ?? \"\"\n // h/w are transparent: they don't reset the adjacent-duplicate rule.\n if (ch === \"h\" || ch === \"w\") continue\n if (code && code !== lastCode) out += code\n lastCode = code\n }\n return out.padEnd(4, \"0\")\n}\n\n/** First index with at >= value (entries time-sorted ascending). */\nfunction lowerBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at < value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\n/** First index with at > value (i.e. exclusive end for an inclusive bound). */\nfunction upperBound(entries: readonly MemorySearchableEntry[], value: number): number {\n let lo = 0\n let hi = entries.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (entries[mid].at <= value) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassly/engine",
3
- "version": "0.4.0",
3
+ "version": "0.4.1-dev.1137",
4
4
  "description": "Glassly Engine — miniapp registry, WebView bridge, and miniapp store",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -97,26 +97,26 @@
97
97
  "registry": "https://registry.npmjs.org/"
98
98
  },
99
99
  "dependencies": {
100
- "@glassly/bluetooth-sdk": "0.4.0",
101
- "@glassly/cloud-client": "0.4.0",
102
- "@glassly/cloud-protocol": "0.4.0",
103
- "@glassly/crust": "0.4.0",
104
- "@glassly/miniapp": "0.4.0",
100
+ "@glassly/bluetooth-sdk": "0.4.1-dev.1137",
101
+ "@glassly/cloud-client": "0.4.1-dev.1137",
102
+ "@glassly/cloud-protocol": "0.4.1-dev.1137",
103
+ "@glassly/crust": "0.4.1-dev.1137",
104
+ "@glassly/miniapp": "0.4.1-dev.1137",
105
105
  "buffer": "^6.0.3",
106
106
  "events": "^3.3.0",
107
- "react-native-marked": "8.3.2",
108
- "semver": "^7.7.4",
107
+ "react-native-marked": "8.3.4",
108
+ "semver": "^7.8.6",
109
109
  "typesafe-ts": "^1.7.1",
110
- "@glassly/llm-providers": "0.4.0",
111
- "@huggingface/jinja": "^0.5.9",
112
- "jsonrepair": "^3.12.0"
110
+ "@glassly/llm-providers": "0.4.1-dev.1137",
111
+ "@huggingface/jinja": "^0.5.12",
112
+ "jsonrepair": "^3.15.0"
113
113
  },
114
114
  "devDependencies": {
115
115
  "@glassly/llm-providers": "workspace:*",
116
- "@types/semver": "^7.7.1",
116
+ "@types/semver": "^7.8.0",
117
117
  "expo-module-scripts": "^56.0.3",
118
- "expo-modules-core": "^58.0.23",
119
- "react-native-nitro-modules": "^0.37.1",
118
+ "expo-modules-core": "^58.0.30",
119
+ "react-native-nitro-modules": "^0.37.2",
120
120
  "typescript": "~6.0.3"
121
121
  },
122
122
  "peerDependencies": {
@@ -155,7 +155,7 @@
155
155
  "@dr.pogodin/react-native-fs": "*",
156
156
  "@craftzdog/react-native-buffer": "*",
157
157
  "axios": "*",
158
- "react-native-executorch": ">=0.10.5 <0.11",
158
+ "react-native-executorch": ">=0.11.0 <0.12",
159
159
  "react-native-blob-util": "*"
160
160
  }
161
161
  }
package/src/engine.ts CHANGED
@@ -129,12 +129,14 @@ export const engine = {
129
129
  // Not awaited: the exchange behind it is a Core round trip with no client
130
130
  // deadline, and start() must resolve offline. The glasses get the token
131
131
  // when it lands; identity resolution joins the same single-flight exchange.
132
- void cloudClientService.syncCoreTokenToBluetooth().catch((error) => {
133
- console.warn(
134
- "engine.start: initial Cloud core token sync failed:",
135
- error instanceof Error ? error.message : error,
136
- )
137
- })
132
+ if (!cloudClientService.isCloudDisabled()) {
133
+ void cloudClientService.syncCoreTokenToBluetooth().catch((error) => {
134
+ console.warn(
135
+ "engine.start: initial Cloud core token sync failed:",
136
+ error instanceof Error ? error.message : error,
137
+ )
138
+ })
139
+ }
138
140
  startSupportProfileSync()
139
141
  // Push device-setting changes to the glasses for ANY host, so
140
142
  // engine.glasses.settings.set() reaches the device (not just the Glassly app).
@@ -237,7 +239,7 @@ export const engine = {
237
239
  backup,
238
240
  /** Device-local voice profiles for on-device speaker ID (Settings > Speakers). */
239
241
  speakers,
240
- /** AI/voice provider key validation — user-supplied keys (Settings > API Keys). */
242
+ /** AI/voice provider key validation — user-supplied keys (Settings > Privacy > API Keys). */
241
243
  providerKeys,
242
244
  display,
243
245
  }
@@ -20,7 +20,7 @@ export const display = {
20
20
  dashboard: {
21
21
  /** An overlay app holds the slot. */
22
22
  isOpen: (): boolean => useDisplayStore.getState().overlayOwner !== null,
23
- /** As if the head was raised/lowered (the dashboard app applies contextual_dashboard). */
23
+ /** As if the head was raised/lowered (the dashboard app decides whether head-up opens it). */
24
24
  setHeadUp: (up: boolean): void => sendGesture(up ? "head_up" : "head_down"),
25
25
  /** A double tap on the empty screen: the dashboard app opens (simulator button). */
26
26
  open: (): void => {
@@ -114,7 +114,7 @@ function projectKeyboardStatus() {
114
114
  const s = useGlassesStore.getState()
115
115
  return {
116
116
  /** Connected glasses run a firmware that can host a keyboard (G2 Glassly CFW 39+). */
117
- available: s.keyboardBridge === true,
117
+ available: isGlassesReady(s.connection) && s.keyboardBridge === true,
118
118
  connected: s.keyboardConnected === true,
119
119
  name: s.keyboardName ?? "",
120
120
  /** A keyboard is remembered and reconnects automatically. */
@@ -125,14 +125,12 @@ export const permissions = {
125
125
  features.add(PermissionFeatures.CALENDAR)
126
126
  features.add(PermissionFeatures.LOCATION)
127
127
  features.add(PermissionFeatures.BACKGROUND_LOCATION)
128
- features.add(PermissionFeatures.POST_NOTIFICATIONS)
129
128
  features.add("read_notifications")
130
129
  break
131
130
  case "MICROPHONE":
132
131
  case "CALENDAR":
133
132
  case "LOCATION":
134
133
  case "BACKGROUND_LOCATION":
135
- case "POST_NOTIFICATIONS":
136
134
  features.add(PermissionFeatures[permission.type])
137
135
  break
138
136
  case "READ_NOTIFICATIONS":