@glassly/engine 0.3.8-dev.999 → 0.4.0-beta.1023
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/engine.d.ts +11 -0
- package/build/engine.d.ts.map +1 -1
- package/build/facades/ai.d.ts +6 -0
- package/build/facades/ai.d.ts.map +1 -1
- package/build/facades/ai.js +6 -0
- package/build/facades/ai.js.map +1 -1
- package/build/facades/glasses.d.ts +9 -1
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +13 -0
- package/build/facades/glasses.js.map +1 -1
- package/build/generated/releaseMetadata.js +4 -4
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/build/services/CloudClientService.d.ts +2 -1
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +8 -0
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/DeviceEventRouter.d.ts.map +1 -1
- package/build/services/DeviceEventRouter.js +1 -0
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/GlassesSensorService.js +1 -1
- package/build/services/GlassesSensorService.js.map +1 -1
- package/build/services/LlmRouting.d.ts +1 -1
- package/build/services/LlmRouting.js.map +1 -1
- package/build/services/LocalLlmModelManager.d.ts +22 -2
- package/build/services/LocalLlmModelManager.d.ts.map +1 -1
- package/build/services/LocalLlmModelManager.js +104 -2
- package/build/services/LocalLlmModelManager.js.map +1 -1
- package/build/services/LocalLlmProvider.d.ts.map +1 -1
- package/build/services/LocalLlmProvider.js +11 -0
- package/build/services/LocalLlmProvider.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +13 -0
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +61 -5
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/NavigationHandlers.js +1 -1
- package/build/services/NavigationHandlers.js.map +1 -1
- package/build/services/NavigationService.js +6 -6
- package/build/services/NavigationService.js.map +1 -1
- package/build/services/controllers.d.ts.map +1 -1
- package/build/services/controllers.js +1 -0
- package/build/services/controllers.js.map +1 -1
- package/build/services/neuralBand/HandwritingGate.d.ts +38 -0
- package/build/services/neuralBand/HandwritingGate.d.ts.map +1 -0
- package/build/services/neuralBand/HandwritingGate.js +89 -0
- package/build/services/neuralBand/HandwritingGate.js.map +1 -0
- package/build/services/neuralBand/NeuralBandInput.d.ts +12 -1
- package/build/services/neuralBand/NeuralBandInput.d.ts.map +1 -1
- package/build/services/neuralBand/NeuralBandInput.js +27 -0
- package/build/services/neuralBand/NeuralBandInput.js.map +1 -1
- package/build/services/neuralBand/NeuralBandSettingsSync.d.ts.map +1 -1
- package/build/services/neuralBand/NeuralBandSettingsSync.js +36 -3
- package/build/services/neuralBand/NeuralBandSettingsSync.js.map +1 -1
- package/build/stores/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js +0 -1
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +26 -0
- package/build/stores/settings.js.map +1 -1
- package/build/types/enums.d.ts +2 -1
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -0
- package/build/types/enums.js.map +1 -1
- package/package.json +7 -7
- package/src/facades/ai.ts +6 -0
- package/src/facades/glasses.ts +17 -0
- package/src/generated/releaseMetadata.ts +4 -4
- package/src/index.ts +1 -0
- package/src/services/CloudClientService.ts +8 -0
- package/src/services/DeviceEventRouter.ts +1 -0
- package/src/services/GlassesSensorService.ts +1 -1
- package/src/services/LlmRouting.ts +1 -1
- package/src/services/LocalLlmModelManager.ts +110 -3
- package/src/services/LocalLlmProvider.ts +8 -0
- package/src/services/LocalMiniappRuntime.ts +66 -5
- package/src/services/NavigationHandlers.ts +1 -1
- package/src/services/NavigationService.ts +6 -6
- package/src/services/controllers.ts +1 -0
- package/src/services/neuralBand/HandwritingGate.ts +111 -0
- package/src/services/neuralBand/NeuralBandInput.ts +37 -1
- package/src/services/neuralBand/NeuralBandSettingsSync.ts +46 -3
- package/src/stores/appVisibility.ts +0 -1
- package/src/stores/settings.ts +26 -0
- package/src/types/enums.ts +1 -0
|
@@ -291,7 +291,7 @@ function directLlmProvider(name) {
|
|
|
291
291
|
directLlmProviders.set(name, built);
|
|
292
292
|
return built;
|
|
293
293
|
}
|
|
294
|
-
const QUOTA_EXCEEDED_MESSAGE = "
|
|
294
|
+
const QUOTA_EXCEEDED_MESSAGE = "AI credits are used up. Get more in Settings > Membership, or add your own API key in Settings > API Keys.";
|
|
295
295
|
/** The user's saved key (Settings > API Keys) for an LLM provider, "" if none. */
|
|
296
296
|
function userLlmKey(provider) {
|
|
297
297
|
const raw = useSettingsStore.getState().getSetting(MINIAPP_READABLE_API_KEYS[provider]);
|
|
@@ -459,6 +459,9 @@ class LocalMiniappRuntime {
|
|
|
459
459
|
connectedApps = new Map();
|
|
460
460
|
/** Claimed gestures (CLAIM_GESTURES): a stack per gesture, the most recent claimer holding it. */
|
|
461
461
|
gestureClaims = emptyGestureClaims();
|
|
462
|
+
/** Apps with a text field open on the glasses (TEXT_FIELD). */
|
|
463
|
+
textFieldApps = new Set();
|
|
464
|
+
textFieldListeners = new Set();
|
|
462
465
|
// The last main-view frame each app asked to render. Widget mode refuses
|
|
463
466
|
// frames and demotion clears them, and an app that has drawn once may not
|
|
464
467
|
// draw again on its own, so promotion replays this.
|
|
@@ -1038,6 +1041,7 @@ class LocalMiniappRuntime {
|
|
|
1038
1041
|
}
|
|
1039
1042
|
// Its gesture claims go back to whoever claimed them before.
|
|
1040
1043
|
this.applyGestureClaimChanges(dropGestureClaims(this.gestureClaims, packageName));
|
|
1044
|
+
this.setTextFieldOpen(packageName, false);
|
|
1041
1045
|
this.retainedRenders.delete(packageName);
|
|
1042
1046
|
// Warm-up is a request-owned camera lease. Cancel it even if the app record was already
|
|
1043
1047
|
// removed so a close racing the camera-open promise cannot leave the sensor running.
|
|
@@ -1198,6 +1202,9 @@ class LocalMiniappRuntime {
|
|
|
1198
1202
|
case MiniappRequestType.CLAIM_GESTURES:
|
|
1199
1203
|
this.handleClaimGestures(packageName, payload, requestId);
|
|
1200
1204
|
break;
|
|
1205
|
+
case MiniappRequestType.TEXT_FIELD:
|
|
1206
|
+
this.handleTextField(packageName, payload, requestId);
|
|
1207
|
+
break;
|
|
1201
1208
|
case MiniappRequestType.DISPLAY:
|
|
1202
1209
|
this.handleDisplay(packageName, payload, requestId);
|
|
1203
1210
|
break;
|
|
@@ -1862,6 +1869,49 @@ class LocalMiniappRuntime {
|
|
|
1862
1869
|
this.forwardEvent(MiniappStreamType.GESTURE_CLAIM, { gesture: change.gesture, held: change.held }, undefined, change.packageName);
|
|
1863
1870
|
}
|
|
1864
1871
|
}
|
|
1872
|
+
/**
|
|
1873
|
+
* TEXT_FIELD (session.input.setTextFieldOpen): the app has a text field on
|
|
1874
|
+
* the glasses, or no longer does. Text entry that costs power to leave on
|
|
1875
|
+
* (Neural Band handwriting) runs while any app has one. Cleared on app stop.
|
|
1876
|
+
*/
|
|
1877
|
+
handleTextField(packageName, payload, requestId) {
|
|
1878
|
+
if (typeof payload.open !== "boolean") {
|
|
1879
|
+
this.sendResult(packageName, requestId, false, undefined, {
|
|
1880
|
+
code: MiniappErrorCode.INVALID_ARGUMENT,
|
|
1881
|
+
message: "Text field open must be a boolean",
|
|
1882
|
+
});
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
if (this.connectedApps.has(packageName))
|
|
1886
|
+
this.setTextFieldOpen(packageName, payload.open);
|
|
1887
|
+
this.sendResult(packageName, requestId, true);
|
|
1888
|
+
}
|
|
1889
|
+
setTextFieldOpen(packageName, open) {
|
|
1890
|
+
const before = this.textFieldApps.size > 0;
|
|
1891
|
+
if (open)
|
|
1892
|
+
this.textFieldApps.add(packageName);
|
|
1893
|
+
else
|
|
1894
|
+
this.textFieldApps.delete(packageName);
|
|
1895
|
+
const after = this.textFieldApps.size > 0;
|
|
1896
|
+
if (before === after)
|
|
1897
|
+
return;
|
|
1898
|
+
for (const cb of this.textFieldListeners) {
|
|
1899
|
+
try {
|
|
1900
|
+
cb(after);
|
|
1901
|
+
}
|
|
1902
|
+
catch (err) {
|
|
1903
|
+
console.warn(`${LOG_TAG}: text field listener failed:`, err);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
/** True while any running miniapp has a text field open on the glasses. */
|
|
1908
|
+
hasOpenTextField() {
|
|
1909
|
+
return this.textFieldApps.size > 0;
|
|
1910
|
+
}
|
|
1911
|
+
onTextFieldChange(cb) {
|
|
1912
|
+
this.textFieldListeners.add(cb);
|
|
1913
|
+
return () => this.textFieldListeners.delete(cb);
|
|
1914
|
+
}
|
|
1865
1915
|
/** The app holding `gesture` (the most recent claimer), or null when it is unclaimed. */
|
|
1866
1916
|
gestureClaimant(gesture) {
|
|
1867
1917
|
const claimant = gestureClaimant(this.gestureClaims, gesture);
|
|
@@ -3690,8 +3740,8 @@ class LocalMiniappRuntime {
|
|
|
3690
3740
|
this.sendResult(packageName, requestId, true, result);
|
|
3691
3741
|
}
|
|
3692
3742
|
catch (err) {
|
|
3693
|
-
// 402 quota_exceeded from the runtime: the account's
|
|
3694
|
-
//
|
|
3743
|
+
// 402 quota_exceeded from the runtime: the account's AI credits are
|
|
3744
|
+
// spent. Distinct code (miniapps may fall back to a local path) and
|
|
3695
3745
|
// a host hook so the app can offer the upgrade paywall — the miniapp
|
|
3696
3746
|
// itself must never own that conversation.
|
|
3697
3747
|
const quotaExceeded = err instanceof HttpError && (err.code === "quota_exceeded" || err.status === 402);
|
|
@@ -3734,6 +3784,12 @@ class LocalMiniappRuntime {
|
|
|
3734
3784
|
*/
|
|
3735
3785
|
async serveLocalAi(packageName, requestId, request, reason, primaryError) {
|
|
3736
3786
|
const modelId = localLlmModelManager.selectedModelId();
|
|
3787
|
+
const unusable = localLlmModelManager.unusableReason(modelId);
|
|
3788
|
+
if (unusable) {
|
|
3789
|
+
console.warn(`${LOG_TAG}: ai.complete on-device for ${packageName} (${reason}): ${unusable}`);
|
|
3790
|
+
this.sendResult(packageName, requestId, false, undefined, primaryError ?? { code: MiniappErrorCode.AI_LOCAL_UNAVAILABLE, message: unusable });
|
|
3791
|
+
return;
|
|
3792
|
+
}
|
|
3737
3793
|
if (!(await localLlmModelManager.ensureSelectedModel())) {
|
|
3738
3794
|
const status = localLlmModelManager.getStatus();
|
|
3739
3795
|
const state = status?.modelId === modelId && status.stage === "downloading"
|
|
@@ -3744,7 +3800,7 @@ class LocalMiniappRuntime {
|
|
|
3744
3800
|
console.warn(`${LOG_TAG}: ai.complete on-device for ${packageName} (${reason}): model ${modelId} ${state}`);
|
|
3745
3801
|
this.sendResult(packageName, requestId, false, undefined, primaryError ?? {
|
|
3746
3802
|
code: MiniappErrorCode.AI_LOCAL_UNAVAILABLE,
|
|
3747
|
-
message: `The on-device model (${localLlmModelManager.model(modelId).label}) ${state}. Manage it in Settings >
|
|
3803
|
+
message: `The on-device model (${localLlmModelManager.model(modelId).label}) ${state}. Manage it in Settings > Offline Models.`,
|
|
3748
3804
|
});
|
|
3749
3805
|
return;
|
|
3750
3806
|
}
|
|
@@ -3818,7 +3874,7 @@ class LocalMiniappRuntime {
|
|
|
3818
3874
|
this.onQuotaExceeded?.("llm");
|
|
3819
3875
|
this.sendResult(packageName, requestId, false, undefined, {
|
|
3820
3876
|
code: MiniappErrorCode.QUOTA_EXCEEDED,
|
|
3821
|
-
message: "
|
|
3877
|
+
message: "AI credits are used up. Get more in Settings > Membership, or add your own API key in Settings > API Keys.",
|
|
3822
3878
|
});
|
|
3823
3879
|
return;
|
|
3824
3880
|
}
|