@glassly/engine 0.3.2-beta.572 → 0.3.2-beta.602

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 (151) hide show
  1. package/README.md +1 -1
  2. package/build/engine.d.ts +15 -1
  3. package/build/engine.d.ts.map +1 -1
  4. package/build/engine.js +7 -3
  5. package/build/engine.js.map +1 -1
  6. package/build/facades/dev.d.ts +2 -2
  7. package/build/facades/dev.d.ts.map +1 -1
  8. package/build/facades/dev.js +2 -2
  9. package/build/facades/dev.js.map +1 -1
  10. package/build/facades/glasses.d.ts +20 -0
  11. package/build/facades/glasses.d.ts.map +1 -1
  12. package/build/facades/glasses.js +21 -0
  13. package/build/facades/glasses.js.map +1 -1
  14. package/build/facades/pairing.js +1 -1
  15. package/build/facades/pairing.js.map +1 -1
  16. package/build/facades/reports.js +2 -2
  17. package/build/facades/reports.js.map +1 -1
  18. package/build/facades/session.d.ts +1 -1
  19. package/build/facades/session.js +2 -2
  20. package/build/facades/session.js.map +1 -1
  21. package/build/generated/releaseMetadata.js +3 -3
  22. package/build/generated/releaseMetadata.js.map +1 -1
  23. package/build/index.d.ts +3 -1
  24. package/build/index.d.ts.map +1 -1
  25. package/build/index.js +3 -1
  26. package/build/index.js.map +1 -1
  27. package/build/runtime/bootstrap.d.ts +2 -2
  28. package/build/runtime/bootstrap.d.ts.map +1 -1
  29. package/build/runtime/bootstrap.js.map +1 -1
  30. package/build/services/CloudAudioSubscriptionSync.d.ts +2 -2
  31. package/build/services/CloudAudioSubscriptionSync.js +2 -2
  32. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  33. package/build/services/CloudClientService.d.ts +2 -2
  34. package/build/services/CloudClientService.d.ts.map +1 -1
  35. package/build/services/CloudClientService.js +4 -4
  36. package/build/services/CloudClientService.js.map +1 -1
  37. package/build/services/CloudTranscriptE2EMetrics.d.ts +2 -2
  38. package/build/services/CloudTranscriptE2EMetrics.d.ts.map +1 -1
  39. package/build/services/CloudTranscriptE2EMetrics.js +3 -3
  40. package/build/services/CloudTranscriptE2EMetrics.js.map +1 -1
  41. package/build/services/DeviceEventRouter.d.ts.map +1 -1
  42. package/build/services/DeviceEventRouter.js +5 -0
  43. package/build/services/DeviceEventRouter.js.map +1 -1
  44. package/build/services/GestureDotsService.d.ts +9 -9
  45. package/build/services/GestureDotsService.d.ts.map +1 -1
  46. package/build/services/GestureDotsService.js +75 -50
  47. package/build/services/GestureDotsService.js.map +1 -1
  48. package/build/services/GlassesTouchInput.d.ts +1 -1
  49. package/build/services/GlassesTouchInput.d.ts.map +1 -1
  50. package/build/services/GlassesTouchInput.js +7 -4
  51. package/build/services/GlassesTouchInput.js.map +1 -1
  52. package/build/services/LocalMiniappRuntime.d.ts +1 -1
  53. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  54. package/build/services/LocalMiniappRuntime.js +32 -8
  55. package/build/services/LocalMiniappRuntime.js.map +1 -1
  56. package/build/services/LocalSttFallbackCoordinator.d.ts +5 -2
  57. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  58. package/build/services/LocalSttFallbackCoordinator.js +7 -3
  59. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  60. package/build/services/PhonePhotoCoordinator.d.ts +1 -1
  61. package/build/services/PhonePhotoCoordinator.js +4 -4
  62. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  63. package/build/services/PhoneStreamCoordinator.d.ts +1 -1
  64. package/build/services/PhoneStreamCoordinator.js +1 -1
  65. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  66. package/build/services/SupportProfileSync.d.ts +1 -1
  67. package/build/services/SupportProfileSync.js +2 -2
  68. package/build/services/SupportProfileSync.js.map +1 -1
  69. package/build/services/TranscriptionRouting.d.ts +6 -1
  70. package/build/services/TranscriptionRouting.d.ts.map +1 -1
  71. package/build/services/TranscriptionRouting.js +7 -3
  72. package/build/services/TranscriptionRouting.js.map +1 -1
  73. package/build/services/cloudStreamApi.d.ts +2 -2
  74. package/build/services/cloudStreamApi.js +2 -2
  75. package/build/services/cloudStreamApi.js.map +1 -1
  76. package/build/services/gestureDotGlyphs.d.ts +1 -1
  77. package/build/services/gestureDotGlyphs.d.ts.map +1 -1
  78. package/build/services/gestureDotGlyphs.js +5 -0
  79. package/build/services/gestureDotGlyphs.js.map +1 -1
  80. package/build/services/neuralBand/MetaAuth.d.ts +31 -0
  81. package/build/services/neuralBand/MetaAuth.d.ts.map +1 -0
  82. package/build/services/neuralBand/MetaAuth.js +161 -0
  83. package/build/services/neuralBand/MetaAuth.js.map +1 -0
  84. package/build/services/neuralBand/NeuralBandInput.d.ts +50 -0
  85. package/build/services/neuralBand/NeuralBandInput.d.ts.map +1 -0
  86. package/build/services/neuralBand/NeuralBandInput.js +114 -0
  87. package/build/services/neuralBand/NeuralBandInput.js.map +1 -0
  88. package/build/services/neuralBand/NeuralBandSettingsSync.d.ts +3 -0
  89. package/build/services/neuralBand/NeuralBandSettingsSync.d.ts.map +1 -0
  90. package/build/services/neuralBand/NeuralBandSettingsSync.js +52 -0
  91. package/build/services/neuralBand/NeuralBandSettingsSync.js.map +1 -0
  92. package/build/services/neuralBand/sha256.d.ts +7 -0
  93. package/build/services/neuralBand/sha256.d.ts.map +1 -0
  94. package/build/services/neuralBand/sha256.js +68 -0
  95. package/build/services/neuralBand/sha256.js.map +1 -0
  96. package/build/services/settingsBridge.d.ts +12 -4
  97. package/build/services/settingsBridge.d.ts.map +1 -1
  98. package/build/services/settingsBridge.js +13 -4
  99. package/build/services/settingsBridge.js.map +1 -1
  100. package/build/services/soniox/SonioxRealtimeClient.d.ts +2 -2
  101. package/build/services/soniox/SonioxRealtimeClient.js +2 -2
  102. package/build/services/soniox/SonioxRealtimeClient.js.map +1 -1
  103. package/build/services/soniox/SonioxTokenAssembler.d.ts +1 -1
  104. package/build/services/soniox/SonioxTokenAssembler.js +1 -1
  105. package/build/services/soniox/SonioxTokenAssembler.js.map +1 -1
  106. package/build/stores/cloudClientStatus.js +1 -1
  107. package/build/stores/cloudClientStatus.js.map +1 -1
  108. package/build/stores/settings.d.ts.map +1 -1
  109. package/build/stores/settings.js +25 -7
  110. package/build/stores/settings.js.map +1 -1
  111. package/build/types/enums.d.ts +2 -1
  112. package/build/types/enums.d.ts.map +1 -1
  113. package/build/types/enums.js +1 -0
  114. package/build/types/enums.js.map +1 -1
  115. package/build/utils/cloudClient/cloudSecureStore.js +2 -2
  116. package/build/utils/cloudClient/cloudSecureStore.js.map +1 -1
  117. package/package.json +7 -7
  118. package/src/engine.ts +7 -3
  119. package/src/facades/dev.ts +2 -2
  120. package/src/facades/glasses.ts +27 -0
  121. package/src/facades/pairing.ts +1 -1
  122. package/src/facades/reports.ts +2 -2
  123. package/src/facades/session.ts +2 -2
  124. package/src/generated/releaseMetadata.ts +3 -3
  125. package/src/index.ts +15 -1
  126. package/src/runtime/bootstrap.ts +2 -2
  127. package/src/services/CloudAudioSubscriptionSync.ts +2 -2
  128. package/src/services/CloudClientService.ts +4 -4
  129. package/src/services/CloudTranscriptE2EMetrics.ts +3 -3
  130. package/src/services/DeviceEventRouter.ts +5 -0
  131. package/src/services/GestureDotsService.ts +72 -49
  132. package/src/services/GlassesTouchInput.ts +13 -5
  133. package/src/services/LocalMiniappRuntime.ts +52 -24
  134. package/src/services/LocalSttFallbackCoordinator.ts +18 -4
  135. package/src/services/PhonePhotoCoordinator.ts +4 -4
  136. package/src/services/PhoneStreamCoordinator.ts +1 -1
  137. package/src/services/SupportProfileSync.ts +2 -2
  138. package/src/services/TranscriptionRouting.ts +12 -4
  139. package/src/services/cloudStreamApi.ts +3 -3
  140. package/src/services/gestureDotGlyphs.ts +6 -1
  141. package/src/services/neuralBand/MetaAuth.ts +192 -0
  142. package/src/services/neuralBand/NeuralBandInput.ts +148 -0
  143. package/src/services/neuralBand/NeuralBandSettingsSync.ts +63 -0
  144. package/src/services/neuralBand/sha256.ts +70 -0
  145. package/src/services/settingsBridge.ts +15 -4
  146. package/src/services/soniox/SonioxRealtimeClient.ts +2 -2
  147. package/src/services/soniox/SonioxTokenAssembler.ts +1 -1
  148. package/src/stores/cloudClientStatus.ts +1 -1
  149. package/src/stores/settings.ts +25 -7
  150. package/src/types/enums.ts +1 -0
  151. package/src/utils/cloudClient/cloudSecureStore.ts +2 -2
package/README.md CHANGED
@@ -43,7 +43,7 @@ resolve live TypeScript source):
43
43
  SDK `react`, `types`, `photo-receiver`, `ota-transport`, and `debug` subpaths are mirrored
44
44
  below this path. The SDK's `internal` entrypoint is deliberately not exposed.
45
45
 
46
- See `cloud-v2/docs/issues/020-glasses-status-boundary/integration-review.md`
46
+ See `cloud/docs/issues/020-glasses-status-boundary/integration-review.md`
47
47
  §D for the burn-down plan.
48
48
 
49
49
  This module owns the pieces of miniapp logic and handling that aren't tied to
package/build/engine.d.ts CHANGED
@@ -63,6 +63,20 @@ export declare const engine: {
63
63
  status: () => import("./facades/glasses").ControllerStatusSnapshot;
64
64
  onStatus: (cb: (status: import("./facades/glasses").ControllerStatusSnapshot) => void) => (() => void);
65
65
  };
66
+ neuralBand: {
67
+ setMetaSession: (accessToken: string, userId: string) => Promise<void>;
68
+ clearMetaSession: () => Promise<void>;
69
+ hasMetaSession: () => Promise<boolean>;
70
+ isClaimed: () => Promise<boolean>;
71
+ claimStatus: () => import(".").NeuralBandClaimStatus;
72
+ resetClaim: () => void;
73
+ onClaimStatus: (cb: (status: import(".").NeuralBandClaimStatus) => void) => (() => void);
74
+ setHandwriting: (enabled: boolean) => Promise<void>;
75
+ handwritingStatus: () => import(".").NeuralBandHandwritingStatus;
76
+ onHandwritingStatus: (cb: (status: import(".").NeuralBandHandwritingStatus) => void) => (() => void);
77
+ setPointer: (enabled: boolean) => Promise<void>;
78
+ setHand: (hand: "left" | "right") => Promise<void>;
79
+ };
66
80
  audio: {
67
81
  getMediaVolume: () => Promise<import("@glassly/bluetooth-sdk").GlassesMediaVolumeGetResult>;
68
82
  setMediaVolume: (level: number) => Promise<import("@glassly/bluetooth-sdk").GlassesMediaVolumeSetResult>;
@@ -124,7 +138,7 @@ export declare const engine: {
124
138
  deleteModel: (_code?: string | undefined) => Promise<void>;
125
139
  };
126
140
  };
