@elizaos/plugin-facewear 2.0.3-beta.6 → 2.0.3-beta.7
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/dist/actions/display-text.d.ts +4 -0
- package/dist/actions/display-text.d.ts.map +1 -0
- package/dist/actions/display-text.js +90 -0
- package/dist/actions/display-text.js.map +1 -0
- package/dist/actions/facewear-connect.d.ts +3 -0
- package/dist/actions/facewear-connect.d.ts.map +1 -0
- package/dist/actions/facewear-connect.js +70 -0
- package/dist/actions/facewear-connect.js.map +1 -0
- package/dist/actions/facewear-control.d.ts +4 -0
- package/dist/actions/facewear-control.d.ts.map +1 -0
- package/dist/actions/facewear-control.js +627 -0
- package/dist/actions/facewear-control.js.map +1 -0
- package/dist/actions/facewear-debug.d.ts +3 -0
- package/dist/actions/facewear-debug.d.ts.map +1 -0
- package/dist/actions/facewear-debug.js +62 -0
- package/dist/actions/facewear-debug.js.map +1 -0
- package/dist/actions/facewear-status.d.ts +4 -0
- package/dist/actions/facewear-status.d.ts.map +1 -0
- package/dist/actions/facewear-status.js +66 -0
- package/dist/actions/facewear-status.js.map +1 -0
- package/dist/actions/microphone.d.ts +4 -0
- package/dist/actions/microphone.d.ts.map +1 -0
- package/dist/actions/microphone.js +63 -0
- package/dist/actions/microphone.js.map +1 -0
- package/dist/actions/view-actions.d.ts +23 -0
- package/dist/actions/view-actions.d.ts.map +1 -0
- package/dist/actions/view-actions.js +314 -0
- package/dist/actions/view-actions.js.map +1 -0
- package/dist/actions/vision-query.d.ts +4 -0
- package/dist/actions/vision-query.d.ts.map +1 -0
- package/dist/actions/vision-query.js +41 -0
- package/dist/actions/vision-query.js.map +1 -0
- package/dist/actions/xr-view-actions.d.ts +14 -0
- package/dist/actions/xr-view-actions.d.ts.map +1 -0
- package/dist/actions/xr-view-actions.js +29 -0
- package/dist/actions/xr-view-actions.js.map +1 -0
- package/dist/components/FacewearSpatialView.d.ts +50 -0
- package/dist/components/FacewearSpatialView.d.ts.map +1 -0
- package/dist/components/FacewearSpatialView.js +129 -0
- package/dist/components/FacewearSpatialView.js.map +1 -0
- package/dist/components/FacewearView.d.ts +17 -0
- package/dist/components/FacewearView.d.ts.map +1 -0
- package/dist/components/FacewearView.js +88 -0
- package/dist/components/FacewearView.js.map +1 -0
- package/dist/components/SmartglassesPanelView.d.ts +22 -0
- package/dist/components/SmartglassesPanelView.d.ts.map +1 -0
- package/dist/components/SmartglassesPanelView.js +140 -0
- package/dist/components/SmartglassesPanelView.js.map +1 -0
- package/dist/components/SmartglassesSpatialView.d.ts +46 -0
- package/dist/components/SmartglassesSpatialView.d.ts.map +1 -0
- package/dist/components/SmartglassesSpatialView.js +240 -0
- package/dist/components/SmartglassesSpatialView.js.map +1 -0
- package/dist/components/facewear-profiles.d.ts +27 -0
- package/dist/components/facewear-profiles.d.ts.map +1 -0
- package/dist/components/facewear-profiles.js +40 -0
- package/dist/components/facewear-profiles.js.map +1 -0
- package/dist/devices/apple-vision-pro.d.ts +7 -0
- package/dist/devices/apple-vision-pro.d.ts.map +1 -0
- package/dist/devices/apple-vision-pro.js +21 -0
- package/dist/devices/apple-vision-pro.js.map +1 -0
- package/dist/devices/even-realities.d.ts +7 -0
- package/dist/devices/even-realities.d.ts.map +1 -0
- package/dist/devices/even-realities.js +13 -0
- package/dist/devices/even-realities.js.map +1 -0
- package/dist/devices/meta-quest.d.ts +5 -0
- package/dist/devices/meta-quest.d.ts.map +1 -0
- package/dist/devices/meta-quest.js +21 -0
- package/dist/devices/meta-quest.js.map +1 -0
- package/dist/devices/registry.d.ts +19 -0
- package/dist/devices/registry.d.ts.map +1 -0
- package/dist/devices/registry.js +96 -0
- package/dist/devices/registry.js.map +1 -0
- package/dist/devices/xreal.d.ts +7 -0
- package/dist/devices/xreal.d.ts.map +1 -0
- package/dist/devices/xreal.js +19 -0
- package/dist/devices/xreal.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +260 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/smartglasses.d.ts +306 -0
- package/dist/protocol/smartglasses.d.ts.map +1 -0
- package/dist/protocol/smartglasses.js +1485 -0
- package/dist/protocol/smartglasses.js.map +1 -0
- package/dist/protocol/xr.d.ts +137 -0
- package/dist/protocol/xr.d.ts.map +1 -0
- package/dist/protocol/xr.js +18 -0
- package/dist/protocol/xr.js.map +1 -0
- package/dist/providers/facewear-context.d.ts +3 -0
- package/dist/providers/facewear-context.d.ts.map +1 -0
- package/dist/providers/facewear-context.js +59 -0
- package/dist/providers/facewear-context.js.map +1 -0
- package/dist/providers/smartglasses-status.d.ts +3 -0
- package/dist/providers/smartglasses-status.d.ts.map +1 -0
- package/dist/providers/smartglasses-status.js +33 -0
- package/dist/providers/smartglasses-status.js.map +1 -0
- package/dist/register-terminal-view.d.ts +21 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +70 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +8 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +116 -0
- package/dist/register.js.map +1 -0
- package/dist/routes/connect.d.ts +3 -0
- package/dist/routes/connect.d.ts.map +1 -0
- package/dist/routes/connect.js +86 -0
- package/dist/routes/connect.js.map +1 -0
- package/dist/routes/device-config.d.ts +5 -0
- package/dist/routes/device-config.d.ts.map +1 -0
- package/dist/routes/device-config.js +56 -0
- package/dist/routes/device-config.js.map +1 -0
- package/dist/routes/simulator-route.d.ts +8 -0
- package/dist/routes/simulator-route.d.ts.map +1 -0
- package/dist/routes/simulator-route.js +32 -0
- package/dist/routes/simulator-route.js.map +1 -0
- package/dist/routes/status.d.ts +3 -0
- package/dist/routes/status.d.ts.map +1 -0
- package/dist/routes/status.js +34 -0
- package/dist/routes/status.js.map +1 -0
- package/dist/routes/view-host.d.ts +24 -0
- package/dist/routes/view-host.d.ts.map +1 -0
- package/dist/routes/view-host.js +339 -0
- package/dist/routes/view-host.js.map +1 -0
- package/dist/routes/views.d.ts +8 -0
- package/dist/routes/views.d.ts.map +1 -0
- package/dist/routes/views.js +31 -0
- package/dist/routes/views.js.map +1 -0
- package/dist/services/audio-pipeline.d.ts +20 -0
- package/dist/services/audio-pipeline.d.ts.map +1 -0
- package/dist/services/audio-pipeline.js +87 -0
- package/dist/services/audio-pipeline.js.map +1 -0
- package/dist/services/facewear-service.d.ts +26 -0
- package/dist/services/facewear-service.d.ts.map +1 -0
- package/dist/services/facewear-service.js +45 -0
- package/dist/services/facewear-service.js.map +1 -0
- package/dist/services/smartglasses-service.d.ts +244 -0
- package/dist/services/smartglasses-service.d.ts.map +1 -0
- package/dist/services/smartglasses-service.js +821 -0
- package/dist/services/smartglasses-service.js.map +1 -0
- package/dist/services/vision-pipeline.d.ts +16 -0
- package/dist/services/vision-pipeline.d.ts.map +1 -0
- package/dist/services/vision-pipeline.js +39 -0
- package/dist/services/vision-pipeline.js.map +1 -0
- package/dist/services/xr-session-service.d.ts +54 -0
- package/dist/services/xr-session-service.d.ts.map +1 -0
- package/dist/services/xr-session-service.js +345 -0
- package/dist/services/xr-session-service.js.map +1 -0
- package/dist/status-format.d.ts +15 -0
- package/dist/status-format.d.ts.map +1 -0
- package/dist/status-format.js +89 -0
- package/dist/status-format.js.map +1 -0
- package/dist/transport/even-bridge.d.ts +69 -0
- package/dist/transport/even-bridge.d.ts.map +1 -0
- package/dist/transport/even-bridge.js +510 -0
- package/dist/transport/even-bridge.js.map +1 -0
- package/dist/transport/mock.d.ts +42 -0
- package/dist/transport/mock.d.ts.map +1 -0
- package/dist/transport/mock.js +124 -0
- package/dist/transport/mock.js.map +1 -0
- package/dist/transport/noble.d.ts +62 -0
- package/dist/transport/noble.d.ts.map +1 -0
- package/dist/transport/noble.js +256 -0
- package/dist/transport/noble.js.map +1 -0
- package/dist/transport/types.d.ts +36 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +1 -0
- package/dist/transport/types.js.map +1 -0
- package/dist/transport/web-bluetooth.d.ts +58 -0
- package/dist/transport/web-bluetooth.d.ts.map +1 -0
- package/dist/transport/web-bluetooth.js +164 -0
- package/dist/transport/web-bluetooth.js.map +1 -0
- package/dist/ui/FacewearAppView.d.ts +4 -0
- package/dist/ui/FacewearAppView.d.ts.map +1 -0
- package/dist/ui/FacewearAppView.js +257 -0
- package/dist/ui/FacewearAppView.js.map +1 -0
- package/dist/ui/SmartglassesView.d.ts +10 -0
- package/dist/ui/SmartglassesView.d.ts.map +1 -0
- package/dist/ui/SmartglassesView.helpers.d.ts +104 -0
- package/dist/ui/SmartglassesView.helpers.d.ts.map +1 -0
- package/dist/ui/SmartglassesView.helpers.js +261 -0
- package/dist/ui/SmartglassesView.helpers.js.map +1 -0
- package/dist/ui/SmartglassesView.js +1189 -0
- package/dist/ui/SmartglassesView.js.map +1 -0
- package/dist/ui/facewear-view-bundle.d.ts +5 -0
- package/dist/ui/facewear-view-bundle.d.ts.map +1 -0
- package/dist/ui/facewear-view-bundle.js +17 -0
- package/dist/ui/facewear-view-bundle.js.map +1 -0
- package/dist/views/bundle.js +2950 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +5 -5
package/dist/register.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { registerAppShellPage } from "@elizaos/ui/app-shell-registry";
|
|
2
|
+
import { createElement, useEffect, useState } from "react";
|
|
3
|
+
function loadFacewearAppView() {
|
|
4
|
+
return import("./ui/FacewearAppView.js").then((module) => ({
|
|
5
|
+
default: module.FacewearAppView
|
|
6
|
+
}));
|
|
7
|
+
}
|
|
8
|
+
function loadFacewearTuiView() {
|
|
9
|
+
return import("./ui/FacewearAppView.js").then((module) => ({
|
|
10
|
+
default: module.FacewearTuiView
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
function loadSmartglassesView() {
|
|
14
|
+
return import("./ui/SmartglassesView.js").then((module) => ({
|
|
15
|
+
default: module.SmartglassesView
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
function loadSmartglassesTuiView() {
|
|
19
|
+
return import("./ui/FacewearAppView.js").then((module) => ({
|
|
20
|
+
default: module.SmartglassesTuiView
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
function deferredComponent(loader) {
|
|
24
|
+
let cached = null;
|
|
25
|
+
let pending = null;
|
|
26
|
+
function load() {
|
|
27
|
+
if (cached) return Promise.resolve(cached);
|
|
28
|
+
pending ??= loader().then(
|
|
29
|
+
(module) => {
|
|
30
|
+
cached = module.default;
|
|
31
|
+
return cached;
|
|
32
|
+
},
|
|
33
|
+
(error) => {
|
|
34
|
+
pending = null;
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
return pending;
|
|
39
|
+
}
|
|
40
|
+
return function DeferredComponent(props) {
|
|
41
|
+
const [Component, setComponent] = useState(
|
|
42
|
+
cached
|
|
43
|
+
);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (Component) return;
|
|
46
|
+
let cancelled = false;
|
|
47
|
+
void load().then((nextComponent) => {
|
|
48
|
+
if (!cancelled) setComponent(() => nextComponent);
|
|
49
|
+
}).catch(() => {
|
|
50
|
+
if (!cancelled) setComponent(null);
|
|
51
|
+
});
|
|
52
|
+
return () => {
|
|
53
|
+
cancelled = true;
|
|
54
|
+
};
|
|
55
|
+
}, [Component]);
|
|
56
|
+
return Component ? createElement(Component, props) : null;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const FacewearAppView = deferredComponent(loadFacewearAppView);
|
|
60
|
+
const FacewearTuiView = deferredComponent(loadFacewearTuiView);
|
|
61
|
+
const SmartglassesView = deferredComponent(loadSmartglassesView);
|
|
62
|
+
const SmartglassesTuiView = deferredComponent(loadSmartglassesTuiView);
|
|
63
|
+
registerAppShellPage({
|
|
64
|
+
id: "facewear.tui",
|
|
65
|
+
pluginId: "@elizaos/plugin-facewear",
|
|
66
|
+
label: "Facewear TUI",
|
|
67
|
+
icon: "Terminal",
|
|
68
|
+
path: "/apps/facewear/tui",
|
|
69
|
+
order: 80.1,
|
|
70
|
+
group: "hardware",
|
|
71
|
+
loader: loadFacewearTuiView
|
|
72
|
+
});
|
|
73
|
+
registerAppShellPage({
|
|
74
|
+
id: "facewear",
|
|
75
|
+
pluginId: "@elizaos/plugin-facewear",
|
|
76
|
+
label: "Facewear",
|
|
77
|
+
icon: "Glasses",
|
|
78
|
+
path: "/apps/facewear",
|
|
79
|
+
order: 80,
|
|
80
|
+
group: "hardware",
|
|
81
|
+
loader: loadFacewearAppView
|
|
82
|
+
});
|
|
83
|
+
registerAppShellPage({
|
|
84
|
+
id: "smartglasses.tui",
|
|
85
|
+
pluginId: "@elizaos/plugin-facewear",
|
|
86
|
+
label: "Smartglasses TUI",
|
|
87
|
+
icon: "Terminal",
|
|
88
|
+
path: "/apps/smartglasses/tui",
|
|
89
|
+
order: 81.1,
|
|
90
|
+
group: "hardware",
|
|
91
|
+
loader: loadSmartglassesTuiView
|
|
92
|
+
});
|
|
93
|
+
registerAppShellPage({
|
|
94
|
+
id: "smartglasses",
|
|
95
|
+
pluginId: "@elizaos/plugin-facewear",
|
|
96
|
+
label: "Smartglasses",
|
|
97
|
+
icon: "Glasses",
|
|
98
|
+
path: "/apps/smartglasses",
|
|
99
|
+
order: 81,
|
|
100
|
+
group: "hardware",
|
|
101
|
+
loader: loadSmartglassesView
|
|
102
|
+
});
|
|
103
|
+
if (typeof window === "undefined") {
|
|
104
|
+
void import("./register-terminal-view.js").then((m) => {
|
|
105
|
+
m.registerFacewearTerminalView();
|
|
106
|
+
m.registerSmartglassesTerminalView();
|
|
107
|
+
}).catch(() => {
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
FacewearAppView,
|
|
112
|
+
FacewearTuiView,
|
|
113
|
+
SmartglassesTuiView,
|
|
114
|
+
SmartglassesView
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/register.ts"],"sourcesContent":["import { registerAppShellPage } from \"@elizaos/ui/app-shell-registry\";\nimport { type ComponentType, createElement, useEffect, useState } from \"react\";\n\ntype DeferredViewComponent = ComponentType<Record<string, unknown>>;\ntype DeferredViewModule = { default: DeferredViewComponent };\ntype DeferredViewLoader = () => Promise<DeferredViewModule>;\n\nfunction loadFacewearAppView(): Promise<DeferredViewModule> {\n return import(\"./ui/FacewearAppView.js\").then((module) => ({\n default: module.FacewearAppView as DeferredViewComponent,\n }));\n}\n\nfunction loadFacewearTuiView(): Promise<DeferredViewModule> {\n return import(\"./ui/FacewearAppView.js\").then((module) => ({\n default: module.FacewearTuiView as DeferredViewComponent,\n }));\n}\n\nfunction loadSmartglassesView(): Promise<DeferredViewModule> {\n return import(\"./ui/SmartglassesView.js\").then((module) => ({\n default: module.SmartglassesView as DeferredViewComponent,\n }));\n}\n\nfunction loadSmartglassesTuiView(): Promise<DeferredViewModule> {\n return import(\"./ui/FacewearAppView.js\").then((module) => ({\n default: module.SmartglassesTuiView as DeferredViewComponent,\n }));\n}\n\nfunction deferredComponent(loader: DeferredViewLoader): DeferredViewComponent {\n let cached: DeferredViewComponent | null = null;\n let pending: Promise<DeferredViewComponent> | null = null;\n\n function load(): Promise<DeferredViewComponent> {\n if (cached) return Promise.resolve(cached);\n pending ??= loader().then(\n (module) => {\n cached = module.default;\n return cached;\n },\n (error) => {\n pending = null;\n throw error;\n },\n );\n return pending;\n }\n\n return function DeferredComponent(props: Record<string, unknown>) {\n const [Component, setComponent] = useState<DeferredViewComponent | null>(\n cached,\n );\n\n useEffect(() => {\n if (Component) return;\n let cancelled = false;\n void load()\n .then((nextComponent) => {\n if (!cancelled) setComponent(() => nextComponent);\n })\n .catch(() => {\n if (!cancelled) setComponent(null);\n });\n return () => {\n cancelled = true;\n };\n }, [Component]);\n\n return Component ? createElement(Component, props) : null;\n };\n}\n\nexport const FacewearAppView = deferredComponent(loadFacewearAppView);\nexport const FacewearTuiView = deferredComponent(loadFacewearTuiView);\nexport const SmartglassesView = deferredComponent(loadSmartglassesView);\nexport const SmartglassesTuiView = deferredComponent(loadSmartglassesTuiView);\n\nregisterAppShellPage({\n id: \"facewear.tui\",\n pluginId: \"@elizaos/plugin-facewear\",\n label: \"Facewear TUI\",\n icon: \"Terminal\",\n path: \"/apps/facewear/tui\",\n order: 80.1,\n group: \"hardware\",\n loader: loadFacewearTuiView,\n});\n\nregisterAppShellPage({\n id: \"facewear\",\n pluginId: \"@elizaos/plugin-facewear\",\n label: \"Facewear\",\n icon: \"Glasses\",\n path: \"/apps/facewear\",\n order: 80,\n group: \"hardware\",\n loader: loadFacewearAppView,\n});\n\nregisterAppShellPage({\n id: \"smartglasses.tui\",\n pluginId: \"@elizaos/plugin-facewear\",\n label: \"Smartglasses TUI\",\n icon: \"Terminal\",\n path: \"/apps/smartglasses/tui\",\n order: 81.1,\n group: \"hardware\",\n loader: loadSmartglassesTuiView,\n});\n\nregisterAppShellPage({\n id: \"smartglasses\",\n pluginId: \"@elizaos/plugin-facewear\",\n label: \"Smartglasses\",\n icon: \"Glasses\",\n path: \"/apps/smartglasses\",\n order: 81,\n group: \"hardware\",\n loader: loadSmartglassesView,\n});\n\n// In a terminal host (the Node agent, no DOM), register the facewear and\n// smartglasses views so they render inline in the terminal as the unified\n// FacewearSpatialView / SmartglassesSpatialView.\n// Lazy + DOM-guarded so the terminal engine stays out of browser/mobile bundles.\nif (typeof window === \"undefined\") {\n void import(\"./register-terminal-view.js\")\n .then((m) => {\n m.registerFacewearTerminalView();\n m.registerSmartglassesTerminalView();\n })\n .catch(() => {\n // Terminal rendering is best-effort; never block plugin load.\n });\n}\n"],"mappings":"AAAA,SAAS,4BAA4B;AACrC,SAA6B,eAAe,WAAW,gBAAgB;AAMvE,SAAS,sBAAmD;AAC1D,SAAO,OAAO,yBAAyB,EAAE,KAAK,CAAC,YAAY;AAAA,IACzD,SAAS,OAAO;AAAA,EAClB,EAAE;AACJ;AAEA,SAAS,sBAAmD;AAC1D,SAAO,OAAO,yBAAyB,EAAE,KAAK,CAAC,YAAY;AAAA,IACzD,SAAS,OAAO;AAAA,EAClB,EAAE;AACJ;AAEA,SAAS,uBAAoD;AAC3D,SAAO,OAAO,0BAA0B,EAAE,KAAK,CAAC,YAAY;AAAA,IAC1D,SAAS,OAAO;AAAA,EAClB,EAAE;AACJ;AAEA,SAAS,0BAAuD;AAC9D,SAAO,OAAO,yBAAyB,EAAE,KAAK,CAAC,YAAY;AAAA,IACzD,SAAS,OAAO;AAAA,EAClB,EAAE;AACJ;AAEA,SAAS,kBAAkB,QAAmD;AAC5E,MAAI,SAAuC;AAC3C,MAAI,UAAiD;AAErD,WAAS,OAAuC;AAC9C,QAAI,OAAQ,QAAO,QAAQ,QAAQ,MAAM;AACzC,gBAAY,OAAO,EAAE;AAAA,MACnB,CAAC,WAAW;AACV,iBAAS,OAAO;AAChB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU;AACT,kBAAU;AACV,cAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO,SAAS,kBAAkB,OAAgC;AAChE,UAAM,CAAC,WAAW,YAAY,IAAI;AAAA,MAChC;AAAA,IACF;AAEA,cAAU,MAAM;AACd,UAAI,UAAW;AACf,UAAI,YAAY;AAChB,WAAK,KAAK,EACP,KAAK,CAAC,kBAAkB;AACvB,YAAI,CAAC,UAAW,cAAa,MAAM,aAAa;AAAA,MAClD,CAAC,EACA,MAAM,MAAM;AACX,YAAI,CAAC,UAAW,cAAa,IAAI;AAAA,MACnC,CAAC;AACH,aAAO,MAAM;AACX,oBAAY;AAAA,MACd;AAAA,IACF,GAAG,CAAC,SAAS,CAAC;AAEd,WAAO,YAAY,cAAc,WAAW,KAAK,IAAI;AAAA,EACvD;AACF;AAEO,MAAM,kBAAkB,kBAAkB,mBAAmB;AAC7D,MAAM,kBAAkB,kBAAkB,mBAAmB;AAC7D,MAAM,mBAAmB,kBAAkB,oBAAoB;AAC/D,MAAM,sBAAsB,kBAAkB,uBAAuB;AAE5E,qBAAqB;AAAA,EACnB,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AACV,CAAC;AAED,qBAAqB;AAAA,EACnB,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AACV,CAAC;AAED,qBAAqB;AAAA,EACnB,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AACV,CAAC;AAED,qBAAqB;AAAA,EACnB,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AACV,CAAC;AAMD,IAAI,OAAO,WAAW,aAAa;AACjC,OAAK,OAAO,6BAA6B,EACtC,KAAK,CAAC,MAAM;AACX,MAAE,6BAA6B;AAC/B,MAAE,iCAAiC;AAAA,EACrC,CAAC,EACA,MAAM,MAAM;AAAA,EAEb,CAAC;AACL;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/routes/connect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AA0E3C,eAAO,MAAM,YAAY,EAAE,KAa1B,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { networkInterfaces } from "node:os";
|
|
2
|
+
function getLocalIp() {
|
|
3
|
+
const nets = networkInterfaces();
|
|
4
|
+
for (const iface of Object.values(nets)) {
|
|
5
|
+
for (const net of iface ?? []) {
|
|
6
|
+
if (!net.internal && net.family === "IPv4") return net.address;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return "127.0.0.1";
|
|
10
|
+
}
|
|
11
|
+
function getAppUrl() {
|
|
12
|
+
if (process.env.XR_APP_URL) return process.env.XR_APP_URL;
|
|
13
|
+
const port = process.env.VITE_PORT ?? "5173";
|
|
14
|
+
return `http://${getLocalIp()}:${port}`;
|
|
15
|
+
}
|
|
16
|
+
function htmlPage(appUrl) {
|
|
17
|
+
const encoded = encodeURIComponent(appUrl);
|
|
18
|
+
return `<!DOCTYPE html>
|
|
19
|
+
<html lang="en">
|
|
20
|
+
<head>
|
|
21
|
+
<meta charset="utf-8">
|
|
22
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
23
|
+
<title>Connect XR Headset</title>
|
|
24
|
+
<style>
|
|
25
|
+
* { box-sizing: border-box; margin: 0; padding: 0 }
|
|
26
|
+
body { font-family: system-ui, sans-serif; background: #0f0f0f; color: #e5e5e5;
|
|
27
|
+
min-height: 100vh; display: flex; align-items: center; justify-content: center; }
|
|
28
|
+
.card { background: #1a1a1a; border: 1px solid #2a2a2a; border-radius: 16px;
|
|
29
|
+
padding: 40px; max-width: 480px; width: 100%; text-align: center; }
|
|
30
|
+
h1 { font-size: 1.5rem; margin-bottom: 8px; }
|
|
31
|
+
.sub { color: #888; font-size: 0.9rem; margin-bottom: 28px; }
|
|
32
|
+
#qrcanvas { border-radius: 12px; background: white; padding: 12px;
|
|
33
|
+
display: block; margin: 0 auto 24px; }
|
|
34
|
+
.url { background: #111; border: 1px solid #333; border-radius: 8px;
|
|
35
|
+
padding: 10px 16px; font-family: monospace; font-size: 0.85rem;
|
|
36
|
+
word-break: break-all; margin-bottom: 24px; }
|
|
37
|
+
.steps { text-align: left; font-size: 0.85rem; color: #aaa; line-height: 1.7; }
|
|
38
|
+
.steps li { margin-bottom: 4px; }
|
|
39
|
+
.warn { margin-top: 20px; font-size: 0.78rem; color: #f59e0b; }
|
|
40
|
+
</style>
|
|
41
|
+
</head>
|
|
42
|
+
<body>
|
|
43
|
+
<div class="card">
|
|
44
|
+
<h1>Connect XR Headset</h1>
|
|
45
|
+
<p class="sub">Scan to open the XR app on your device</p>
|
|
46
|
+
<canvas id="qrcanvas"></canvas>
|
|
47
|
+
<div class="url">${appUrl}</div>
|
|
48
|
+
<ol class="steps">
|
|
49
|
+
<li>Put on your headset and open the browser</li>
|
|
50
|
+
<li>Scan the QR code or type the URL above</li>
|
|
51
|
+
<li>Allow microphone and camera access when prompted</li>
|
|
52
|
+
<li>The agent will connect automatically</li>
|
|
53
|
+
</ol>
|
|
54
|
+
${appUrl.startsWith("http://") ? `<p class="warn">\u26A0 HTTP URL \u2014 WebXR requires HTTPS on device.<br>Run <code>bun run connect</code> for an HTTPS tunnel.</p>` : ""}
|
|
55
|
+
</div>
|
|
56
|
+
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.4/build/qrcode.min.js"></script>
|
|
57
|
+
<script>
|
|
58
|
+
var url = decodeURIComponent("${encoded}");
|
|
59
|
+
if (typeof QRCode !== "undefined") {
|
|
60
|
+
QRCode.toCanvas(document.getElementById("qrcanvas"), url, { width: 220, margin: 2 }, function(err) {
|
|
61
|
+
if (err) document.getElementById("qrcanvas").style.display = "none";
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
document.getElementById("qrcanvas").style.display = "none";
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
</body>
|
|
68
|
+
</html>`;
|
|
69
|
+
}
|
|
70
|
+
const connectRoute = {
|
|
71
|
+
type: "GET",
|
|
72
|
+
path: "/xr/connect",
|
|
73
|
+
description: "Returns an HTML page with a QR code to connect an XR headset. Set XR_APP_URL env var (or run `bun run connect` in plugins/plugin-facewear/app-xr) to show the correct public URL.",
|
|
74
|
+
routeHandler: async (_ctx) => {
|
|
75
|
+
const url = getAppUrl();
|
|
76
|
+
return {
|
|
77
|
+
status: 200,
|
|
78
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
79
|
+
body: htmlPage(url)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
export {
|
|
84
|
+
connectRoute
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/routes/connect.ts"],"sourcesContent":["import { networkInterfaces } from \"node:os\";\nimport type { Route } from \"@elizaos/core\";\n\nfunction getLocalIp(): string {\n const nets = networkInterfaces();\n for (const iface of Object.values(nets)) {\n for (const net of iface ?? []) {\n if (!net.internal && net.family === \"IPv4\") return net.address;\n }\n }\n return \"127.0.0.1\";\n}\n\nfunction getAppUrl(): string {\n // Set by the connect script when a tunnel is active\n if (process.env.XR_APP_URL) return process.env.XR_APP_URL;\n const port = process.env.VITE_PORT ?? \"5173\";\n return `http://${getLocalIp()}:${port}`;\n}\n\nfunction htmlPage(appUrl: string): string {\n const encoded = encodeURIComponent(appUrl);\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Connect XR Headset</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0 }\n body { font-family: system-ui, sans-serif; background: #0f0f0f; color: #e5e5e5;\n min-height: 100vh; display: flex; align-items: center; justify-content: center; }\n .card { background: #1a1a1a; border: 1px solid #2a2a2a; border-radius: 16px;\n padding: 40px; max-width: 480px; width: 100%; text-align: center; }\n h1 { font-size: 1.5rem; margin-bottom: 8px; }\n .sub { color: #888; font-size: 0.9rem; margin-bottom: 28px; }\n #qrcanvas { border-radius: 12px; background: white; padding: 12px;\n display: block; margin: 0 auto 24px; }\n .url { background: #111; border: 1px solid #333; border-radius: 8px;\n padding: 10px 16px; font-family: monospace; font-size: 0.85rem;\n word-break: break-all; margin-bottom: 24px; }\n .steps { text-align: left; font-size: 0.85rem; color: #aaa; line-height: 1.7; }\n .steps li { margin-bottom: 4px; }\n .warn { margin-top: 20px; font-size: 0.78rem; color: #f59e0b; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <h1>Connect XR Headset</h1>\n <p class=\"sub\">Scan to open the XR app on your device</p>\n <canvas id=\"qrcanvas\"></canvas>\n <div class=\"url\">${appUrl}</div>\n <ol class=\"steps\">\n <li>Put on your headset and open the browser</li>\n <li>Scan the QR code or type the URL above</li>\n <li>Allow microphone and camera access when prompted</li>\n <li>The agent will connect automatically</li>\n </ol>\n ${appUrl.startsWith(\"http://\") ? `<p class=\"warn\">⚠ HTTP URL — WebXR requires HTTPS on device.<br>Run <code>bun run connect</code> for an HTTPS tunnel.</p>` : \"\"}\n </div>\n <script src=\"https://cdn.jsdelivr.net/npm/qrcode@1.5.4/build/qrcode.min.js\"></script>\n <script>\n var url = decodeURIComponent(\"${encoded}\");\n if (typeof QRCode !== \"undefined\") {\n QRCode.toCanvas(document.getElementById(\"qrcanvas\"), url, { width: 220, margin: 2 }, function(err) {\n if (err) document.getElementById(\"qrcanvas\").style.display = \"none\";\n });\n } else {\n document.getElementById(\"qrcanvas\").style.display = \"none\";\n }\n </script>\n</body>\n</html>`;\n}\n\nexport const connectRoute: Route = {\n type: \"GET\",\n path: \"/xr/connect\",\n description:\n \"Returns an HTML page with a QR code to connect an XR headset. Set XR_APP_URL env var (or run `bun run connect` in plugins/plugin-facewear/app-xr) to show the correct public URL.\",\n routeHandler: async (_ctx) => {\n const url = getAppUrl();\n return {\n status: 200,\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n body: htmlPage(url),\n };\n },\n};\n"],"mappings":"AAAA,SAAS,yBAAyB;AAGlC,SAAS,aAAqB;AAC5B,QAAM,OAAO,kBAAkB;AAC/B,aAAW,SAAS,OAAO,OAAO,IAAI,GAAG;AACvC,eAAW,OAAO,SAAS,CAAC,GAAG;AAC7B,UAAI,CAAC,IAAI,YAAY,IAAI,WAAW,OAAQ,QAAO,IAAI;AAAA,IACzD;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAoB;AAE3B,MAAI,QAAQ,IAAI,WAAY,QAAO,QAAQ,IAAI;AAC/C,QAAM,OAAO,QAAQ,IAAI,aAAa;AACtC,SAAO,UAAU,WAAW,CAAC,IAAI,IAAI;AACvC;AAEA,SAAS,SAAS,QAAwB;AACxC,QAAM,UAAU,mBAAmB,MAAM;AACzC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBA6Bc,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOvB,OAAO,WAAW,SAAS,IAAI,wIAA8H,EAAE;AAAA;AAAA;AAAA;AAAA,oCAIjI,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAW3C;AAEO,MAAM,eAAsB;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aACE;AAAA,EACF,cAAc,OAAO,SAAS;AAC5B,UAAM,MAAM,UAAU;AACtB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,2BAA2B;AAAA,MACtD,MAAM,SAAS,GAAG;AAAA,IACpB;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-config.d.ts","sourceRoot":"","sources":["../../src/routes/device-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAW3C,eAAO,MAAM,oBAAoB,EAAE,KAQlC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAmBjC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAYjC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAllDeviceProfiles,
|
|
3
|
+
getDeviceProfile,
|
|
4
|
+
isFacewearDeviceType
|
|
5
|
+
} from "../devices/registry.js";
|
|
6
|
+
import {
|
|
7
|
+
FACEWEAR_SERVICE_TYPE
|
|
8
|
+
} from "../services/facewear-service.js";
|
|
9
|
+
const facewearDevicesRoute = {
|
|
10
|
+
path: "/api/facewear/devices",
|
|
11
|
+
type: "GET",
|
|
12
|
+
routeHandler: async (_ctx) => ({
|
|
13
|
+
status: 200,
|
|
14
|
+
headers: { "Content-Type": "application/json" },
|
|
15
|
+
body: JSON.stringify({ devices: getAllDeviceProfiles() })
|
|
16
|
+
})
|
|
17
|
+
};
|
|
18
|
+
const facewearDeviceRoute = {
|
|
19
|
+
path: "/api/facewear/devices/:id",
|
|
20
|
+
type: "GET",
|
|
21
|
+
routeHandler: async (ctx) => {
|
|
22
|
+
const id = ctx.params.id;
|
|
23
|
+
const profile = isFacewearDeviceType(id) ? getDeviceProfile(id) : void 0;
|
|
24
|
+
if (!profile) {
|
|
25
|
+
return {
|
|
26
|
+
status: 404,
|
|
27
|
+
headers: { "Content-Type": "application/json" },
|
|
28
|
+
body: JSON.stringify({ error: "Device not found" })
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
status: 200,
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
body: JSON.stringify(profile)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const facewearStatusRoute = {
|
|
39
|
+
path: "/api/facewear/status",
|
|
40
|
+
type: "GET",
|
|
41
|
+
routeHandler: async (ctx) => {
|
|
42
|
+
const svc = ctx.runtime?.getService(FACEWEAR_SERVICE_TYPE);
|
|
43
|
+
const devices = svc?.getConnectedDevices() ?? [];
|
|
44
|
+
return {
|
|
45
|
+
status: 200,
|
|
46
|
+
headers: { "Content-Type": "application/json" },
|
|
47
|
+
body: JSON.stringify({ connected: devices.length > 0, devices })
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
facewearDeviceRoute,
|
|
53
|
+
facewearDevicesRoute,
|
|
54
|
+
facewearStatusRoute
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=device-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/routes/device-config.ts"],"sourcesContent":["import type { Route } from \"@elizaos/core\";\nimport {\n getAllDeviceProfiles,\n getDeviceProfile,\n isFacewearDeviceType,\n} from \"../devices/registry.js\";\nimport {\n FACEWEAR_SERVICE_TYPE,\n type FacewearService,\n} from \"../services/facewear-service.js\";\n\nexport const facewearDevicesRoute: Route = {\n path: \"/api/facewear/devices\",\n type: \"GET\",\n routeHandler: async (_ctx) => ({\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ devices: getAllDeviceProfiles() }),\n }),\n};\n\nexport const facewearDeviceRoute: Route = {\n path: \"/api/facewear/devices/:id\",\n type: \"GET\",\n routeHandler: async (ctx) => {\n const id = (ctx.params as Record<string, string>).id;\n const profile = isFacewearDeviceType(id) ? getDeviceProfile(id) : undefined;\n if (!profile) {\n return {\n status: 404,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ error: \"Device not found\" }),\n };\n }\n return {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(profile),\n };\n },\n};\n\nexport const facewearStatusRoute: Route = {\n path: \"/api/facewear/status\",\n type: \"GET\",\n routeHandler: async (ctx) => {\n const svc = ctx.runtime?.getService<FacewearService>(FACEWEAR_SERVICE_TYPE);\n const devices = svc?.getConnectedDevices() ?? [];\n return {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ connected: devices.length > 0, devices }),\n };\n },\n};\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OAEK;AAEA,MAAM,uBAA8B;AAAA,EACzC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,cAAc,OAAO,UAAU;AAAA,IAC7B,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,qBAAqB,EAAE,CAAC;AAAA,EAC1D;AACF;AAEO,MAAM,sBAA6B;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,cAAc,OAAO,QAAQ;AAC3B,UAAM,KAAM,IAAI,OAAkC;AAClD,UAAM,UAAU,qBAAqB,EAAE,IAAI,iBAAiB,EAAE,IAAI;AAClE,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,mBAAmB,CAAC;AAAA,MACpD;AAAA,IACF;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,MAAM,sBAA6B;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,cAAc,OAAO,QAAQ;AAC3B,UAAM,MAAM,IAAI,SAAS,WAA4B,qBAAqB;AAC1E,UAAM,UAAU,KAAK,oBAAoB,KAAK,CAAC;AAC/C,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,WAAW,QAAQ,SAAS,GAAG,QAAQ,CAAC;AAAA,IACjE;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Route } from "@elizaos/core";
|
|
2
|
+
/**
|
|
3
|
+
* Serves the built WebXR emulator bundle at GET /api/xr/simulator.js
|
|
4
|
+
* Only active when the bundle exists (i.e., after `bun run emulator:build`).
|
|
5
|
+
* Used by Playwright tests that prefer HTTP-served scripts over filesystem paths.
|
|
6
|
+
*/
|
|
7
|
+
export declare const simulatorRoute: Route;
|
|
8
|
+
//# sourceMappingURL=simulator-route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simulator-route.d.ts","sourceRoot":"","sources":["../../src/routes/simulator-route.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAM3C;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,KAuB5B,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
const pluginRoot = resolve(__dirname, "../../");
|
|
6
|
+
const EMULATOR_BUNDLE = resolve(pluginRoot, "../../emulator/dist/emulator.js");
|
|
7
|
+
const simulatorRoute = {
|
|
8
|
+
type: "GET",
|
|
9
|
+
path: "/xr/simulator.js",
|
|
10
|
+
description: "Serves the XR device emulator bundle (IWER + camera injection) for Playwright testing. Build first: cd plugins/plugin-facewear/emulator && bun run build",
|
|
11
|
+
routeHandler: async (_ctx) => {
|
|
12
|
+
if (!existsSync(EMULATOR_BUNDLE)) {
|
|
13
|
+
return {
|
|
14
|
+
status: 404,
|
|
15
|
+
body: {
|
|
16
|
+
error: "Emulator bundle not built",
|
|
17
|
+
hint: "Run: cd eliza/plugins/plugin-facewear/emulator && bun run build"
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const js = readFileSync(EMULATOR_BUNDLE, "utf8");
|
|
22
|
+
return {
|
|
23
|
+
status: 200,
|
|
24
|
+
headers: { "Content-Type": "application/javascript; charset=utf-8" },
|
|
25
|
+
body: js
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
simulatorRoute
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=simulator-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/routes/simulator-route.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Route } from \"@elizaos/core\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pluginRoot = resolve(__dirname, \"../../\");\nconst EMULATOR_BUNDLE = resolve(pluginRoot, \"../../emulator/dist/emulator.js\");\n\n/**\n * Serves the built WebXR emulator bundle at GET /api/xr/simulator.js\n * Only active when the bundle exists (i.e., after `bun run emulator:build`).\n * Used by Playwright tests that prefer HTTP-served scripts over filesystem paths.\n */\nexport const simulatorRoute: Route = {\n type: \"GET\",\n path: \"/xr/simulator.js\",\n description:\n \"Serves the XR device emulator bundle (IWER + camera injection) for Playwright testing. Build first: cd plugins/plugin-facewear/emulator && bun run build\",\n routeHandler: async (_ctx) => {\n if (!existsSync(EMULATOR_BUNDLE)) {\n return {\n status: 404,\n body: {\n error: \"Emulator bundle not built\",\n hint: \"Run: cd eliza/plugins/plugin-facewear/emulator && bun run build\",\n },\n };\n }\n\n const js = readFileSync(EMULATOR_BUNDLE, \"utf8\");\n return {\n status: 200,\n headers: { \"Content-Type\": \"application/javascript; charset=utf-8\" },\n body: js,\n };\n },\n};\n"],"mappings":"AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAG9B,MAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,MAAM,aAAa,QAAQ,WAAW,QAAQ;AAC9C,MAAM,kBAAkB,QAAQ,YAAY,iCAAiC;AAOtE,MAAM,iBAAwB;AAAA,EACnC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aACE;AAAA,EACF,cAAc,OAAO,SAAS;AAC5B,QAAI,CAAC,WAAW,eAAe,GAAG;AAChC,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,UACJ,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK,aAAa,iBAAiB,MAAM;AAC/C,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,wCAAwC;AAAA,MACnE,MAAM;AAAA,IACR;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/routes/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAM3C,eAAO,MAAM,WAAW,EAAE,KA6BzB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
XR_SERVICE_TYPE
|
|
3
|
+
} from "../services/xr-session-service.js";
|
|
4
|
+
const statusRoute = {
|
|
5
|
+
type: "GET",
|
|
6
|
+
path: "/xr/status",
|
|
7
|
+
description: "Returns the list of connected XR devices and session state",
|
|
8
|
+
routeHandler: async (ctx) => {
|
|
9
|
+
const svc = ctx.runtime.getService(XR_SERVICE_TYPE);
|
|
10
|
+
if (!svc) {
|
|
11
|
+
return {
|
|
12
|
+
status: 503,
|
|
13
|
+
body: { error: "XR service not running" }
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const conns = svc.getConnections().map((c) => ({
|
|
17
|
+
id: c.id,
|
|
18
|
+
deviceType: c.deviceType,
|
|
19
|
+
connectedAt: c.connectedAt.toISOString(),
|
|
20
|
+
hasRecentFrame: svc.getVisionPipeline().hasRecentFrame(c.id)
|
|
21
|
+
}));
|
|
22
|
+
return {
|
|
23
|
+
status: 200,
|
|
24
|
+
body: {
|
|
25
|
+
connected: conns.length > 0,
|
|
26
|
+
connections: conns
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
export {
|
|
32
|
+
statusRoute
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/routes/status.ts"],"sourcesContent":["import type { Route } from \"@elizaos/core\";\nimport {\n XR_SERVICE_TYPE,\n type XRSessionService,\n} from \"../services/xr-session-service.js\";\n\nexport const statusRoute: Route = {\n type: \"GET\",\n path: \"/xr/status\",\n description: \"Returns the list of connected XR devices and session state\",\n routeHandler: async (ctx) => {\n const svc = ctx.runtime.getService<XRSessionService>(XR_SERVICE_TYPE);\n\n if (!svc) {\n return {\n status: 503,\n body: { error: \"XR service not running\" },\n };\n }\n\n const conns = svc.getConnections().map((c) => ({\n id: c.id,\n deviceType: c.deviceType,\n connectedAt: c.connectedAt.toISOString(),\n hasRecentFrame: svc.getVisionPipeline().hasRecentFrame(c.id),\n }));\n\n return {\n status: 200,\n body: {\n connected: conns.length > 0,\n connections: conns,\n },\n };\n },\n};\n"],"mappings":"AACA;AAAA,EACE;AAAA,OAEK;AAEA,MAAM,cAAqB;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,cAAc,OAAO,QAAQ;AAC3B,UAAM,MAAM,IAAI,QAAQ,WAA6B,eAAe;AAEpE,QAAI,CAAC,KAAK;AACR,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM,EAAE,OAAO,yBAAyB;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,eAAe,EAAE,IAAI,CAAC,OAAO;AAAA,MAC7C,IAAI,EAAE;AAAA,MACN,YAAY,EAAE;AAAA,MACd,aAAa,EAAE,YAAY,YAAY;AAAA,MACvC,gBAAgB,IAAI,kBAAkB,EAAE,eAAe,EAAE,EAAE;AAAA,IAC7D,EAAE;AAEF,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ,WAAW,MAAM,SAAS;AAAA,QAC1B,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Route } from "@elizaos/core";
|
|
2
|
+
/**
|
|
3
|
+
* GET /api/xr/view-host/:id
|
|
4
|
+
*
|
|
5
|
+
* Serves a self-contained HTML page that loads and renders a registered
|
|
6
|
+
* elizaOS view bundle inside an XR-optimised shell. App-xr opens this URL
|
|
7
|
+
* in an iframe that is overlaid on the WebXR scene.
|
|
8
|
+
*
|
|
9
|
+
* The host page:
|
|
10
|
+
* 1. Loads React + ReactDOM from the CDN (same versions as the view bundles).
|
|
11
|
+
* 2. Dynamically imports the view bundle from the agent's /api/views/:id/bundle.js.
|
|
12
|
+
* 3. Mounts the view component inside an XR-friendly dark-theme container.
|
|
13
|
+
* 4. Provides a minimal elizaOS context (agentBaseUrl, viewId, postMessage bridge).
|
|
14
|
+
* 5. Routes voice transcript text to the focused form input.
|
|
15
|
+
*
|
|
16
|
+
* Inter-frame communication (postMessage):
|
|
17
|
+
* Parent → host: { type:"xr:transcript", text:"..." } — fill focused input
|
|
18
|
+
* { type:"xr:focus-next" } — tab to next field
|
|
19
|
+
* Host → parent: { type:"xr:view-ready", viewId:"..." }
|
|
20
|
+
* { type:"xr:navigate", viewId:"..." }
|
|
21
|
+
* { type:"xr:close" }
|
|
22
|
+
*/
|
|
23
|
+
export declare const viewHostRoute: Route;
|
|
24
|
+
//# sourceMappingURL=view-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-host.d.ts","sourceRoot":"","sources":["../../src/routes/view-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,EAAE,KAkC3B,CAAC"}
|