@glassly/engine 0.3.2-dev.596 → 0.3.2-dev.599
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/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +6 -1
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/settingsBridge.d.ts +12 -4
- package/build/services/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js +13 -4
- package/build/services/settingsBridge.js.map +1 -1
- package/package.json +7 -7
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/services/LocalMiniappRuntime.ts +6 -0
- package/src/services/settingsBridge.ts +15 -4
|
@@ -16,11 +16,11 @@ export type SettingsBridgeAccess = "read" | "write";
|
|
|
16
16
|
export declare const SETTINGS_BRIDGE_KEYS: Readonly<Record<string, SettingsBridgeAccess>>;
|
|
17
17
|
/**
|
|
18
18
|
* Read-only keys the engine computes: whether the wearer can see the phone,
|
|
19
|
-
* whether the foreground miniapp is drawing on the glasses,
|
|
20
|
-
* battery
|
|
21
|
-
* stored keys.
|
|
19
|
+
* whether the foreground miniapp is drawing on the glasses, the ring's
|
|
20
|
+
* battery, and whether a 2D controller is connected. They change on their
|
|
21
|
+
* own clocks; the runtime pushes them like stored keys.
|
|
22
22
|
*/
|
|
23
|
-
export declare const DERIVED_SETTINGS_KEYS: readonly ["phone_active", "foreground_app_on_screen", "ring_battery"];
|
|
23
|
+
export declare const DERIVED_SETTINGS_KEYS: readonly ["phone_active", "foreground_app_on_screen", "ring_battery", "input_2d"];
|
|
24
24
|
export type DerivedSettingsKey = (typeof DERIVED_SETTINGS_KEYS)[number];
|
|
25
25
|
export declare function isDerivedSettingsKey(key: string): key is DerivedSettingsKey;
|
|
26
26
|
/** What a permitted app may do with `key`, or null when the bridge does not serve it. */
|
|
@@ -56,4 +56,12 @@ export declare function ringBatteryFrom(glasses: {
|
|
|
56
56
|
controllerConnected: boolean;
|
|
57
57
|
controllerBatteryLevel: number;
|
|
58
58
|
}): RingBattery;
|
|
59
|
+
/**
|
|
60
|
+
* Whether the connected controller swipes in two dimensions (sideways as well
|
|
61
|
+
* as up and down): the Meta Neural Band's thumb swipes. The R1 ring and the
|
|
62
|
+
* glasses' temples are one-dimensional.
|
|
63
|
+
*/
|
|
64
|
+
export declare function input2dFrom(glasses: {
|
|
65
|
+
controllerConnected: boolean;
|
|
66
|
+
}, controllerType: unknown): boolean;
|
|
59
67
|
//# sourceMappingURL=settingsBridge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settingsBridge.d.ts","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"settingsBridge.d.ts","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAA;AAEnD,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAkB/E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,mFAAoF,CAAA;AACtH,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,kBAAkB,CAE3E;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAG7E;AAED,wDAAwD;AACxD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,EAAE,CAIrE;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAC,GACvC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,GAAG,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAA;AAE5E,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,qBAAqB,CAY3F;AAED,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAA;IAClB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,aAAa,EAAE,OAAO,CAAA;IACtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,mBAAmB,EAAE,OAAO,CAAA;IAC5B,sBAAsB,EAAE,MAAM,CAAA;CAC/B,GAAG,WAAW,CAMd;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IAAC,mBAAmB,EAAE,OAAO,CAAA;CAAC,EAAE,cAAc,EAAE,OAAO,GAAG,OAAO,CAErG"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* of `menu_apps` and the position behave as if a phone screen wrote them. A dashboard's own look is not here; it keeps
|
|
12
12
|
* that in its storage.
|
|
13
13
|
*/
|
|
14
|
+
import { ControllerTypes } from "../types/enums";
|
|
14
15
|
/** Stored settings the bridge serves, by key, with what a permitted app may do to each. */
|
|
15
16
|
export const SETTINGS_BRIDGE_KEYS = {
|
|
16
17
|
// The dashboard's master switch is a phone-side debug knob.
|
|
@@ -33,11 +34,11 @@ export const SETTINGS_BRIDGE_KEYS = {
|
|
|
33
34
|
};
|
|
34
35
|
/**
|
|
35
36
|
* Read-only keys the engine computes: whether the wearer can see the phone,
|
|
36
|
-
* whether the foreground miniapp is drawing on the glasses,
|
|
37
|
-
* battery
|
|
38
|
-
* stored keys.
|
|
37
|
+
* whether the foreground miniapp is drawing on the glasses, the ring's
|
|
38
|
+
* battery, and whether a 2D controller is connected. They change on their
|
|
39
|
+
* own clocks; the runtime pushes them like stored keys.
|
|
39
40
|
*/
|
|
40
|
-
export const DERIVED_SETTINGS_KEYS = ["phone_active", "foreground_app_on_screen", "ring_battery"];
|
|
41
|
+
export const DERIVED_SETTINGS_KEYS = ["phone_active", "foreground_app_on_screen", "ring_battery", "input_2d"];
|
|
41
42
|
export function isDerivedSettingsKey(key) {
|
|
42
43
|
return DERIVED_SETTINGS_KEYS.includes(key);
|
|
43
44
|
}
|
|
@@ -86,4 +87,12 @@ export function ringBatteryFrom(glasses) {
|
|
|
86
87
|
level: relayed ? glasses.ringBatteryLevel : glasses.controllerBatteryLevel,
|
|
87
88
|
};
|
|
88
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Whether the connected controller swipes in two dimensions (sideways as well
|
|
92
|
+
* as up and down): the Meta Neural Band's thumb swipes. The R1 ring and the
|
|
93
|
+
* glasses' temples are one-dimensional.
|
|
94
|
+
*/
|
|
95
|
+
export function input2dFrom(glasses, controllerType) {
|
|
96
|
+
return glasses.controllerConnected && controllerType === ControllerTypes.NEURAL_BAND;
|
|
97
|
+
}
|
|
89
98
|
//# sourceMappingURL=settingsBridge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settingsBridge.js","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"settingsBridge.js","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The settings bridge's vocabulary (session.settings): which engine settings\n * a miniapp with the PLATFORM_SETTINGS permission may read or write, the\n * derived read-only keys the engine computes rather than stores, and the\n * request validation. Pure, so the runtime's handlers stay thin and this can\n * be tested without the native import surface the runtime pulls in.\n *\n * A dashboard miniapp is the usual consumer: it edits the notification,\n * glasses-menu and display-position keys the phone's settings screens used\n * to, through the store, so persistence, server sync and the Bluetooth sync\n * of `menu_apps` and the position behave as if a phone screen wrote them. A dashboard's own look is not here; it keeps\n * that in its storage.\n */\n\nimport {ControllerTypes} from \"../types/enums\"\n\nexport type SettingsBridgeAccess = \"read\" | \"write\"\n\n/** Stored settings the bridge serves, by key, with what a permitted app may do to each. */\nexport const SETTINGS_BRIDGE_KEYS: Readonly<Record<string, SettingsBridgeAccess>> = {\n // The dashboard's master switch is a phone-side debug knob.\n custom_dashboard_enabled: \"read\",\n contextual_dashboard: \"write\",\n head_up_angle: \"write\",\n // Where the glasses draw; each model's steps are its display.positionRange.\n dashboard_depth: \"write\",\n dashboard_height: \"write\",\n twelve_hour_time: \"write\",\n menu_apps: \"write\",\n notifications_enabled: \"write\",\n notifications_popups: \"write\",\n notifications_popup_seconds: \"write\",\n notifications_hold_during_apps: \"write\",\n notifications_ignore_while_active: \"write\",\n notifications_blocklist: \"write\",\n // Apps the glasses reported posting notifications; the engine records it.\n notification_seen_apps: \"read\",\n}\n\n/**\n * Read-only keys the engine computes: whether the wearer can see the phone,\n * whether the foreground miniapp is drawing on the glasses, the ring's\n * battery, and whether a 2D controller is connected. They change on their\n * own clocks; the runtime pushes them like stored keys.\n */\nexport const DERIVED_SETTINGS_KEYS = [\"phone_active\", \"foreground_app_on_screen\", \"ring_battery\", \"input_2d\"] as const\nexport type DerivedSettingsKey = (typeof DERIVED_SETTINGS_KEYS)[number]\n\nexport function isDerivedSettingsKey(key: string): key is DerivedSettingsKey {\n return (DERIVED_SETTINGS_KEYS as readonly string[]).includes(key)\n}\n\n/** What a permitted app may do with `key`, or null when the bridge does not serve it. */\nexport function settingsBridgeAccess(key: string): SettingsBridgeAccess | null {\n if (isDerivedSettingsKey(key)) return \"read\"\n return SETTINGS_BRIDGE_KEYS[key] ?? null\n}\n\n/** Every key the bridge serves, stored then derived. */\nexport function allSettingsBridgeKeys(): string[] {\n return [...Object.keys(SETTINGS_BRIDGE_KEYS), ...DERIVED_SETTINGS_KEYS]\n}\n\n/**\n * The keys a SETTINGS_GET asks for: everything when `requested` is absent,\n * else the known ones among the requested strings (unknown keys are left\n * out, never rejected).\n */\nexport function selectSettingsBridgeKeys(requested: unknown): string[] {\n if (requested === undefined || requested === null) return allSettingsBridgeKeys()\n if (!Array.isArray(requested)) return []\n return requested.filter((key): key is string => typeof key === \"string\" && settingsBridgeAccess(key) !== null)\n}\n\nexport type SettingsSetValidation =\n | {ok: true; key: string; value: unknown}\n | {ok: false; code: \"INVALID_ARGUMENT\" | \"NOT_PERMITTED\"; message: string}\n\n/** A SETTINGS_SET payload: a writable key and a JSON value (undefined is not a value). */\nexport function validateSettingsSet(payload: Record<string, unknown>): SettingsSetValidation {\n const key = payload.key\n if (typeof key !== \"string\" || !key) {\n return {ok: false, code: \"INVALID_ARGUMENT\", message: \"settings.set requires a key\"}\n }\n const access = settingsBridgeAccess(key)\n if (access === null) return {ok: false, code: \"INVALID_ARGUMENT\", message: `Unknown setting \"${key}\"`}\n if (access !== \"write\") return {ok: false, code: \"NOT_PERMITTED\", message: `Setting \"${key}\" is read-only`}\n if (!(\"value\" in payload) || payload.value === undefined) {\n return {ok: false, code: \"INVALID_ARGUMENT\", message: \"settings.set requires a value\"}\n }\n return {ok: true, key, value: payload.value}\n}\n\n/** The ring's battery as the dashboard shows it: the relayed ring first, else the controller. */\nexport interface RingBattery {\n connected: boolean\n /** -1 when unknown. */\n level: number\n}\n\nexport function ringBatteryFrom(glasses: {\n ringConnected: boolean\n ringBatteryLevel: number\n controllerConnected: boolean\n controllerBatteryLevel: number\n}): RingBattery {\n const relayed = glasses.ringConnected && glasses.ringBatteryLevel >= 0\n return {\n connected: relayed || glasses.controllerConnected,\n level: relayed ? glasses.ringBatteryLevel : glasses.controllerBatteryLevel,\n }\n}\n\n/**\n * Whether the connected controller swipes in two dimensions (sideways as well\n * as up and down): the Meta Neural Band's thumb swipes. The R1 ring and the\n * glasses' temples are one-dimensional.\n */\nexport function input2dFrom(glasses: {controllerConnected: boolean}, controllerType: unknown): boolean {\n return glasses.controllerConnected && controllerType === ControllerTypes.NEURAL_BAND\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassly/engine",
|
|
3
|
-
"version": "0.3.2-dev.
|
|
3
|
+
"version": "0.3.2-dev.599",
|
|
4
4
|
"description": "Glassly Engine — miniapp registry, WebView bridge, and miniapp store",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -97,17 +97,17 @@
|
|
|
97
97
|
"registry": "https://registry.npmjs.org/"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@glassly/bluetooth-sdk": "0.3.2-dev.
|
|
101
|
-
"@glassly/cloud-client": "0.3.2-dev.
|
|
102
|
-
"@glassly/cloud-protocol": "0.3.2-dev.
|
|
103
|
-
"@glassly/crust": "0.3.2-dev.
|
|
104
|
-
"@glassly/miniapp": "0.3.2-dev.
|
|
100
|
+
"@glassly/bluetooth-sdk": "0.3.2-dev.599",
|
|
101
|
+
"@glassly/cloud-client": "0.3.2-dev.599",
|
|
102
|
+
"@glassly/cloud-protocol": "0.3.2-dev.599",
|
|
103
|
+
"@glassly/crust": "0.3.2-dev.599",
|
|
104
|
+
"@glassly/miniapp": "0.3.2-dev.599",
|
|
105
105
|
"buffer": "^6.0.3",
|
|
106
106
|
"events": "^3.3.0",
|
|
107
107
|
"react-native-marked": "8.1.1",
|
|
108
108
|
"semver": "^7.7.4",
|
|
109
109
|
"typesafe-ts": "^1.7.1",
|
|
110
|
-
"@glassly/llm-providers": "0.3.2-dev.
|
|
110
|
+
"@glassly/llm-providers": "0.3.2-dev.599"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
113
|
"@glassly/llm-providers": "workspace:*",
|
|
@@ -12,9 +12,9 @@ export interface EngineReleaseMetadata {
|
|
|
12
12
|
export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
14
|
"familyBaseVersion": "0.3.2",
|
|
15
|
-
"releaseIdentity": "0.3.2-dev.
|
|
16
|
-
"releaseSetId": "glassly-0.3.2-dev.
|
|
17
|
-
"sourceCommit": "
|
|
15
|
+
"releaseIdentity": "0.3.2-dev.599",
|
|
16
|
+
"releaseSetId": "glassly-0.3.2-dev.599",
|
|
17
|
+
"sourceCommit": "8b233044287fc5abbb79168438dc24fcd8b844ca",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
|
@@ -75,6 +75,7 @@ import {installedNotificationApps} from "./PhoneNotificationsSync"
|
|
|
75
75
|
import {
|
|
76
76
|
DERIVED_SETTINGS_KEYS,
|
|
77
77
|
SETTINGS_BRIDGE_KEYS,
|
|
78
|
+
input2dFrom,
|
|
78
79
|
isDerivedSettingsKey,
|
|
79
80
|
ringBatteryFrom,
|
|
80
81
|
selectSettingsBridgeKeys,
|
|
@@ -2574,6 +2575,10 @@ class LocalMiniappRuntime {
|
|
|
2574
2575
|
return localDisplayManager.foregroundAppOnScreen()
|
|
2575
2576
|
case "ring_battery":
|
|
2576
2577
|
return ringBatteryFrom(useGlassesStore.getState())
|
|
2578
|
+
case "input_2d": {
|
|
2579
|
+
const controller = useSettingsStore.getState().getSetting(SETTINGS.default_controller.key)
|
|
2580
|
+
return input2dFrom(useGlassesStore.getState(), controller)
|
|
2581
|
+
}
|
|
2577
2582
|
}
|
|
2578
2583
|
}
|
|
2579
2584
|
|
|
@@ -2670,6 +2675,7 @@ class LocalMiniappRuntime {
|
|
|
2670
2675
|
(s) => `${s.ringConnected}:${s.ringBatteryLevel}:${s.controllerConnected}:${s.controllerBatteryLevel}`,
|
|
2671
2676
|
pushDerived,
|
|
2672
2677
|
)
|
|
2678
|
+
useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.default_controller.key), pushDerived)
|
|
2673
2679
|
}
|
|
2674
2680
|
|
|
2675
2681
|
/**
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* that in its storage.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import {ControllerTypes} from "../types/enums"
|
|
16
|
+
|
|
15
17
|
export type SettingsBridgeAccess = "read" | "write"
|
|
16
18
|
|
|
17
19
|
/** Stored settings the bridge serves, by key, with what a permitted app may do to each. */
|
|
@@ -37,11 +39,11 @@ export const SETTINGS_BRIDGE_KEYS: Readonly<Record<string, SettingsBridgeAccess>
|
|
|
37
39
|
|
|
38
40
|
/**
|
|
39
41
|
* Read-only keys the engine computes: whether the wearer can see the phone,
|
|
40
|
-
* whether the foreground miniapp is drawing on the glasses,
|
|
41
|
-
* battery
|
|
42
|
-
* stored keys.
|
|
42
|
+
* whether the foreground miniapp is drawing on the glasses, the ring's
|
|
43
|
+
* battery, and whether a 2D controller is connected. They change on their
|
|
44
|
+
* own clocks; the runtime pushes them like stored keys.
|
|
43
45
|
*/
|
|
44
|
-
export const DERIVED_SETTINGS_KEYS = ["phone_active", "foreground_app_on_screen", "ring_battery"] as const
|
|
46
|
+
export const DERIVED_SETTINGS_KEYS = ["phone_active", "foreground_app_on_screen", "ring_battery", "input_2d"] as const
|
|
45
47
|
export type DerivedSettingsKey = (typeof DERIVED_SETTINGS_KEYS)[number]
|
|
46
48
|
|
|
47
49
|
export function isDerivedSettingsKey(key: string): key is DerivedSettingsKey {
|
|
@@ -108,3 +110,12 @@ export function ringBatteryFrom(glasses: {
|
|
|
108
110
|
level: relayed ? glasses.ringBatteryLevel : glasses.controllerBatteryLevel,
|
|
109
111
|
}
|
|
110
112
|
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Whether the connected controller swipes in two dimensions (sideways as well
|
|
116
|
+
* as up and down): the Meta Neural Band's thumb swipes. The R1 ring and the
|
|
117
|
+
* glasses' temples are one-dimensional.
|
|
118
|
+
*/
|
|
119
|
+
export function input2dFrom(glasses: {controllerConnected: boolean}, controllerType: unknown): boolean {
|
|
120
|
+
return glasses.controllerConnected && controllerType === ControllerTypes.NEURAL_BAND
|
|
121
|
+
}
|