127
- /** Cloud (cloud-v2) live-session status + account ops — engine owns the client. */
141
+ /** Cloud live-session status + account ops — engine owns the client. */
128
142
  session: {
129
143
  status: () => import(".").CloudClientStatusSnapshot;
130
144
  onStatus: (cb: (status: import(".").CloudClientStatusSnapshot) => void) => (() => void);
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,SAAS,EAAkD,aAAa,EAAC,MAAM,qBAAqB,CAAA;AA2C5G,eAAO,MAAM,MAAM;IACjB,2EAA2E;;IAE3E,8EAA8E;;IAE9E;iDAC6C;;IA8F7C;;yCAEqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkCrC,mFAAmF;;;;;;;;IAEnF,sEAAsE;;;;;;;;;;;;IAEtE,qFAAqF;;;;gBAtHnF,CADD;mBAAiB,CAAC;;;gBAUjB,CAJC;mBAAiB,CAAC;;;;;;;;;;;;;;;;;IAmHrB,qEAAqE;;;;IAErE,sFAAsF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEtF,6EAA6E;;;;;;;;;;;;IAE7E,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;IAEjF,8CAA8C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAE9C,uDAAuD;;;;;;;;;;;;;;;;IAEvD,8EAA8E;;;;;;;;IAE9E,qFAAqF;;;;IAErF,4EAA4E;;;;;;;;;;;IAE5E,+EAA+E;;;;;;;;;;;;IAE/E,kFAAkF;;;;;+BA9I3D,CAAC;;;+BAWtB,CAAA;;;;;;;;;;;;IAqIF,mFAAmF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGpF,CAAA"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,SAAS,EAAkD,aAAa,EAAC,MAAM,qBAAqB,CAAA;AA4C5G,eAAO,MAAM,MAAM;IACjB,2EAA2E;;IAE3E,8EAA8E;;IAE9E;iDAC6C;;IAgG7C;;yCAEqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmCrC,wEAAwE;;;;;;;;IAExE,sEAAsE;;;;;;;;;;;;IAEtE,qFAAqF;;;;gBA5HV,CAAC;mBAAiB,CAAC;;;gBAM5F,CADA;mBAAiB,CAAC;;;;;;;;;;;;;;;;;IAyHpB,qEAAqE;;;;IAErE,sFAAsF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEtF,6EAA6E;;;;;;;;;;;;IAE7E,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;IAEjF,8CAA8C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAE9C,uDAAuD;;;;;;;;;;;;;;;;IAEvD,8EAA8E;;;;;;;;IAE9E,qFAAqF;;;;IAErF,4EAA4E;;;;;;;;;;;IAE5E,+EAA+E;;;;;;;;;;;;IAE/E,kFAAkF;;;;;+BAlJ3D,CAAC;;;+BAUf,CAAC;;;;;;;;;;;;IA0IV,mFAAmF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGpF,CAAA"}
package/build/engine.js CHANGED
@@ -23,6 +23,7 @@ import { startDeviceEventRouter, stopDeviceEventRouter } from "./services/Device
23
23
  import { startPhoneActivityTracking, stopPhoneActivityTracking } from "./services/PhoneActivity";
24
24
  import { startPhoneNotificationsSync, stopPhoneNotificationsSync } from "./services/PhoneNotificationsSync";
25
25
  import { startSpeakerIdSync, stopSpeakerIdSync } from "./services/SpeakerIdSync";
26
+ import { startNeuralBandSettingsSync, stopNeuralBandSettingsSync } from "./services/neuralBand/NeuralBandSettingsSync";
26
27
  import { startCaptionsTesterReportService, stopCaptionsTesterReportService } from "./services/CaptionsTesterReportService";
27
28
  import { startJSCrashloopReportService, stopJSCrashloopReportService } from "./services/JSCrashloopReportService";
28
29
  import { ensureMiniappEngine, stopMiniappEngine } from "./services/MiniappEngine";
@@ -118,7 +119,7 @@ export const engine = {
118
119
  // deadline, and start() must resolve offline. The glasses get the token
119
120
  // when it lands; identity resolution joins the same single-flight exchange.
120
121
  void cloudClientService.syncCoreTokenToBluetooth().catch((error) => {
121
- console.warn("engine.start: initial Cloud V2 core token sync failed:", error instanceof Error ? error.message : error);
122
+ console.warn("engine.start: initial Cloud core token sync failed:", error instanceof Error ? error.message : error);
122
123
  });
123
124
  startSupportProfileSync();
124
125
  // Push device-setting changes to the glasses for ANY host, so
@@ -130,8 +131,10 @@ export const engine = {
130
131
  // profile centroids to the native SpeakerIdEngine, and start the resolver
131
132
  // that annotates cloud transcripts with resolved speaker identities.
132
133
  startSpeakerIdSync();
134
+ // Meta Neural Band: push the air mouse and wearing-hand settings to the band on connect.
135
+ startNeuralBandSettingsSync();
133
136
  // Android internal/e2e: laptop captions tester can broadcast a failure intent;
134
- // engine owns turning that into a Cloud V2 report.
137
+ // engine owns turning that into a Cloud report.
135
138
  startCaptionsTesterReportService();
136
139
  // JSRuntime crashloop-disabled is runtime state; engine owns filing the
137
140
  // automatic report while hosts only render alert/telemetry side effects.
@@ -174,6 +177,7 @@ export const engine = {
174
177
  await safely("phone notifications sync", stopPhoneNotificationsSync);
175
178
  await safely("phone activity tracking", stopPhoneActivityTracking);
176
179
  await safely("speaker id sync", stopSpeakerIdSync);
180
+ await safely("neural band settings sync", stopNeuralBandSettingsSync);
177
181
  await safely("captions tester report service", stopCaptionsTesterReportService);
178
182
  await safely("js crashloop report service", stopJSCrashloopReportService);
179
183
  await safely("miniapp engine", stopMiniappEngine);
@@ -185,7 +189,7 @@ export const engine = {
185
189
  },
186
190
  glasses,
187
191
  speech,
188
- /** Cloud (cloud-v2) live-session status + account ops — engine owns the client. */
192
+ /** Cloud live-session status + account ops — engine owns the client. */
189
193
  session,
190
194
  /** Typed keyed user settings over the engine-owned settings store. */
191
195
  settings,
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `engine` — the namespaced OEM-facing engine API (the \"(A) host API\" from the\n * Phase-1 contract). Host UI calls `engine.<domain>.<method>()`; each domain is a\n * typed facade over the runtime. (Exported from the `@glassly/engine` module, whose\n * name stays `engine` in code; the public API surface is `engine`.)\n *\n * It grows one facade at a time. The migration-era flat store/service exports\n * remain in a private Glassly host package; they shrink as screens move onto\n * `engine.*`.\n */\nimport {configure, start as bootstrapStart, stop as bootstrapStop, updateUiSeams} from \"./runtime/bootstrap\"\nimport {cloudClientService} from \"./services/CloudClientService\"\nimport {hydrateDeviceStore, demoteOrphanedDefaultWearable} from \"./services/DeviceStoreHydration\"\nimport {startPairedGlassesLatch, stopPairedGlassesLatch} from \"./services/PairedGlassesLatch\"\nimport {startMiniappPauseCoordinator, stopMiniappPauseCoordinator} from \"./services/MiniappPauseCoordinator\"\nimport {startGlassesSettingsSync, stopGlassesSettingsSync} from \"./services/GlassesSettingsSync\"\nimport {startGlassesStatusProjection, stopGlassesStatusProjection} from \"./services/GlassesStatusProjection\"\nimport {startOtaService, stopOtaService} from \"./services/OtaService\"\nimport {startAudioCloudUplink, stopAudioCloudUplink} from \"./services/AudioCloudUplink\"\nimport sonioxDirectService from \"./services/soniox/SonioxDirectService\"\nimport {startSupportProfileSync, stopSupportProfileSync} from \"./services/SupportProfileSync\"\nimport {startDeviceEventRouter, stopDeviceEventRouter} from \"./services/DeviceEventRouter\"\nimport {startPhoneActivityTracking, stopPhoneActivityTracking} from \"./services/PhoneActivity\"\nimport {startPhoneNotificationsSync, stopPhoneNotificationsSync} from \"./services/PhoneNotificationsSync\"\nimport {startSpeakerIdSync, stopSpeakerIdSync} from \"./services/SpeakerIdSync\"\nimport {startCaptionsTesterReportService, stopCaptionsTesterReportService} from \"./services/CaptionsTesterReportService\"\nimport {startJSCrashloopReportService, stopJSCrashloopReportService} from \"./services/JSCrashloopReportService\"\nimport {ensureMiniappEngine, stopMiniappEngine} from \"./services/MiniappEngine\"\nimport localMiniappRuntime from \"./services/LocalMiniappRuntime\"\nimport displayProcessor from \"./services/DisplayProcessor\"\nimport {gallerySyncService} from \"./services/asg/gallerySyncService\"\nimport {glasses} from \"./facades/glasses\"\nimport {display} from \"./facades/display\"\nimport {speech} from \"./facades/speech\"\nimport {session} from \"./facades/session\"\nimport {settings} from \"./facades/settings\"\nimport {dev} from \"./facades/dev\"\nimport {reports} from \"./facades/reports\"\nimport {ota} from \"./facades/ota\"\nimport {gallery} from \"./facades/gallery\"\nimport {miniapps} from \"./facades/miniapps\"\nimport {pairing} from \"./facades/pairing\"\nimport {phoneNotifications} from \"./facades/phoneNotifications\"\nimport {permissions} from \"./facades/permissions\"\nimport {notifications} from \"./facades/notifications\"\nimport {maps} from \"./facades/maps\"\nimport {memory} from \"./facades/memory\"\nimport {speakers} from \"./facades/speakers\"\nimport {providerKeys} from \"./facades/providerKeys\"\nimport {logBuffer} from \"./utils/devLogging\"\nimport pageHost from \"./services/pages/PageHost\"\nimport gestureDotsService from \"./services/GestureDotsService\"\n\nexport const engine = {\n /** Front door — hand engine auth + config, then start/stop the runtime. */\n configure,\n /** Merge host-UI seams on a running runtime (scan overlay, wifi setup, …). */\n updateUiSeams,\n /** Start the runtime: mark started + construct/connect the cloud client + begin\n * syncing device settings to the glasses. */\n async start() {\n // Reports attach recent phone logs, so engine owns console interception for\n // OEM hosts too. Idempotent; the Glassly host may start it earlier.\n logBuffer.startConsoleInterception()\n await bootstrapStart()\n // Construct + connect the cloud client so the documented configure()+start()\n // lifecycle yields a live engine.session for OEMs. Idempotent for repeated\n // start() calls.\n cloudClientService.init()\n // Project native device status -> the engine stores (the inbound feed the rest\n // of the runtime reads). Established first so the stores are live before the\n // syncs below react to them.\n startGlassesStatusProjection((changed) => localMiniappRuntime.forwardEvent(\"glasses_connection_state\", changed))\n // Lock + foreground state, read by the dashboard's notification gate and\n // the G2 notification ctrl below; up before either consumer.\n startPhoneActivityTracking()\n // The overlay slot's owner: the designated dashboard miniapp's page shows\n // through it (ADR-0006), so it is up before the miniapp runtime.\n pageHost.start()\n gestureDotsService.start()\n // Route the rest of the inbound device events (wifi/hotspot/gallery -> stores+bus,\n // photo/stream -> coordinators, button/touch/accel/head -> miniapps, save_setting ->\n // store, miniapp_selected -> launcher) so a bare OEM gets device data, not just the\n // Glassly app's MantleManager.\n startDeviceEventRouter()\n // Hydration contract: the native DeviceStore is in-memory and starts empty\n // every launch; seed it from the persisted settings BEFORE start() resolves\n // so every post-start getDefaultDevice() read is a trustworthy two-state\n // answer (no false \"absent\" for genuinely-paired users at cold start).\n // Ordered before startGlassesSettingsSync so the settings load can't\n // double-push through the change subscription. A failed hydration must not\n // brick the runtime: start() continues, and the guards that consume\n // hasDefaultDevice() see the rejection and fail open.\n try {\n await hydrateDeviceStore()\n // Boot repair: a persisted default_wearable without a native default\n // device (identity abandoned mid-pairing, or resurrected from the server\n // before identity stopped syncing) demotes to pending_wearable so hosts\n // render finish-pairing instead of a connect that would throw.\n await demoteOrphanedDefaultWearable()\n } catch (error) {\n console.warn(\"engine.start: device-store hydration failed:\", error instanceof Error ? error.message : error)\n }\n // After the settings load so an already-paired phone latches on this start.\n startPairedGlassesLatch()\n // Pause local miniapps while the paired glasses stay disconnected. Reads\n // the pairing identity, so after the settings load like the latch.\n startMiniappPauseCoordinator()\n // Project the glasses' OTA events into the store for the engine.ota read surface.\n startOtaService()\n // Forward glasses mic_lc3 frames to the v2 cloud session so cloud transcription\n // works for any host (not just the Glassly app's host-side MantleManager fork).\n startAudioCloudUplink()\n // Phone -> Soniox direct transcription (user-supplied API key). Started\n // after device-store hydration so the persisted key is already loaded.\n sonioxDirectService.start()\n // Not awaited: the exchange behind it is a Core round trip with no client\n // deadline, and start() must resolve offline. The glasses get the token\n // when it lands; identity resolution joins the same single-flight exchange.\n void cloudClientService.syncCoreTokenToBluetooth().catch((error) => {\n console.warn(\n \"engine.start: initial Cloud V2 core token sync failed:\",\n error instanceof Error ? error.message : error,\n )\n })\n startSupportProfileSync()\n // Push device-setting changes to the glasses for ANY host, so\n // engine.glasses.settings.set() reaches the device (not just the Glassly app).\n startGlassesSettingsSync()\n // Same for phone-notification config -> the native listener (Android).\n startPhoneNotificationsSync()\n // On-device speaker identification: sync the enabled setting + enrolled\n // profile centroids to the native SpeakerIdEngine, and start the resolver\n // that annotates cloud transcripts with resolved speaker identities.\n startSpeakerIdSync()\n // Android internal/e2e: laptop captions tester can broadcast a failure intent;\n // engine owns turning that into a Cloud V2 report.\n startCaptionsTesterReportService()\n // JSRuntime crashloop-disabled is runtime state; engine owns filing the\n // automatic report while hosts only render alert/telemetry side effects.\n startJSCrashloopReportService()\n // Bring up the local-miniapp engine so a bare OEM can run JSRuntime miniapps:\n // the LocalMiniappRuntime (registry + WebView bridge), the JSRuntime router\n // (crust-bound spawn/dispatch pump + launcher wiring), the DisplayProcessor\n // (layout arbitration over the engine stores), and the gallery-sync service.\n // All idempotent — when the Glassly app's host bootstrap also calls these, the\n // second call is a no-op. Host-only crashloop telemetry is attached\n // separately by the Glassly app.\n localMiniappRuntime.initialize()\n ensureMiniappEngine()\n displayProcessor.attachToRuntime()\n gallerySyncService.initialize()\n },\n /** Stop the runtime: tear down the settings sync + cloud client + mark stopped.\n * Each step is guarded so one failing teardown can't skip the rest and leak\n * the remaining runtime services. */\n async stop() {\n const safely = async (label: string, step: () => unknown): Promise<void> => {\n try {\n await step()\n } catch (error) {\n console.warn(`engine.stop: ${label} failed:`, error)\n }\n }\n await safely(\"glasses settings sync\", stopGlassesSettingsSync)\n await safely(\"paired glasses latch\", stopPairedGlassesLatch)\n await safely(\"miniapp pause coordinator\", stopMiniappPauseCoordinator)\n await safely(\"glasses status projection\", stopGlassesStatusProjection)\n await safely(\"device event router\", stopDeviceEventRouter)\n await safely(\"page host\", () => pageHost.stop())\n await safely(\"gesture dots service\", () => gestureDotsService.stop())\n await safely(\"ota service\", stopOtaService)\n await safely(\"audio cloud uplink\", stopAudioCloudUplink)\n await safely(\"soniox direct service\", () => sonioxDirectService.stop())\n await safely(\"support profile sync\", stopSupportProfileSync)\n await safely(\"phone notifications sync\", stopPhoneNotificationsSync)\n await safely(\"phone activity tracking\", stopPhoneActivityTracking)\n await safely(\"speaker id sync\", stopSpeakerIdSync)\n await safely(\"captions tester report service\", stopCaptionsTesterReportService)\n await safely(\"js crashloop report service\", stopJSCrashloopReportService)\n await safely(\"miniapp engine\", stopMiniappEngine)\n await safely(\"local miniapp runtime\", () => localMiniappRuntime.cleanup())\n await safely(\"display processor\", () => displayProcessor.detachFromRuntime())\n await safely(\"gallery sync service\", () => gallerySyncService.cleanup())\n await safely(\"cloud client\", () => cloudClientService.shutdown())\n await safely(\"bootstrap\", bootstrapStop)\n },\n glasses,\n speech,\n /** Cloud (cloud-v2) live-session status + account ops — engine owns the client. */\n session,\n /** Typed keyed user settings over the engine-owned settings store. */\n settings,\n /** Developer/debug surface (backend+cloud URL overrides, reconnect, min version). */\n dev,\n /** Bug-report, automatic runtime report, and feedback submission. */\n reports,\n /** Firmware OTA read/observe surface (updateAvailable/status + on* subscriptions). */\n ota,\n /** Gallery sync: status/onStatus · onNotice (host renders) · sync/cancel. */\n gallery,\n /** Miniapp lifecycle (the WebView bridge primitives are exported separately). */\n miniapps,\n /** First-time glasses discovery + pairing. */\n pairing,\n /** Phone→glasses notification forwarding (Android). */\n phoneNotifications,\n /** OS permissions (check/request/openSettings + per-miniapp requirements). */\n permissions,\n /** Inbound alerts engine→host (crashloop, version-incompatible, connection loss). */\n notifications,\n /** Maps providers — user-supplied Mapbox access token (Settings > Keys). */\n maps,\n /** Shared user-scoped memory timeline (Settings > Memory + session.memory). */\n memory,\n /** Device-local voice profiles for on-device speaker ID (Settings > Speakers). */\n speakers,\n /** AI/voice provider key validation — user-supplied keys (Settings > API Keys). */\n providerKeys,\n display,\n}\n"]}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `engine` — the namespaced OEM-facing engine API (the \"(A) host API\" from the\n * Phase-1 contract). Host UI calls `engine.<domain>.<method>()`; each domain is a\n * typed facade over the runtime. (Exported from the `@glassly/engine` module, whose\n * name stays `engine` in code; the public API surface is `engine`.)\n *\n * It grows one facade at a time. The migration-era flat store/service exports\n * remain in a private Glassly host package; they shrink as screens move onto\n * `engine.*`.\n */\nimport {configure, start as bootstrapStart, stop as bootstrapStop, updateUiSeams} from \"./runtime/bootstrap\"\nimport {cloudClientService} from \"./services/CloudClientService\"\nimport {hydrateDeviceStore, demoteOrphanedDefaultWearable} from \"./services/DeviceStoreHydration\"\nimport {startPairedGlassesLatch, stopPairedGlassesLatch} from \"./services/PairedGlassesLatch\"\nimport {startMiniappPauseCoordinator, stopMiniappPauseCoordinator} from \"./services/MiniappPauseCoordinator\"\nimport {startGlassesSettingsSync, stopGlassesSettingsSync} from \"./services/GlassesSettingsSync\"\nimport {startGlassesStatusProjection, stopGlassesStatusProjection} from \"./services/GlassesStatusProjection\"\nimport {startOtaService, stopOtaService} from \"./services/OtaService\"\nimport {startAudioCloudUplink, stopAudioCloudUplink} from \"./services/AudioCloudUplink\"\nimport sonioxDirectService from \"./services/soniox/SonioxDirectService\"\nimport {startSupportProfileSync, stopSupportProfileSync} from \"./services/SupportProfileSync\"\nimport {startDeviceEventRouter, stopDeviceEventRouter} from \"./services/DeviceEventRouter\"\nimport {startPhoneActivityTracking, stopPhoneActivityTracking} from \"./services/PhoneActivity\"\nimport {startPhoneNotificationsSync, stopPhoneNotificationsSync} from \"./services/PhoneNotificationsSync\"\nimport {startSpeakerIdSync, stopSpeakerIdSync} from \"./services/SpeakerIdSync\"\nimport {startNeuralBandSettingsSync, stopNeuralBandSettingsSync} from \"./services/neuralBand/NeuralBandSettingsSync\"\nimport {startCaptionsTesterReportService, stopCaptionsTesterReportService} from \"./services/CaptionsTesterReportService\"\nimport {startJSCrashloopReportService, stopJSCrashloopReportService} from \"./services/JSCrashloopReportService\"\nimport {ensureMiniappEngine, stopMiniappEngine} from \"./services/MiniappEngine\"\nimport localMiniappRuntime from \"./services/LocalMiniappRuntime\"\nimport displayProcessor from \"./services/DisplayProcessor\"\nimport {gallerySyncService} from \"./services/asg/gallerySyncService\"\nimport {glasses} from \"./facades/glasses\"\nimport {display} from \"./facades/display\"\nimport {speech} from \"./facades/speech\"\nimport {session} from \"./facades/session\"\nimport {settings} from \"./facades/settings\"\nimport {dev} from \"./facades/dev\"\nimport {reports} from \"./facades/reports\"\nimport {ota} from \"./facades/ota\"\nimport {gallery} from \"./facades/gallery\"\nimport {miniapps} from \"./facades/miniapps\"\nimport {pairing} from \"./facades/pairing\"\nimport {phoneNotifications} from \"./facades/phoneNotifications\"\nimport {permissions} from \"./facades/permissions\"\nimport {notifications} from \"./facades/notifications\"\nimport {maps} from \"./facades/maps\"\nimport {memory} from \"./facades/memory\"\nimport {speakers} from \"./facades/speakers\"\nimport {providerKeys} from \"./facades/providerKeys\"\nimport {logBuffer} from \"./utils/devLogging\"\nimport pageHost from \"./services/pages/PageHost\"\nimport gestureDotsService from \"./services/GestureDotsService\"\n\nexport const engine = {\n /** Front door — hand engine auth + config, then start/stop the runtime. */\n configure,\n /** Merge host-UI seams on a running runtime (scan overlay, wifi setup, …). */\n updateUiSeams,\n /** Start the runtime: mark started + construct/connect the cloud client + begin\n * syncing device settings to the glasses. */\n async start() {\n // Reports attach recent phone logs, so engine owns console interception for\n // OEM hosts too. Idempotent; the Glassly host may start it earlier.\n logBuffer.startConsoleInterception()\n await bootstrapStart()\n // Construct + connect the cloud client so the documented configure()+start()\n // lifecycle yields a live engine.session for OEMs. Idempotent for repeated\n // start() calls.\n cloudClientService.init()\n // Project native device status -> the engine stores (the inbound feed the rest\n // of the runtime reads). Established first so the stores are live before the\n // syncs below react to them.\n startGlassesStatusProjection((changed) => localMiniappRuntime.forwardEvent(\"glasses_connection_state\", changed))\n // Lock + foreground state, read by the dashboard's notification gate and\n // the G2 notification ctrl below; up before either consumer.\n startPhoneActivityTracking()\n // The overlay slot's owner: the designated dashboard miniapp's page shows\n // through it (ADR-0006), so it is up before the miniapp runtime.\n pageHost.start()\n gestureDotsService.start()\n // Route the rest of the inbound device events (wifi/hotspot/gallery -> stores+bus,\n // photo/stream -> coordinators, button/touch/accel/head -> miniapps, save_setting ->\n // store, miniapp_selected -> launcher) so a bare OEM gets device data, not just the\n // Glassly app's MantleManager.\n startDeviceEventRouter()\n // Hydration contract: the native DeviceStore is in-memory and starts empty\n // every launch; seed it from the persisted settings BEFORE start() resolves\n // so every post-start getDefaultDevice() read is a trustworthy two-state\n // answer (no false \"absent\" for genuinely-paired users at cold start).\n // Ordered before startGlassesSettingsSync so the settings load can't\n // double-push through the change subscription. A failed hydration must not\n // brick the runtime: start() continues, and the guards that consume\n // hasDefaultDevice() see the rejection and fail open.\n try {\n await hydrateDeviceStore()\n // Boot repair: a persisted default_wearable without a native default\n // device (identity abandoned mid-pairing, or resurrected from the server\n // before identity stopped syncing) demotes to pending_wearable so hosts\n // render finish-pairing instead of a connect that would throw.\n await demoteOrphanedDefaultWearable()\n } catch (error) {\n console.warn(\"engine.start: device-store hydration failed:\", error instanceof Error ? error.message : error)\n }\n // After the settings load so an already-paired phone latches on this start.\n startPairedGlassesLatch()\n // Pause local miniapps while the paired glasses stay disconnected. Reads\n // the pairing identity, so after the settings load like the latch.\n startMiniappPauseCoordinator()\n // Project the glasses' OTA events into the store for the engine.ota read surface.\n startOtaService()\n // Forward glasses mic_lc3 frames to the v2 cloud session so cloud transcription\n // works for any host (not just the Glassly app's host-side MantleManager fork).\n startAudioCloudUplink()\n // Phone -> Soniox direct transcription (user-supplied API key). Started\n // after device-store hydration so the persisted key is already loaded.\n sonioxDirectService.start()\n // Not awaited: the exchange behind it is a Core round trip with no client\n // deadline, and start() must resolve offline. The glasses get the token\n // when it lands; identity resolution joins the same single-flight exchange.\n void cloudClientService.syncCoreTokenToBluetooth().catch((error) => {\n console.warn(\n \"engine.start: initial Cloud core token sync failed:\",\n error instanceof Error ? error.message : error,\n )\n })\n startSupportProfileSync()\n // Push device-setting changes to the glasses for ANY host, so\n // engine.glasses.settings.set() reaches the device (not just the Glassly app).\n startGlassesSettingsSync()\n // Same for phone-notification config -> the native listener (Android).\n startPhoneNotificationsSync()\n // On-device speaker identification: sync the enabled setting + enrolled\n // profile centroids to the native SpeakerIdEngine, and start the resolver\n // that annotates cloud transcripts with resolved speaker identities.\n startSpeakerIdSync()\n // Meta Neural Band: push the air mouse and wearing-hand settings to the band on connect.\n startNeuralBandSettingsSync()\n // Android internal/e2e: laptop captions tester can broadcast a failure intent;\n // engine owns turning that into a Cloud report.\n startCaptionsTesterReportService()\n // JSRuntime crashloop-disabled is runtime state; engine owns filing the\n // automatic report while hosts only render alert/telemetry side effects.\n startJSCrashloopReportService()\n // Bring up the local-miniapp engine so a bare OEM can run JSRuntime miniapps:\n // the LocalMiniappRuntime (registry + WebView bridge), the JSRuntime router\n // (crust-bound spawn/dispatch pump + launcher wiring), the DisplayProcessor\n // (layout arbitration over the engine stores), and the gallery-sync service.\n // All idempotent — when the Glassly app's host bootstrap also calls these, the\n // second call is a no-op. Host-only crashloop telemetry is attached\n // separately by the Glassly app.\n localMiniappRuntime.initialize()\n ensureMiniappEngine()\n displayProcessor.attachToRuntime()\n gallerySyncService.initialize()\n },\n /** Stop the runtime: tear down the settings sync + cloud client + mark stopped.\n * Each step is guarded so one failing teardown can't skip the rest and leak\n * the remaining runtime services. */\n async stop() {\n const safely = async (label: string, step: () => unknown): Promise<void> => {\n try {\n await step()\n } catch (error) {\n console.warn(`engine.stop: ${label} failed:`, error)\n }\n }\n await safely(\"glasses settings sync\", stopGlassesSettingsSync)\n await safely(\"paired glasses latch\", stopPairedGlassesLatch)\n await safely(\"miniapp pause coordinator\", stopMiniappPauseCoordinator)\n await safely(\"glasses status projection\", stopGlassesStatusProjection)\n await safely(\"device event router\", stopDeviceEventRouter)\n await safely(\"page host\", () => pageHost.stop())\n await safely(\"gesture dots service\", () => gestureDotsService.stop())\n await safely(\"ota service\", stopOtaService)\n await safely(\"audio cloud uplink\", stopAudioCloudUplink)\n await safely(\"soniox direct service\", () => sonioxDirectService.stop())\n await safely(\"support profile sync\", stopSupportProfileSync)\n await safely(\"phone notifications sync\", stopPhoneNotificationsSync)\n await safely(\"phone activity tracking\", stopPhoneActivityTracking)\n await safely(\"speaker id sync\", stopSpeakerIdSync)\n await safely(\"neural band settings sync\", stopNeuralBandSettingsSync)\n await safely(\"captions tester report service\", stopCaptionsTesterReportService)\n await safely(\"js crashloop report service\", stopJSCrashloopReportService)\n await safely(\"miniapp engine\", stopMiniappEngine)\n await safely(\"local miniapp runtime\", () => localMiniappRuntime.cleanup())\n await safely(\"display processor\", () => displayProcessor.detachFromRuntime())\n await safely(\"gallery sync service\", () => gallerySyncService.cleanup())\n await safely(\"cloud client\", () => cloudClientService.shutdown())\n await safely(\"bootstrap\", bootstrapStop)\n },\n glasses,\n speech,\n /** Cloud live-session status + account ops — engine owns the client. */\n session,\n /** Typed keyed user settings over the engine-owned settings store. */\n settings,\n /** Developer/debug surface (backend+cloud URL overrides, reconnect, min version). */\n dev,\n /** Bug-report, automatic runtime report, and feedback submission. */\n reports,\n /** Firmware OTA read/observe surface (updateAvailable/status + on* subscriptions). */\n ota,\n /** Gallery sync: status/onStatus · onNotice (host renders) · sync/cancel. */\n gallery,\n /** Miniapp lifecycle (the WebView bridge primitives are exported separately). */\n miniapps,\n /** First-time glasses discovery + pairing. */\n pairing,\n /** Phone→glasses notification forwarding (Android). */\n phoneNotifications,\n /** OS permissions (check/request/openSettings + per-miniapp requirements). */\n permissions,\n /** Inbound alerts engine→host (crashloop, version-incompatible, connection loss). */\n notifications,\n /** Maps providers — user-supplied Mapbox access token (Settings > Keys). */\n maps,\n /** Shared user-scoped memory timeline (Settings > Memory + session.memory). */\n memory,\n /** Device-local voice profiles for on-device speaker ID (Settings > Speakers). */\n speakers,\n /** AI/voice provider key validation — user-supplied keys (Settings > API Keys). */\n providerKeys,\n display,\n}\n"]}
@@ -27,12 +27,12 @@ export type DevRuntimeStatusSnapshot = ReturnType<typeof projectRuntimeStatus>;
27
27
  export declare const dev: {
28
28
  /** Inject a glasses gesture through the normal dashboard/miniapp input policy. */
29
29
  sendGesture: typeof sendGesture;
30
- /** The cloud-v2 core/runtime URL overrides. */
30
+ /** The cloud core/runtime URL overrides. */
31
31
  cloudUrls: () => {
32
32
  core?: string;
33
33
  runtime?: string;
34
34
  };
35
- /** Override the cloud-v2 URLs and reconnect the live client onto them. */
35
+ /** Override the cloud URLs and reconnect the live client onto them. */
36
36
  setCloudUrls: (urls: {
37
37
  core?: string;
38
38
  runtime?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/facades/dev.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAC,WAAW,EAAC,MAAM,+BAA+B,CAAA;AACzD,OAA2B,EAAC,KAAK,mBAAmB,EAAC,MAAM,sCAAsC,CAAA;AA2CjG,iBAAS,oBAAoB;;;;;;;;;;;;;;;;;;;;;;EAuB5B;AAED,MAAM,MAAM,wBAAwB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAE9E,eAAO,MAAM,GAAG;IACd,kFAAkF;;IAElF,+CAA+C;qBAChC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC;IAIhD,0EAA0E;yBACrD;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC;IAkBtD,8EAA8E;0BAC1D,IAAI;IAExB,iFAAiF;uBAChE,MAAM;IACvB;;;OAGG;2BACkB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAK5C;;;;;;;;;OASG;0BAEI,MAAM,SACJ,MAAM,KACZ,OAAO,CAAC;QAAC,EAAE,EAAE,IAAI,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAAG;QAAC,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;IA6CtF,qEAAqE;yBAClD,wBAAwB;IAE3C,gFAAgF;0BAC1D,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAqB/E;;;OAGG;+BACwB,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;CAChF,CAAA"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/facades/dev.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAC,WAAW,EAAC,MAAM,+BAA+B,CAAA;AACzD,OAA2B,EAAC,KAAK,mBAAmB,EAAC,MAAM,sCAAsC,CAAA;AA2CjG,iBAAS,oBAAoB;;;;;;;;;;;;;;;;;;;;;;EAuB5B;AAED,MAAM,MAAM,wBAAwB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAE9E,eAAO,MAAM,GAAG;IACd,kFAAkF;;IAElF,4CAA4C;qBAC7B;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC;IAIhD,uEAAuE;yBAClD;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC;IAkBtD,8EAA8E;0BAC1D,IAAI;IAExB,iFAAiF;uBAChE,MAAM;IACvB;;;OAGG;2BACkB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAK5C;;;;;;;;;OASG;0BAEI,MAAM,SACJ,MAAM,KACZ,OAAO,CAAC;QAAC,EAAE,EAAE,IAAI,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAAG;QAAC,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;IA6CtF,qEAAqE;yBAClD,wBAAwB;IAE3C,gFAAgF;0BAC1D,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAqB/E;;;OAGG;+BACwB,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;CAChF,CAAA"}
@@ -86,12 +86,12 @@ function projectRuntimeStatus() {
86
86
  export const dev = {
87
87
  /** Inject a glasses gesture through the normal dashboard/miniapp input policy. */
88
88
  sendGesture,
89
- /** The cloud-v2 core/runtime URL overrides. */
89
+ /** The cloud core/runtime URL overrides. */
90
90
  cloudUrls: () => {
91
91
  const s = useSettingsStore.getState();
92
92
  return { core: s.getSetting(SETTINGS.cloud_core_url.key), runtime: s.getSetting(SETTINGS.cloud_runtime_url.key) };
93
93
  },
94
- /** Override the cloud-v2 URLs and reconnect the live client onto them. */
94
+ /** Override the cloud URLs and reconnect the live client onto them. */
95
95
  setCloudUrls: (urls) => {
96
96
  const next = { ...currentCloudUrlOverrides(), ...urls };
97
97
  const resolved = resolveCloudUrlReconnectTarget(next);
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/facades/dev.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * dev facade — `engine.dev`: developer/debug surface over engine-owned state.\n * Backend/cloud URL overrides read+write the engine settings store; the cloud\n * URL setters reconnect the engine-owned cloud client onto the new endpoints;\n *\n * NOTE: the dev-time endpoint *resolution* (Metro-host auto-detect, env defaults)\n * still lives host-side in `@/services/cloudClient` during the migration; this\n * facade manages the explicit overrides + reconnect.\n */\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport {isGlassesReady} from \"../services/GlassesReadiness\"\nimport {useCloudClientStatusStore} from \"../stores/cloudClientStatus\"\nimport {useConnectionStore} from \"../stores/connection\"\nimport {useCoreStore} from \"../stores/core\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {useTranscriptionDebugStore} from \"../stores/transcriptionDebug\"\nimport {cloudClientService} from \"../services/CloudClientService\"\nimport {getConfigValues} from \"../runtime/bootstrap\"\nimport {decideDevLaunchRoute} from \"../utils/devMiniappLaunch\"\nimport {deriveDevPackageId, registerDevApp, DEV_APP_PACKAGE_NAME, type DevAppRecord} from \"../services/AppRegistry\"\nimport {useAppStatusStore} from \"../stores/apps\"\nimport {sendGesture} from \"../services/GlassesTouchInput\"\nimport dashboardOpenTrace, {type DashboardOpenReport} from \"../services/debug/DashboardOpenTrace\"\n\ntype CloudUrlOverrides = {core?: string; runtime?: string}\n\n/**\n * Reconnect the cloud client onto the current cloud-URL overrides. Explicit\n * partial overrides merge over the boot-resolved config (which carries the\n * host's Metro/env URL resolution); both empty clears the live override.\n */\nfunction applyCloudUrlReconnect(urls: CloudUrlOverrides = currentCloudUrlOverrides()): void {\n const resolved = resolveCloudUrlReconnectTarget(urls)\n if (resolved === undefined) {\n cloudClientService.reconnect(null)\n } else if (resolved) {\n cloudClientService.reconnect(resolved)\n } else {\n console.warn(\"engine.dev.setCloudUrls: partial cloud override missing boot-resolved sibling endpoint\")\n }\n}\n\nfunction currentCloudUrlOverrides(): CloudUrlOverrides {\n const s = useSettingsStore.getState()\n return {\n core: trimSetting(s.getSetting(SETTINGS.cloud_core_url.key)),\n runtime: trimSetting(s.getSetting(SETTINGS.cloud_runtime_url.key)),\n }\n}\n\nfunction resolveCloudUrlReconnectTarget(urls: CloudUrlOverrides): {core: string; runtime: string} | null | undefined {\n const core = trimSetting(urls.core)\n const runtime = trimSetting(urls.runtime)\n if (!core && !runtime) return undefined\n\n const config = getConfigValues()\n const resolvedCore = core || config.coreUrl?.trim()\n const resolvedRuntime = runtime || config.runtimeUrl?.trim()\n return resolvedCore && resolvedRuntime ? {core: resolvedCore, runtime: resolvedRuntime} : null\n}\n\nfunction trimSetting(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined\n}\n\nfunction projectRuntimeStatus() {\n const core = useCoreStore.getState()\n const glasses = useGlassesStore.getState()\n const connection = useConnectionStore.getState()\n const cloudClient = useCloudClientStatusStore.getState()\n const transcriptionDebug = useTranscriptionDebugStore.getState()\n return {\n searching: core.searching,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n micRanking: [...core.micRanking],\n currentMic: core.currentMic,\n systemMicUnavailable: core.systemMicUnavailable,\n glassesConnected: glasses.connection.state === \"connected\",\n glassesFullyBooted: isGlassesReady(glasses.connection),\n bluetoothClassicConnected: glasses.bluetoothClassicConnected,\n coreStatus: connection.status,\n cloudClientStatus: cloudClient.status,\n cloudClientAudioTransport: cloudClient.audioTransport,\n transcriptionSubscribers: [...transcriptionDebug.transcriptionSubscribers],\n translationSubscribers: [...transcriptionDebug.translationSubscribers],\n recentTranscriptSources: {...transcriptionDebug.recentTranscriptSources},\n cloudAudioSubscriptionWrite: {...transcriptionDebug.cloudAudioSubscriptionWrite},\n }\n}\n\nexport type DevRuntimeStatusSnapshot = ReturnType<typeof projectRuntimeStatus>\n\nexport const dev = {\n /** Inject a glasses gesture through the normal dashboard/miniapp input policy. */\n sendGesture,\n /** The cloud-v2 core/runtime URL overrides. */\n cloudUrls: (): {core?: string; runtime?: string} => {\n const s = useSettingsStore.getState()\n return {core: s.getSetting(SETTINGS.cloud_core_url.key), runtime: s.getSetting(SETTINGS.cloud_runtime_url.key)}\n },\n /** Override the cloud-v2 URLs and reconnect the live client onto them. */\n setCloudUrls: (urls: {core?: string; runtime?: string}) => {\n const next = {...currentCloudUrlOverrides(), ...urls}\n const resolved = resolveCloudUrlReconnectTarget(next)\n if (resolved === null) {\n console.warn(\"engine.dev.setCloudUrls: ignoring partial cloud override without a resolvable sibling endpoint\")\n return\n }\n\n const s = useSettingsStore.getState()\n if (urls.core !== undefined) s.setSetting(SETTINGS.cloud_core_url.key, urls.core)\n if (urls.runtime !== undefined) s.setSetting(SETTINGS.cloud_runtime_url.key, urls.runtime)\n if (resolved === undefined) {\n cloudClientService.reconnect(null)\n } else {\n cloudClientService.reconnect(resolved)\n }\n },\n\n /** Tear down + rebuild the live cloud client (the dev \"reconnect\" button). */\n reconnectCloud: (): void => applyCloudUrlReconnect(),\n\n /** Current native (BLE-process) memory usage in MB — a dev/diagnostics gauge. */\n getMemoryMB: (): number => BluetoothSdk.getMemoryMB(),\n /**\n * Phone-side bluetooth runtime snapshot (the core store read-model: scan/mic/\n * search state) — the diagnostics/data-export surface. Shallow copy.\n */\n bluetoothStatus: (): Record<string, unknown> => {\n const {setCoreInfo: _setCoreInfo, reset: _reset, ...state} = useCoreStore.getState()\n return {...state}\n },\n\n /**\n * Side-load a miniapp being served from a dev machine (the `glassly dev` / CLI\n * flow) by its URL: probes `<url>/miniapp.json`, and on a reachable manifest\n * registers it under its manifest package so it appears in `engine.miniapps`\n * and can coexist with other dev miniapps. This is the OEM-host equivalent\n * of the first-party\n * developer-URL screen — the registration itself is engine-internal, so a\n * host reaches it here rather than the internal registry. Rendering still\n * flows through the normal display path once the miniapp is started.\n */\n loadDevMiniapp: async (\n url: string,\n name?: string,\n ): Promise<{ok: true; packageName: string; name: string} | {ok: false; error: string}> => {\n const devUrl = url.trim().replace(/\\/+$/, \"\")\n if (!devUrl) return {ok: false, error: \"empty url\"}\n const result = await decideDevLaunchRoute(\"\", devUrl)\n if (result.decision !== \"live\") {\n return {ok: false, error: \"dev server unreachable, or no miniapp.json served there\"}\n }\n const manifest = result.manifest\n const appName = name ?? manifest.name ?? \"Dev Miniapp\"\n const packageName = (manifest.packageName as string | undefined) ?? DEV_APP_PACKAGE_NAME\n // Persist the host that answered — not the stale input IP — so home-tile\n // relaunches skip a dead LAN address after mDNS/Metro failover.\n const resolvedUrl = result.resolvedUrl || devUrl\n // The `glassly dev` server puts the hot-reload/log sidecar on the\n // user port PLUS ONE — same convention as the first-party developer-URL\n // screen's deriveDevPort.\n let devPort: number | undefined\n try {\n const parsed = Number(new URL(resolvedUrl).port)\n devPort = Number.isFinite(parsed) && parsed > 0 ? parsed + 1 : undefined\n } catch {\n devPort = undefined\n }\n // The record is stored under a namespaced dev id (deriveDevPackageId) so\n // it survives release installs of the manifest package — stop/refresh and\n // the returned packageName must use that id, which registerDevApp returns.\n const devPackageId = deriveDevPackageId(packageName)\n const existing = useAppStatusStore.getState().apps.find((app) => app.packageName === devPackageId)\n if (existing?.running) await useAppStatusStore.getState().stop(devPackageId)\n const record = await registerDevApp({\n packageName,\n name: appName,\n iconUrl: manifest.icon ? new URL(manifest.icon, `${resolvedUrl}/`).toString() : `${resolvedUrl}/icon.png`,\n // Persist the host that answered — not the stale input IP.\n devUrl: resolvedUrl,\n devPort,\n type: manifest.type as DevAppRecord[\"type\"],\n permissions: manifest.permissions as DevAppRecord[\"permissions\"],\n hardwareRequirements: manifest.hardwareRequirements as DevAppRecord[\"hardwareRequirements\"],\n actions: manifest.actions as DevAppRecord[\"actions\"],\n })\n await useAppStatusStore.getState().refresh()\n return {ok: true, packageName: record.packageName, name: appName}\n },\n\n /** Current engine runtime status for engine-owned debug surfaces. */\n runtimeStatus: (): DevRuntimeStatusSnapshot => projectRuntimeStatus(),\n\n /** Subscribe to the projected engine runtime status; returns an unsubscribe. */\n onRuntimeStatus: (cb: (status: DevRuntimeStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectRuntimeStatus())\n const notify = () => {\n const snap = projectRuntimeStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n }\n const unsubscribers = [\n useCoreStore.subscribe(notify),\n useGlassesStore.subscribe(notify),\n useConnectionStore.subscribe(notify),\n useCloudClientStatusStore.subscribe(notify),\n useTranscriptionDebugStore.subscribe(notify),\n ]\n return () => {\n unsubscribers.forEach((unsubscribe) => unsubscribe())\n }\n },\n\n /**\n * Each finished dashboard open while the debug_dashboard_open_timing setting\n * is on: a ready-made title/body plus the stage timings. Returns an unsubscribe.\n */\n onDashboardOpenTrace: (cb: (report: DashboardOpenReport) => void): (() => void) => dashboardOpenTrace.onReport(cb),\n}\n"]}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/facades/dev.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * dev facade — `engine.dev`: developer/debug surface over engine-owned state.\n * Backend/cloud URL overrides read+write the engine settings store; the cloud\n * URL setters reconnect the engine-owned cloud client onto the new endpoints;\n *\n * NOTE: the dev-time endpoint *resolution* (Metro-host auto-detect, env defaults)\n * still lives host-side in `@/services/cloudClient` during the migration; this\n * facade manages the explicit overrides + reconnect.\n */\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport {isGlassesReady} from \"../services/GlassesReadiness\"\nimport {useCloudClientStatusStore} from \"../stores/cloudClientStatus\"\nimport {useConnectionStore} from \"../stores/connection\"\nimport {useCoreStore} from \"../stores/core\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {useTranscriptionDebugStore} from \"../stores/transcriptionDebug\"\nimport {cloudClientService} from \"../services/CloudClientService\"\nimport {getConfigValues} from \"../runtime/bootstrap\"\nimport {decideDevLaunchRoute} from \"../utils/devMiniappLaunch\"\nimport {deriveDevPackageId, registerDevApp, DEV_APP_PACKAGE_NAME, type DevAppRecord} from \"../services/AppRegistry\"\nimport {useAppStatusStore} from \"../stores/apps\"\nimport {sendGesture} from \"../services/GlassesTouchInput\"\nimport dashboardOpenTrace, {type DashboardOpenReport} from \"../services/debug/DashboardOpenTrace\"\n\ntype CloudUrlOverrides = {core?: string; runtime?: string}\n\n/**\n * Reconnect the cloud client onto the current cloud-URL overrides. Explicit\n * partial overrides merge over the boot-resolved config (which carries the\n * host's Metro/env URL resolution); both empty clears the live override.\n */\nfunction applyCloudUrlReconnect(urls: CloudUrlOverrides = currentCloudUrlOverrides()): void {\n const resolved = resolveCloudUrlReconnectTarget(urls)\n if (resolved === undefined) {\n cloudClientService.reconnect(null)\n } else if (resolved) {\n cloudClientService.reconnect(resolved)\n } else {\n console.warn(\"engine.dev.setCloudUrls: partial cloud override missing boot-resolved sibling endpoint\")\n }\n}\n\nfunction currentCloudUrlOverrides(): CloudUrlOverrides {\n const s = useSettingsStore.getState()\n return {\n core: trimSetting(s.getSetting(SETTINGS.cloud_core_url.key)),\n runtime: trimSetting(s.getSetting(SETTINGS.cloud_runtime_url.key)),\n }\n}\n\nfunction resolveCloudUrlReconnectTarget(urls: CloudUrlOverrides): {core: string; runtime: string} | null | undefined {\n const core = trimSetting(urls.core)\n const runtime = trimSetting(urls.runtime)\n if (!core && !runtime) return undefined\n\n const config = getConfigValues()\n const resolvedCore = core || config.coreUrl?.trim()\n const resolvedRuntime = runtime || config.runtimeUrl?.trim()\n return resolvedCore && resolvedRuntime ? {core: resolvedCore, runtime: resolvedRuntime} : null\n}\n\nfunction trimSetting(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined\n}\n\nfunction projectRuntimeStatus() {\n const core = useCoreStore.getState()\n const glasses = useGlassesStore.getState()\n const connection = useConnectionStore.getState()\n const cloudClient = useCloudClientStatusStore.getState()\n const transcriptionDebug = useTranscriptionDebugStore.getState()\n return {\n searching: core.searching,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n micRanking: [...core.micRanking],\n currentMic: core.currentMic,\n systemMicUnavailable: core.systemMicUnavailable,\n glassesConnected: glasses.connection.state === \"connected\",\n glassesFullyBooted: isGlassesReady(glasses.connection),\n bluetoothClassicConnected: glasses.bluetoothClassicConnected,\n coreStatus: connection.status,\n cloudClientStatus: cloudClient.status,\n cloudClientAudioTransport: cloudClient.audioTransport,\n transcriptionSubscribers: [...transcriptionDebug.transcriptionSubscribers],\n translationSubscribers: [...transcriptionDebug.translationSubscribers],\n recentTranscriptSources: {...transcriptionDebug.recentTranscriptSources},\n cloudAudioSubscriptionWrite: {...transcriptionDebug.cloudAudioSubscriptionWrite},\n }\n}\n\nexport type DevRuntimeStatusSnapshot = ReturnType<typeof projectRuntimeStatus>\n\nexport const dev = {\n /** Inject a glasses gesture through the normal dashboard/miniapp input policy. */\n sendGesture,\n /** The cloud core/runtime URL overrides. */\n cloudUrls: (): {core?: string; runtime?: string} => {\n const s = useSettingsStore.getState()\n return {core: s.getSetting(SETTINGS.cloud_core_url.key), runtime: s.getSetting(SETTINGS.cloud_runtime_url.key)}\n },\n /** Override the cloud URLs and reconnect the live client onto them. */\n setCloudUrls: (urls: {core?: string; runtime?: string}) => {\n const next = {...currentCloudUrlOverrides(), ...urls}\n const resolved = resolveCloudUrlReconnectTarget(next)\n if (resolved === null) {\n console.warn(\"engine.dev.setCloudUrls: ignoring partial cloud override without a resolvable sibling endpoint\")\n return\n }\n\n const s = useSettingsStore.getState()\n if (urls.core !== undefined) s.setSetting(SETTINGS.cloud_core_url.key, urls.core)\n if (urls.runtime !== undefined) s.setSetting(SETTINGS.cloud_runtime_url.key, urls.runtime)\n if (resolved === undefined) {\n cloudClientService.reconnect(null)\n } else {\n cloudClientService.reconnect(resolved)\n }\n },\n\n /** Tear down + rebuild the live cloud client (the dev \"reconnect\" button). */\n reconnectCloud: (): void => applyCloudUrlReconnect(),\n\n /** Current native (BLE-process) memory usage in MB — a dev/diagnostics gauge. */\n getMemoryMB: (): number => BluetoothSdk.getMemoryMB(),\n /**\n * Phone-side bluetooth runtime snapshot (the core store read-model: scan/mic/\n * search state) — the diagnostics/data-export surface. Shallow copy.\n */\n bluetoothStatus: (): Record<string, unknown> => {\n const {setCoreInfo: _setCoreInfo, reset: _reset, ...state} = useCoreStore.getState()\n return {...state}\n },\n\n /**\n * Side-load a miniapp being served from a dev machine (the `glassly dev` / CLI\n * flow) by its URL: probes `<url>/miniapp.json`, and on a reachable manifest\n * registers it under its manifest package so it appears in `engine.miniapps`\n * and can coexist with other dev miniapps. This is the OEM-host equivalent\n * of the first-party\n * developer-URL screen — the registration itself is engine-internal, so a\n * host reaches it here rather than the internal registry. Rendering still\n * flows through the normal display path once the miniapp is started.\n */\n loadDevMiniapp: async (\n url: string,\n name?: string,\n ): Promise<{ok: true; packageName: string; name: string} | {ok: false; error: string}> => {\n const devUrl = url.trim().replace(/\\/+$/, \"\")\n if (!devUrl) return {ok: false, error: \"empty url\"}\n const result = await decideDevLaunchRoute(\"\", devUrl)\n if (result.decision !== \"live\") {\n return {ok: false, error: \"dev server unreachable, or no miniapp.json served there\"}\n }\n const manifest = result.manifest\n const appName = name ?? manifest.name ?? \"Dev Miniapp\"\n const packageName = (manifest.packageName as string | undefined) ?? DEV_APP_PACKAGE_NAME\n // Persist the host that answered — not the stale input IP — so home-tile\n // relaunches skip a dead LAN address after mDNS/Metro failover.\n const resolvedUrl = result.resolvedUrl || devUrl\n // The `glassly dev` server puts the hot-reload/log sidecar on the\n // user port PLUS ONE — same convention as the first-party developer-URL\n // screen's deriveDevPort.\n let devPort: number | undefined\n try {\n const parsed = Number(new URL(resolvedUrl).port)\n devPort = Number.isFinite(parsed) && parsed > 0 ? parsed + 1 : undefined\n } catch {\n devPort = undefined\n }\n // The record is stored under a namespaced dev id (deriveDevPackageId) so\n // it survives release installs of the manifest package — stop/refresh and\n // the returned packageName must use that id, which registerDevApp returns.\n const devPackageId = deriveDevPackageId(packageName)\n const existing = useAppStatusStore.getState().apps.find((app) => app.packageName === devPackageId)\n if (existing?.running) await useAppStatusStore.getState().stop(devPackageId)\n const record = await registerDevApp({\n packageName,\n name: appName,\n iconUrl: manifest.icon ? new URL(manifest.icon, `${resolvedUrl}/`).toString() : `${resolvedUrl}/icon.png`,\n // Persist the host that answered — not the stale input IP.\n devUrl: resolvedUrl,\n devPort,\n type: manifest.type as DevAppRecord[\"type\"],\n permissions: manifest.permissions as DevAppRecord[\"permissions\"],\n hardwareRequirements: manifest.hardwareRequirements as DevAppRecord[\"hardwareRequirements\"],\n actions: manifest.actions as DevAppRecord[\"actions\"],\n })\n await useAppStatusStore.getState().refresh()\n return {ok: true, packageName: record.packageName, name: appName}\n },\n\n /** Current engine runtime status for engine-owned debug surfaces. */\n runtimeStatus: (): DevRuntimeStatusSnapshot => projectRuntimeStatus(),\n\n /** Subscribe to the projected engine runtime status; returns an unsubscribe. */\n onRuntimeStatus: (cb: (status: DevRuntimeStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectRuntimeStatus())\n const notify = () => {\n const snap = projectRuntimeStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n }\n const unsubscribers = [\n useCoreStore.subscribe(notify),\n useGlassesStore.subscribe(notify),\n useConnectionStore.subscribe(notify),\n useCloudClientStatusStore.subscribe(notify),\n useTranscriptionDebugStore.subscribe(notify),\n ]\n return () => {\n unsubscribers.forEach((unsubscribe) => unsubscribe())\n }\n },\n\n /**\n * Each finished dashboard open while the debug_dashboard_open_timing setting\n * is on: a ready-made title/body plus the stage timings. Returns an unsubscribe.\n */\n onDashboardOpenTrace: (cb: (report: DashboardOpenReport) => void): (() => void) => dashboardOpenTrace.onReport(cb),\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import type { ButtonPressEvent, ConnectOptions, Device, KeyboardAdvertEvent, KeyboardPairingEvent, TouchEvent } from "@glassly/bluetooth-sdk";
2
+ import { type NeuralBandClaimStatus, type NeuralBandHandwritingStatus } from "../services/neuralBand/NeuralBandInput";
2
3
  declare function projectStatus(): {
3
4
  state: "connecting" | "connected" | "disconnected" | "scanning" | "bonding";
4
5
  fullyBooted: boolean;
@@ -137,6 +138,25 @@ export declare const glasses: {
137
138
  status: () => ControllerStatusSnapshot;
138
139
  onStatus: (cb: (status: ControllerStatusSnapshot) => void) => (() => void);
139
140
  };
141
+ neuralBand: {
142
+ /** Store the Meta account session the one-time band claim uses. */
143
+ setMetaSession: (accessToken: string, userId: string) => Promise<void>;
144
+ clearMetaSession: () => Promise<void>;
145
+ hasMetaSession: () => Promise<boolean>;
146
+ /** A band identity is stored on this phone, so the remembered band connects without a claim. */
147
+ isClaimed: () => Promise<boolean>;
148
+ /** The latest claim progress, kept across screens. */
149
+ claimStatus: () => NeuralBandClaimStatus;
150
+ resetClaim: () => void;
151
+ onClaimStatus: (cb: (status: NeuralBandClaimStatus) => void) => (() => void);
152
+ /** The band's handwriting model; writing arrives on the miniapp keyboard stream. */
153
+ setHandwriting: (enabled: boolean) => Promise<void>;
154
+ handwritingStatus: () => NeuralBandHandwritingStatus;
155
+ onHandwritingStatus: (cb: (status: NeuralBandHandwritingStatus) => void) => (() => void);
156
+ /** The band's air mouse; movement reaches miniapps on the pointer stream. */
157
+ setPointer: (enabled: boolean) => Promise<void>;
158
+ setHand: (hand: "left" | "right") => Promise<void>;
159
+ };
140
160
  audio: {
141
161
  /** Read the glasses' current media volume. */
142
162
  getMediaVolume: () => Promise<import("@glassly/bluetooth-sdk").GlassesMediaVolumeGetResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"glasses.d.ts","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"glasses.d.ts","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ import { hasDefaultDevice } from "../services/DeviceStoreHydration";
17
17
  import { projectPairingIdentity } from "../services/PairingIdentity";
18
18
  import { isGlassesConnected, isGlassesReady } from "../services/GlassesReadiness";
19
19
  import { pushAllBluetoothSettings } from "../services/GlassesSettingsSync";
20
+ import neuralBandInput from "../services/neuralBand/NeuralBandInput";
20
21
  import { recordSupportProfileConnectionFailure } from "../services/SupportProfileSync";
21
22
  import { getModelCapabilities } from "../types";
22
23
  import { glassesWifi } from "./glassesWifi";
@@ -253,6 +254,26 @@ export const glasses = {
253
254
  });
254
255
  },
255
256
  },
257
+ // --- Meta Neural Band (a controller with a claim step and its own features) ---
258
+ neuralBand: {
259
+ /** Store the Meta account session the one-time band claim uses. */
260
+ setMetaSession: (accessToken, userId) => BluetoothSdk.neuralBandSetMetaSession(accessToken, userId),
261
+ clearMetaSession: () => BluetoothSdk.neuralBandClearMetaSession(),
262
+ hasMetaSession: () => BluetoothSdk.neuralBandHasMetaSession(),
263
+ /** A band identity is stored on this phone, so the remembered band connects without a claim. */
264
+ isClaimed: () => BluetoothSdk.neuralBandIsClaimed(),
265
+ /** The latest claim progress, kept across screens. */
266
+ claimStatus: () => neuralBandInput.claimStatus(),
267
+ resetClaim: () => neuralBandInput.resetClaim(),
268
+ onClaimStatus: (cb) => neuralBandInput.onClaimStatus(cb),
269
+ /** The band's handwriting model; writing arrives on the miniapp keyboard stream. */
270
+ setHandwriting: (enabled) => BluetoothSdk.neuralBandSetHandwriting(enabled),
271
+ handwritingStatus: () => neuralBandInput.handwritingStatus(),
272
+ onHandwritingStatus: (cb) => neuralBandInput.onHandwritingStatus(cb),
273
+ /** The band's air mouse; movement reaches miniapps on the pointer stream. */
274
+ setPointer: (enabled) => BluetoothSdk.neuralBandSetPointer(enabled),
275
+ setHand: (hand) => BluetoothSdk.neuralBandSetHand(hand),
276
+ },
256
277
  // --- audio (glasses media-volume + own-app playback hint) ---
257
278
  audio: {
258
279
  /** Read the glasses' current media volume. */
@@ -1 +1 @@
1
- {"version":3,"file":"glasses.js","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * glasses facade — the core `engine.glasses.*` surface: connection actions (over\n * the bluetooth-sdk passthrough), a curated status/info read-model (projected from\n * the engine-owned glasses store), capabilities (from the model table), and the\n * discrete input events. The `wifi` sub-facade is nested here.\n *\n * Read-models project the raw glasses store into the stable shape OEM UIs consume,\n * so the device store's field layout doesn't leak into every screen.\n */\n// Internal btsdk surface — connectSimulated/reconnect/controller live on the full\n// surface, not the public entry. Relative path (the alias doesn't resolve in engine's\n// standalone build); jest moduleNameMapper + tsconfig both resolve it.\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {\n ButtonPressEvent,\n ConnectOptions,\n Device,\n KeyboardAdvertEvent,\n KeyboardPairingEvent,\n TouchEvent,\n} from \"@glassly/bluetooth-sdk\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {hasDefaultDevice} from \"../services/DeviceStoreHydration\"\nimport {projectPairingIdentity} from \"../services/PairingIdentity\"\nimport {isGlassesConnected, isGlassesReady} from \"../services/GlassesReadiness\"\nimport {pushAllBluetoothSettings} from \"../services/GlassesSettingsSync\"\nimport {recordSupportProfileConnectionFailure} from \"../services/SupportProfileSync\"\nimport {getModelCapabilities, type DeviceTypes} from \"../types\"\nimport {glassesWifi} from \"./glassesWifi\"\nimport {glassesSettings} from \"./glassesSettings\"\n\nfunction projectStatus() {\n const s = useGlassesStore.getState()\n return {\n state: s.connection.state,\n fullyBooted: isGlassesReady(s.connection),\n battery: s.batteryLevel,\n charging: s.charging,\n case: {battery: s.caseBatteryLevel, charging: s.caseCharging, open: s.caseOpen, removed: s.caseRemoved},\n signal: s.signalStrength,\n micEnabled: s.micEnabled,\n vadEnabled: s.voiceActivityDetectionEnabled,\n btClassic: s.bluetoothClassicConnected,\n // iOS: glasses may read the phone's ANCS stream (\"Share System Notifications\").\n ancsAuthorized: Boolean(s.ancsAuthorized),\n }\n}\n\nfunction projectControllerStatus() {\n const s = useGlassesStore.getState()\n return {\n connected: s.controllerConnected,\n fullyBooted: s.controllerFullyBooted,\n battery: s.controllerBatteryLevel,\n signal: s.controllerSignalStrength,\n }\n}\n\nfunction projectKeyboardStatus() {\n const s = useGlassesStore.getState()\n return {\n /** Connected glasses run a firmware that can host a keyboard (G2 Glassly CFW 39+). */\n available: s.keyboardBridge === true,\n connected: s.keyboardConnected === true,\n name: s.keyboardName ?? \"\",\n /** A keyboard is remembered and reconnects automatically. */\n saved: s.keyboardSaved === true,\n state: s.keyboardState ?? \"idle\",\n error: s.keyboardError ?? \"\",\n }\n}\n\nfunction projectInfo() {\n const s = useGlassesStore.getState()\n return {\n model: s.deviceModel,\n style: s.style,\n color: s.color,\n bluetoothName: s.bluetoothName,\n firmwareVersion: s.firmwareVersion,\n mtkFirmware: s.mtkFirmwareVersion,\n besFirmware: s.besFirmwareVersion,\n appVersion: s.appVersion,\n androidVersion: s.androidVersion,\n serialNumber: s.serialNumber,\n buildNumber: s.buildNumber,\n btMac: s.bluetoothMacAddress,\n wifiMac: s.wifiMacAddress,\n leftMac: s.leftMacAddress,\n rightMac: s.rightMacAddress,\n sceneCanvasWidth: s.sceneCanvasWidth,\n sceneCanvasHeight: s.sceneCanvasHeight,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n wifi: {...s.wifi},\n }\n}\n\nexport type GlassesStatusSnapshot = ReturnType<typeof projectStatus>\nexport type ControllerStatusSnapshot = ReturnType<typeof projectControllerStatus>\nexport type KeyboardStatusSnapshot = ReturnType<typeof projectKeyboardStatus>\nexport type GlassesInfoSnapshot = ReturnType<typeof projectInfo>\n\nexport const glasses = {\n // --- connection (bluetooth-sdk passthrough) ---\n /**\n * Reconnect the default wearable. Seeds the phone's current device settings to\n * native first, so they're primed before the connect handshake replays them to\n * the glasses (this used to be a host-side step before `connectDefault`).\n */\n connectDefault: async (): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect_default\")\n throw error\n }\n },\n disconnect: (): Promise<void> => BluetoothSdk.disconnect(),\n forget: (): Promise<void> => BluetoothSdk.forget(),\n /** Connect to a specific (discovered) device. */\n connect: async (device: Device, options?: ConnectOptions): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connect(device, options)\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect\")\n throw error\n }\n },\n /** Connect the built-in simulated glasses (dev/testing). */\n connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),\n /** Set a device as the `connectDefault()` target. */\n setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),\n /**\n * Reconnect to the saved default glasses. Resolves `false` when there's nothing to\n * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered\n * off), `true` when already connected or after kicking off the connect. Never\n * rejects — the boolean contract holds. The host gates connectivity/permissions\n * (its UI) before calling.\n */\n reconnect: async (): Promise<boolean> => {\n const defaultWearable = useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n if (!defaultWearable) return false\n if (isGlassesConnected(useGlassesStore.getState().connection)) return true\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"reconnect\")\n console.warn(\"engine.glasses.reconnect failed:\", error)\n return false\n }\n return true\n },\n /** True when no glasses has ever been paired NOR selected (the pairing-identity\n * lifecycle is in its `none` state) — e.g. to route a first-run host into the\n * pairing/onboarding flow. A pending selection is not \"first\" — the host should\n * offer finish-pairing (see `engine.pairing.identity()`). */\n isFirstPairing: (): boolean => projectPairingIdentity().kind === \"none\",\n /**\n * True when the SDK has an actual default DEVICE to reconnect to. Distinct from\n * `default_wearable` (a model string that a pending or orphaned selection can\n * hold without any paired device): connectDefault() throws without a device, so\n * hosts should route to the pairing flow when this is false.\n *\n * Hydration-aware: awaits the device-store seed internally, so a cold-start\n * read can't see a false \"absent\" for genuinely-paired users. Rejects if\n * hydration failed — callers guarding destructive or routing decisions must\n * fail open (treat as \"has a device\").\n */\n hasDefaultDevice: (): Promise<boolean> => hasDefaultDevice(),\n\n // --- read-model (projected from the engine-owned glasses store) ---\n status: (): GlassesStatusSnapshot => projectStatus(),\n onStatus: (cb: (status: GlassesStatusSnapshot) => void): (() => void) => {\n // Dedupe: the glasses store updates on many fields; only fire when the\n // projected status snapshot actually changes.\n let last = JSON.stringify(projectStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n info: (): GlassesInfoSnapshot => projectInfo(),\n onInfo: (cb: (info: GlassesInfoSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectInfo())\n return useGlassesStore.subscribe(() => {\n const snap = projectInfo()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n capabilities: () => getModelCapabilities(useGlassesStore.getState().deviceModel as DeviceTypes),\n /** Ask the glasses to report fresh firmware/version info (updates the store). */\n requestVersionInfo: () => BluetoothSdk.requestVersionInfo(),\n\n // --- discrete input events (passthrough listeners) ---\n onButtonPress: (cb: (event: ButtonPressEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"button_press\", cb)\n return () => sub.remove()\n },\n onTouchGesture: (cb: (event: TouchEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"touch_event\", cb)\n return () => sub.remove()\n },\n\n // --- BLE keyboard bridged through G2 Glassly CFW (revision 39+) ---\n keyboard: {\n /** Five-second scan; distinct advertisers, HID ones flagged. Also streams via onAdvert. */\n scan: (): Promise<KeyboardAdvertEvent[]> => BluetoothSdk.g2KeyboardScan(),\n /** Connect, pair and subscribe; the keyboard is remembered and auto-reconnected. */\n connect: async (device: {address: string; addressType: number; name: string}): Promise<void> => {\n await BluetoothSdk.g2KeyboardConnect(device.address, device.addressType, device.name)\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, device.name)\n },\n reconnect: (): Promise<void> => BluetoothSdk.g2KeyboardReconnect(),\n disconnect: (): Promise<void> => BluetoothSdk.g2KeyboardDisconnect(),\n forget: async (): Promise<void> => {\n await BluetoothSdk.g2KeyboardForget()\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, \"\")\n },\n passkey: (pin: number): Promise<void> => BluetoothSdk.g2KeyboardPasskey(pin),\n compare: (accept: boolean): Promise<void> => BluetoothSdk.g2KeyboardCompare(accept),\n status: (): KeyboardStatusSnapshot => projectKeyboardStatus(),\n onStatus: (cb: (status: KeyboardStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectKeyboardStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectKeyboardStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n onAdvert: (cb: (advert: KeyboardAdvertEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_advert\", cb)\n return () => sub.remove()\n },\n onPairing: (cb: (prompt: KeyboardPairingEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_pairing\", cb)\n return () => sub.remove()\n },\n },\n\n // --- ring controller (optional input device) ---\n controller: {\n connectDefault: (): Promise<void> => BluetoothSdk.connectDefaultController(),\n disconnect: (): Promise<void> => BluetoothSdk.disconnectController(),\n forget: (): Promise<void> => BluetoothSdk.forgetController(),\n status: (): ControllerStatusSnapshot => projectControllerStatus(),\n onStatus: (cb: (status: ControllerStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectControllerStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectControllerStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n },\n\n // --- audio (glasses media-volume + own-app playback hint) ---\n audio: {\n /** Read the glasses' current media volume. */\n getMediaVolume: () => BluetoothSdk.getGlassesMediaVolume(),\n /** Set the glasses' media volume. */\n setMediaVolume: (level: number) => BluetoothSdk.setGlassesMediaVolume(level),\n /** Tell native whether THIS app is currently playing audio (for ducking). */\n setOwnAppPlaying: (playing: boolean): Promise<void> => BluetoothSdk.setOwnAppAudioPlaying(playing),\n },\n\n // --- sub-facades ---\n wifi: glassesWifi,\n settings: glassesSettings,\n}\n"]}
1
+ {"version":3,"file":"glasses.js","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * glasses facade — the core `engine.glasses.*` surface: connection actions (over\n * the bluetooth-sdk passthrough), a curated status/info read-model (projected from\n * the engine-owned glasses store), capabilities (from the model table), and the\n * discrete input events. The `wifi` sub-facade is nested here.\n *\n * Read-models project the raw glasses store into the stable shape OEM UIs consume,\n * so the device store's field layout doesn't leak into every screen.\n */\n// Internal btsdk surface — connectSimulated/reconnect/controller live on the full\n// surface, not the public entry. Relative path (the alias doesn't resolve in engine's\n// standalone build); jest moduleNameMapper + tsconfig both resolve it.\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {\n ButtonPressEvent,\n ConnectOptions,\n Device,\n KeyboardAdvertEvent,\n KeyboardPairingEvent,\n TouchEvent,\n} from \"@glassly/bluetooth-sdk\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {hasDefaultDevice} from \"../services/DeviceStoreHydration\"\nimport {projectPairingIdentity} from \"../services/PairingIdentity\"\nimport {isGlassesConnected, isGlassesReady} from \"../services/GlassesReadiness\"\nimport {pushAllBluetoothSettings} from \"../services/GlassesSettingsSync\"\nimport neuralBandInput, {\n type NeuralBandClaimStatus,\n type NeuralBandHandwritingStatus,\n} from \"../services/neuralBand/NeuralBandInput\"\nimport {recordSupportProfileConnectionFailure} from \"../services/SupportProfileSync\"\nimport {getModelCapabilities, type DeviceTypes} from \"../types\"\nimport {glassesWifi} from \"./glassesWifi\"\nimport {glassesSettings} from \"./glassesSettings\"\n\nfunction projectStatus() {\n const s = useGlassesStore.getState()\n return {\n state: s.connection.state,\n fullyBooted: isGlassesReady(s.connection),\n battery: s.batteryLevel,\n charging: s.charging,\n case: {battery: s.caseBatteryLevel, charging: s.caseCharging, open: s.caseOpen, removed: s.caseRemoved},\n signal: s.signalStrength,\n micEnabled: s.micEnabled,\n vadEnabled: s.voiceActivityDetectionEnabled,\n btClassic: s.bluetoothClassicConnected,\n // iOS: glasses may read the phone's ANCS stream (\"Share System Notifications\").\n ancsAuthorized: Boolean(s.ancsAuthorized),\n }\n}\n\nfunction projectControllerStatus() {\n const s = useGlassesStore.getState()\n return {\n connected: s.controllerConnected,\n fullyBooted: s.controllerFullyBooted,\n battery: s.controllerBatteryLevel,\n signal: s.controllerSignalStrength,\n }\n}\n\nfunction projectKeyboardStatus() {\n const s = useGlassesStore.getState()\n return {\n /** Connected glasses run a firmware that can host a keyboard (G2 Glassly CFW 39+). */\n available: s.keyboardBridge === true,\n connected: s.keyboardConnected === true,\n name: s.keyboardName ?? \"\",\n /** A keyboard is remembered and reconnects automatically. */\n saved: s.keyboardSaved === true,\n state: s.keyboardState ?? \"idle\",\n error: s.keyboardError ?? \"\",\n }\n}\n\nfunction projectInfo() {\n const s = useGlassesStore.getState()\n return {\n model: s.deviceModel,\n style: s.style,\n color: s.color,\n bluetoothName: s.bluetoothName,\n firmwareVersion: s.firmwareVersion,\n mtkFirmware: s.mtkFirmwareVersion,\n besFirmware: s.besFirmwareVersion,\n appVersion: s.appVersion,\n androidVersion: s.androidVersion,\n serialNumber: s.serialNumber,\n buildNumber: s.buildNumber,\n btMac: s.bluetoothMacAddress,\n wifiMac: s.wifiMacAddress,\n leftMac: s.leftMacAddress,\n rightMac: s.rightMacAddress,\n sceneCanvasWidth: s.sceneCanvasWidth,\n sceneCanvasHeight: s.sceneCanvasHeight,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n wifi: {...s.wifi},\n }\n}\n\nexport type GlassesStatusSnapshot = ReturnType<typeof projectStatus>\nexport type ControllerStatusSnapshot = ReturnType<typeof projectControllerStatus>\nexport type KeyboardStatusSnapshot = ReturnType<typeof projectKeyboardStatus>\nexport type GlassesInfoSnapshot = ReturnType<typeof projectInfo>\n\nexport const glasses = {\n // --- connection (bluetooth-sdk passthrough) ---\n /**\n * Reconnect the default wearable. Seeds the phone's current device settings to\n * native first, so they're primed before the connect handshake replays them to\n * the glasses (this used to be a host-side step before `connectDefault`).\n */\n connectDefault: async (): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect_default\")\n throw error\n }\n },\n disconnect: (): Promise<void> => BluetoothSdk.disconnect(),\n forget: (): Promise<void> => BluetoothSdk.forget(),\n /** Connect to a specific (discovered) device. */\n connect: async (device: Device, options?: ConnectOptions): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connect(device, options)\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect\")\n throw error\n }\n },\n /** Connect the built-in simulated glasses (dev/testing). */\n connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),\n /** Set a device as the `connectDefault()` target. */\n setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),\n /**\n * Reconnect to the saved default glasses. Resolves `false` when there's nothing to\n * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered\n * off), `true` when already connected or after kicking off the connect. Never\n * rejects — the boolean contract holds. The host gates connectivity/permissions\n * (its UI) before calling.\n */\n reconnect: async (): Promise<boolean> => {\n const defaultWearable = useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n if (!defaultWearable) return false\n if (isGlassesConnected(useGlassesStore.getState().connection)) return true\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"reconnect\")\n console.warn(\"engine.glasses.reconnect failed:\", error)\n return false\n }\n return true\n },\n /** True when no glasses has ever been paired NOR selected (the pairing-identity\n * lifecycle is in its `none` state) — e.g. to route a first-run host into the\n * pairing/onboarding flow. A pending selection is not \"first\" — the host should\n * offer finish-pairing (see `engine.pairing.identity()`). */\n isFirstPairing: (): boolean => projectPairingIdentity().kind === \"none\",\n /**\n * True when the SDK has an actual default DEVICE to reconnect to. Distinct from\n * `default_wearable` (a model string that a pending or orphaned selection can\n * hold without any paired device): connectDefault() throws without a device, so\n * hosts should route to the pairing flow when this is false.\n *\n * Hydration-aware: awaits the device-store seed internally, so a cold-start\n * read can't see a false \"absent\" for genuinely-paired users. Rejects if\n * hydration failed — callers guarding destructive or routing decisions must\n * fail open (treat as \"has a device\").\n */\n hasDefaultDevice: (): Promise<boolean> => hasDefaultDevice(),\n\n // --- read-model (projected from the engine-owned glasses store) ---\n status: (): GlassesStatusSnapshot => projectStatus(),\n onStatus: (cb: (status: GlassesStatusSnapshot) => void): (() => void) => {\n // Dedupe: the glasses store updates on many fields; only fire when the\n // projected status snapshot actually changes.\n let last = JSON.stringify(projectStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n info: (): GlassesInfoSnapshot => projectInfo(),\n onInfo: (cb: (info: GlassesInfoSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectInfo())\n return useGlassesStore.subscribe(() => {\n const snap = projectInfo()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n capabilities: () => getModelCapabilities(useGlassesStore.getState().deviceModel as DeviceTypes),\n /** Ask the glasses to report fresh firmware/version info (updates the store). */\n requestVersionInfo: () => BluetoothSdk.requestVersionInfo(),\n\n // --- discrete input events (passthrough listeners) ---\n onButtonPress: (cb: (event: ButtonPressEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"button_press\", cb)\n return () => sub.remove()\n },\n onTouchGesture: (cb: (event: TouchEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"touch_event\", cb)\n return () => sub.remove()\n },\n\n // --- BLE keyboard bridged through G2 Glassly CFW (revision 39+) ---\n keyboard: {\n /** Five-second scan; distinct advertisers, HID ones flagged. Also streams via onAdvert. */\n scan: (): Promise<KeyboardAdvertEvent[]> => BluetoothSdk.g2KeyboardScan(),\n /** Connect, pair and subscribe; the keyboard is remembered and auto-reconnected. */\n connect: async (device: {address: string; addressType: number; name: string}): Promise<void> => {\n await BluetoothSdk.g2KeyboardConnect(device.address, device.addressType, device.name)\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, device.name)\n },\n reconnect: (): Promise<void> => BluetoothSdk.g2KeyboardReconnect(),\n disconnect: (): Promise<void> => BluetoothSdk.g2KeyboardDisconnect(),\n forget: async (): Promise<void> => {\n await BluetoothSdk.g2KeyboardForget()\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, \"\")\n },\n passkey: (pin: number): Promise<void> => BluetoothSdk.g2KeyboardPasskey(pin),\n compare: (accept: boolean): Promise<void> => BluetoothSdk.g2KeyboardCompare(accept),\n status: (): KeyboardStatusSnapshot => projectKeyboardStatus(),\n onStatus: (cb: (status: KeyboardStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectKeyboardStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectKeyboardStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n onAdvert: (cb: (advert: KeyboardAdvertEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_advert\", cb)\n return () => sub.remove()\n },\n onPairing: (cb: (prompt: KeyboardPairingEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_pairing\", cb)\n return () => sub.remove()\n },\n },\n\n // --- ring controller (optional input device) ---\n controller: {\n connectDefault: (): Promise<void> => BluetoothSdk.connectDefaultController(),\n disconnect: (): Promise<void> => BluetoothSdk.disconnectController(),\n forget: (): Promise<void> => BluetoothSdk.forgetController(),\n status: (): ControllerStatusSnapshot => projectControllerStatus(),\n onStatus: (cb: (status: ControllerStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectControllerStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectControllerStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n },\n\n // --- Meta Neural Band (a controller with a claim step and its own features) ---\n neuralBand: {\n /** Store the Meta account session the one-time band claim uses. */\n setMetaSession: (accessToken: string, userId: string): Promise<void> =>\n BluetoothSdk.neuralBandSetMetaSession(accessToken, userId),\n clearMetaSession: (): Promise<void> => BluetoothSdk.neuralBandClearMetaSession(),\n hasMetaSession: (): Promise<boolean> => BluetoothSdk.neuralBandHasMetaSession(),\n /** A band identity is stored on this phone, so the remembered band connects without a claim. */\n isClaimed: (): Promise<boolean> => BluetoothSdk.neuralBandIsClaimed(),\n /** The latest claim progress, kept across screens. */\n claimStatus: (): NeuralBandClaimStatus => neuralBandInput.claimStatus(),\n resetClaim: (): void => neuralBandInput.resetClaim(),\n onClaimStatus: (cb: (status: NeuralBandClaimStatus) => void): (() => void) => neuralBandInput.onClaimStatus(cb),\n /** The band's handwriting model; writing arrives on the miniapp keyboard stream. */\n setHandwriting: (enabled: boolean): Promise<void> => BluetoothSdk.neuralBandSetHandwriting(enabled),\n handwritingStatus: (): NeuralBandHandwritingStatus => neuralBandInput.handwritingStatus(),\n onHandwritingStatus: (cb: (status: NeuralBandHandwritingStatus) => void): (() => void) =>\n neuralBandInput.onHandwritingStatus(cb),\n /** The band's air mouse; movement reaches miniapps on the pointer stream. */\n setPointer: (enabled: boolean): Promise<void> => BluetoothSdk.neuralBandSetPointer(enabled),\n setHand: (hand: \"left\" | \"right\"): Promise<void> => BluetoothSdk.neuralBandSetHand(hand),\n },\n\n // --- audio (glasses media-volume + own-app playback hint) ---\n audio: {\n /** Read the glasses' current media volume. */\n getMediaVolume: () => BluetoothSdk.getGlassesMediaVolume(),\n /** Set the glasses' media volume. */\n setMediaVolume: (level: number) => BluetoothSdk.setGlassesMediaVolume(level),\n /** Tell native whether THIS app is currently playing audio (for ducking). */\n setOwnAppPlaying: (playing: boolean): Promise<void> => BluetoothSdk.setOwnAppAudioPlaying(playing),\n },\n\n // --- sub-facades ---\n wifi: glassesWifi,\n settings: glassesSettings,\n}\n"]}
@@ -38,7 +38,7 @@ function projectReadiness() {
38
38
  function projectTargetReady(options) {
39
39
  const { deviceModel, deviceName } = options;
40
40
  const glasses = useGlassesStore.getState();
41
- if (deviceModel === ControllerTypes.R1) {
41
+ if (deviceModel !== undefined && Object.values(ControllerTypes).includes(deviceModel)) {
42
42
  if (!glasses.controllerConnected || !glasses.controllerFullyBooted)
43
43
  return false;
44
44
  const settings = useSettingsStore.getState();