@elizaos/plugin-xr 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.
Files changed (83) hide show
  1. package/dist/actions/xr-query-vision.d.ts +3 -0
  2. package/dist/actions/xr-query-vision.d.ts.map +1 -0
  3. package/dist/actions/xr-query-vision.js +39 -0
  4. package/dist/actions/xr-query-vision.js.map +1 -0
  5. package/dist/actions/xr-view-actions.d.ts +18 -0
  6. package/dist/actions/xr-view-actions.d.ts.map +1 -0
  7. package/dist/actions/xr-view-actions.js +304 -0
  8. package/dist/actions/xr-view-actions.js.map +1 -0
  9. package/dist/index.d.ts +8 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +57 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/protocol.d.ts +124 -0
  14. package/dist/protocol.d.ts.map +1 -0
  15. package/dist/protocol.js +18 -0
  16. package/dist/protocol.js.map +1 -0
  17. package/dist/providers/xr-context.d.ts +3 -0
  18. package/dist/providers/xr-context.d.ts.map +1 -0
  19. package/dist/providers/xr-context.js +34 -0
  20. package/dist/providers/xr-context.js.map +1 -0
  21. package/dist/routes/xr-connect.d.ts +3 -0
  22. package/dist/routes/xr-connect.d.ts.map +1 -0
  23. package/{src/routes/xr-connect.ts → dist/routes/xr-connect.js} +12 -15
  24. package/dist/routes/xr-connect.js.map +1 -0
  25. package/dist/routes/xr-simulator-route.d.ts +8 -0
  26. package/dist/routes/xr-simulator-route.d.ts.map +1 -0
  27. package/{src/routes/xr-simulator-route.ts → dist/routes/xr-simulator-route.js} +10 -16
  28. package/dist/routes/xr-simulator-route.js.map +1 -0
  29. package/dist/routes/xr-status.d.ts +3 -0
  30. package/dist/routes/xr-status.d.ts.map +1 -0
  31. package/{src/routes/xr-status.ts → dist/routes/xr-status.js} +13 -15
  32. package/dist/routes/xr-status.js.map +1 -0
  33. package/dist/routes/xr-view-host.d.ts +24 -0
  34. package/dist/routes/xr-view-host.d.ts.map +1 -0
  35. package/{src/routes/xr-view-host.ts → dist/routes/xr-view-host.js} +22 -59
  36. package/dist/routes/xr-view-host.js.map +1 -0
  37. package/dist/routes/xr-views.d.ts +8 -0
  38. package/dist/routes/xr-views.d.ts.map +1 -0
  39. package/dist/routes/xr-views.js +31 -0
  40. package/dist/routes/xr-views.js.map +1 -0
  41. package/dist/services/audio-pipeline.d.ts +20 -0
  42. package/dist/services/audio-pipeline.d.ts.map +1 -0
  43. package/{src/services/audio-pipeline.ts → dist/services/audio-pipeline.js} +25 -58
  44. package/dist/services/audio-pipeline.js.map +1 -0
  45. package/dist/services/vision-pipeline.d.ts +16 -0
  46. package/dist/services/vision-pipeline.d.ts.map +1 -0
  47. package/dist/services/vision-pipeline.js +39 -0
  48. package/dist/services/vision-pipeline.js.map +1 -0
  49. package/dist/services/xr-session-service.d.ts +50 -0
  50. package/dist/services/xr-session-service.d.ts.map +1 -0
  51. package/{src/services/xr-session-service.ts → dist/services/xr-session-service.js} +85 -194
  52. package/dist/services/xr-session-service.js.map +1 -0
  53. package/package.json +9 -4
  54. package/AGENTS.md +0 -151
  55. package/CLAUDE.md +0 -151
  56. package/simulator/bun.lock +0 -159
  57. package/simulator/package.json +0 -28
  58. package/simulator/src/emulator.ts +0 -174
  59. package/simulator/src/mock-agent.ts +0 -233
  60. package/simulator/src/node.ts +0 -9
  61. package/simulator/src/playwright-fixture.ts +0 -169
  62. package/simulator/src/types.ts +0 -51
  63. package/simulator/tsconfig.json +0 -13
  64. package/simulator/vite.config.ts +0 -25
  65. package/src/__tests__/audio-pipeline.test.ts +0 -129
  66. package/src/__tests__/protocol.test.ts +0 -53
  67. package/src/__tests__/routes-e2e.test.ts +0 -276
  68. package/src/__tests__/vision-pipeline.test.ts +0 -73
  69. package/src/__tests__/xr-bundle-coverage.test.ts +0 -303
  70. package/src/__tests__/xr-feature-parity.test.ts +0 -524
  71. package/src/__tests__/xr-functional-parity.test.ts +0 -522
  72. package/src/__tests__/xr-view-host-http.test.ts +0 -239
  73. package/src/__tests__/xr-view-host.test.ts +0 -174
  74. package/src/actions/xr-query-vision.ts +0 -64
  75. package/src/actions/xr-view-actions.ts +0 -386
  76. package/src/index.ts +0 -55
  77. package/src/protocol.ts +0 -126
  78. package/src/providers/xr-context.ts +0 -49
  79. package/src/routes/xr-views.ts +0 -43
  80. package/src/services/vision-pipeline.ts +0 -57
  81. package/tsconfig.build.json +0 -9
  82. package/tsconfig.json +0 -30
  83. package/vitest.config.ts +0 -21
@@ -1,203 +1,132 @@
1
- import type {
2
- Content,
3
- HandlerCallback,
4
- IAgentRuntime,
5
- Memory,
6
- UUID,
7
- } from "@elizaos/core";
8
1
  import {
9
2
  ChannelType,
10
3
  createMessageMemory,
11
4
  ModelType,
12
- Service,
5
+ Service
13
6
  } from "@elizaos/core";
14
- import { type WebSocket, WebSocketServer } from "ws";
7
+ import { WebSocketServer } from "ws";
15
8
  import {
16
9
  decodeBinaryFrame,
17
- encodeBinaryFrame,
18
- type XRClientControl,
19
- type XRDeviceType,
20
- type XRPanelConfig,
21
- type XRServerControl,
22
- type XRTTSAudioHeader,
23
- } from "../protocol.ts";
24
- import { AudioPipeline } from "./audio-pipeline.ts";
25
- import { VisionPipeline } from "./vision-pipeline.ts";
26
-
27
- export const XR_SERVICE_TYPE = "xr-session";
28
- export const XR_WS_PORT_DEFAULT = 31338;
29
- export const XR_WS_PORT_ENV = "XR_WS_PORT";
30
-
31
- export interface XRConnection {
32
- id: string;
33
- ws: WebSocket;
34
- deviceType: XRDeviceType;
35
- entityId: UUID;
36
- roomId: UUID;
37
- connectedAt: Date;
38
- }
39
-
40
- export class XRSessionService extends Service {
41
- static override serviceType = XR_SERVICE_TYPE;
42
-
43
- readonly capabilityDescription =
44
- "Streams audio and camera from XR headsets (Quest 3, XReal) to the agent and returns voice responses.";
45
-
46
- private wss!: WebSocketServer;
47
- private connections = new Map<string, XRConnection>();
48
- private audioPipeline!: AudioPipeline;
49
- private visionPipeline!: VisionPipeline;
50
-
51
- static override async start(runtime: IAgentRuntime): Promise<Service> {
10
+ encodeBinaryFrame
11
+ } from "../protocol.js";
12
+ import { AudioPipeline } from "./audio-pipeline.js";
13
+ import { VisionPipeline } from "./vision-pipeline.js";
14
+ const XR_SERVICE_TYPE = "xr-session";
15
+ const XR_WS_PORT_DEFAULT = 31338;
16
+ const XR_WS_PORT_ENV = "XR_WS_PORT";
17
+ class XRSessionService extends Service {
18
+ static serviceType = XR_SERVICE_TYPE;
19
+ capabilityDescription = "Streams audio and camera from XR headsets (Quest 3, XReal) to the agent and returns voice responses.";
20
+ wss;
21
+ connections = /* @__PURE__ */ new Map();
22
+ audioPipeline;
23
+ visionPipeline;
24
+ static async start(runtime) {
52
25
  const svc = new XRSessionService(runtime);
53
26
  await svc.initialize(runtime);
54
27
  return svc;
55
28
  }
56
-
57
- private async initialize(runtime: IAgentRuntime): Promise<void> {
29
+ async initialize(runtime) {
58
30
  this.visionPipeline = new VisionPipeline();
59
31
  this.audioPipeline = new AudioPipeline(
60
32
  runtime,
61
- (connectionId, transcript) =>
62
- this.handleTranscript(connectionId, transcript),
33
+ (connectionId, transcript) => this.handleTranscript(connectionId, transcript)
63
34
  );
64
-
65
35
  const port = Number(
66
- runtime.getSetting(XR_WS_PORT_ENV) ?? XR_WS_PORT_DEFAULT,
36
+ runtime.getSetting(XR_WS_PORT_ENV) ?? XR_WS_PORT_DEFAULT
67
37
  );
68
38
  this.wss = new WebSocketServer({ port });
69
-
70
- this.wss.on("connection", (ws: WebSocket) => this.onConnect(runtime, ws));
71
- this.wss.on("error", (err: Error) =>
72
- console.error("[plugin-xr] WebSocket server error:", err),
39
+ this.wss.on("connection", (ws) => this.onConnect(runtime, ws));
40
+ this.wss.on(
41
+ "error",
42
+ (err) => console.error("[plugin-xr] WebSocket server error:", err)
73
43
  );
74
-
75
44
  console.info(
76
- `[plugin-xr] WebSocket server listening on ws://localhost:${port}`,
45
+ `[plugin-xr] WebSocket server listening on ws://localhost:${port}`
77
46
  );
78
47
  }
79
-
80
- override async stop(): Promise<void> {
48
+ async stop() {
81
49
  for (const conn of this.connections.values()) {
82
50
  this.audioPipeline.clear(conn.id);
83
51
  this.visionPipeline.clear(conn.id);
84
52
  conn.ws.close();
85
53
  }
86
54
  this.connections.clear();
87
- await new Promise<void>((resolve) => this.wss.close(() => resolve()));
55
+ await new Promise((resolve) => this.wss.close(() => resolve()));
88
56
  }
89
-
90
57
  // ── Public accessors used by provider / action ──────────────────────────
91
-
92
- getConnections(): XRConnection[] {
58
+ getConnections() {
93
59
  return [...this.connections.values()];
94
60
  }
95
-
96
- hasActiveConnections(): boolean {
61
+ hasActiveConnections() {
97
62
  return this.connections.size > 0;
98
63
  }
99
-
100
- getVisionPipeline(): VisionPipeline {
64
+ getVisionPipeline() {
101
65
  return this.visionPipeline;
102
66
  }
103
-
104
- sendText(connectionId: string, text: string): void {
67
+ sendText(connectionId, text) {
105
68
  const conn = this.connections.get(connectionId);
106
69
  if (!conn || conn.ws.readyState !== conn.ws.OPEN) return;
107
70
  conn.ws.send(JSON.stringify({ type: "agent_text", text }));
108
71
  }
109
-
110
- sendControl(connectionId: string, msg: XRServerControl): void {
72
+ sendControl(connectionId, msg) {
111
73
  const conn = this.connections.get(connectionId);
112
74
  if (!conn || conn.ws.readyState !== conn.ws.OPEN) return;
113
75
  conn.ws.send(JSON.stringify(msg));
114
76
  }
115
-
116
- broadcastControl(msg: XRServerControl): void {
77
+ broadcastControl(msg) {
117
78
  for (const conn of this.connections.values()) {
118
79
  if (conn.ws.readyState === conn.ws.OPEN) {
119
80
  conn.ws.send(JSON.stringify(msg));
120
81
  }
121
82
  }
122
83
  }
123
-
124
- openView(
125
- connectionId: string,
126
- viewId: string,
127
- agentBaseUrl: string,
128
- config?: XRPanelConfig,
129
- ): void {
84
+ openView(connectionId, viewId, agentBaseUrl, config) {
130
85
  this.sendControl(connectionId, {
131
86
  type: "view_open",
132
87
  viewId,
133
88
  agentBaseUrl,
134
- config,
89
+ config
135
90
  });
136
91
  }
137
-
138
- closeView(connectionId: string, viewId: string): void {
92
+ closeView(connectionId, viewId) {
139
93
  this.sendControl(connectionId, { type: "view_close", viewId });
140
94
  }
141
-
142
- switchView(connectionId: string, viewId: string): void {
95
+ switchView(connectionId, viewId) {
143
96
  this.sendControl(connectionId, { type: "view_switch", viewId });
144
97
  }
145
-
146
- resizeView(
147
- connectionId: string,
148
- viewId: string,
149
- config: XRPanelConfig,
150
- ): void {
98
+ resizeView(connectionId, viewId, config) {
151
99
  this.sendControl(connectionId, { type: "view_resize", viewId, config });
152
100
  }
153
-
154
- sendViewsCatalog(
155
- connectionId: string,
156
- views: Array<{
157
- id: string;
158
- label: string;
159
- icon?: string;
160
- description?: string;
161
- }>,
162
- ): void {
101
+ sendViewsCatalog(connectionId, views) {
163
102
  this.sendControl(connectionId, { type: "views_catalog", views });
164
103
  }
165
-
166
- sendAudio(connectionId: string, audio: Buffer, sampleRate = 24000): void {
104
+ sendAudio(connectionId, audio, sampleRate = 24e3) {
167
105
  const conn = this.connections.get(connectionId);
168
106
  if (!conn || conn.ws.readyState !== conn.ws.OPEN) return;
169
- const header: XRTTSAudioHeader = {
107
+ const header = {
170
108
  type: "tts_audio",
171
109
  sampleRate,
172
110
  channels: 1,
173
- encoding: "mp3",
111
+ encoding: "mp3"
174
112
  };
175
113
  conn.ws.send(encodeBinaryFrame(header, audio), { binary: true });
176
114
  }
177
-
178
115
  // ── WebSocket connection lifecycle ──────────────────────────────────────
179
-
180
- private onConnect(runtime: IAgentRuntime, ws: WebSocket): void {
116
+ onConnect(runtime, ws) {
181
117
  const connId = crypto.randomUUID();
182
-
183
- ws.on("message", (data: unknown, isBinary: boolean) => {
118
+ ws.on("message", (data, isBinary) => {
184
119
  try {
185
120
  if (isBinary) {
186
- this.handleBinaryMessage(connId, data as Buffer);
121
+ this.handleBinaryMessage(connId, data);
187
122
  } else {
188
- const raw =
189
- typeof data === "string"
190
- ? data
191
- : Buffer.isBuffer(data)
192
- ? data.toString("utf8")
193
- : String(data);
123
+ const raw = typeof data === "string" ? data : Buffer.isBuffer(data) ? data.toString("utf8") : String(data);
194
124
  this.handleTextMessage(runtime, connId, ws, raw);
195
125
  }
196
126
  } catch (err) {
197
127
  console.error("[plugin-xr] message handler error:", err);
198
128
  }
199
129
  });
200
-
201
130
  ws.on("close", () => {
202
131
  this.audioPipeline.flush(connId);
203
132
  this.audioPipeline.clear(connId);
@@ -205,30 +134,23 @@ export class XRSessionService extends Service {
205
134
  this.connections.delete(connId);
206
135
  console.info(`[plugin-xr] device disconnected: ${connId}`);
207
136
  });
208
-
209
- ws.on("error", (err: Error) =>
210
- console.error(`[plugin-xr] ws error on ${connId}:`, err),
137
+ ws.on(
138
+ "error",
139
+ (err) => console.error(`[plugin-xr] ws error on ${connId}:`, err)
211
140
  );
212
141
  }
213
-
214
- private handleTextMessage(
215
- runtime: IAgentRuntime,
216
- connId: string,
217
- ws: WebSocket,
218
- raw: string,
219
- ): void {
220
- const msg = JSON.parse(raw) as XRClientControl;
221
-
142
+ handleTextMessage(runtime, connId, ws, raw) {
143
+ const msg = JSON.parse(raw);
222
144
  if (msg.type === "hello") {
223
- const entityId = crypto.randomUUID() as UUID;
224
- const roomId = crypto.randomUUID() as UUID;
225
- const conn: XRConnection = {
145
+ const entityId = crypto.randomUUID();
146
+ const roomId = crypto.randomUUID();
147
+ const conn = {
226
148
  id: connId,
227
149
  ws,
228
150
  deviceType: msg.deviceType,
229
151
  entityId,
230
152
  roomId,
231
- connectedAt: new Date(),
153
+ connectedAt: /* @__PURE__ */ new Date()
232
154
  };
233
155
  this.connections.set(connId, conn);
234
156
  ws.send(JSON.stringify({ type: "ready", sessionId: connId }));
@@ -236,78 +158,58 @@ export class XRSessionService extends Service {
236
158
  console.info(`[plugin-xr] ${msg.deviceType} connected: ${connId}`);
237
159
  return;
238
160
  }
239
-
240
161
  if (msg.type === "ping") {
241
162
  ws.send(JSON.stringify({ type: "pong" }));
242
163
  return;
243
164
  }
244
-
245
165
  if (msg.type === "view_ready") {
246
166
  console.info(`[plugin-xr] view ready on ${connId}: ${msg.viewId}`);
247
167
  return;
248
168
  }
249
-
250
169
  if (msg.type === "view_closed") {
251
170
  console.info(`[plugin-xr] view closed on ${connId}: ${msg.viewId}`);
252
171
  return;
253
172
  }
254
-
255
173
  if (msg.type === "view_event") {
256
174
  console.info(
257
175
  `[plugin-xr] view event on ${connId}:`,
258
176
  msg.viewId,
259
- msg.event,
177
+ msg.event
260
178
  );
261
179
  return;
262
180
  }
263
181
  }
264
-
265
- private handleBinaryMessage(connId: string, data: Buffer): void {
182
+ handleBinaryMessage(connId, data) {
266
183
  const conn = this.connections.get(connId);
267
184
  if (!conn) return;
268
-
269
185
  const { header, payload } = decodeBinaryFrame(data);
270
-
271
186
  if (header.type === "audio") {
272
187
  this.audioPipeline.push(connId, header, payload);
273
188
  return;
274
189
  }
275
-
276
190
  if (header.type === "frame") {
277
191
  this.visionPipeline.storeFrame(connId, header, payload);
278
192
  return;
279
193
  }
280
194
  }
281
-
282
195
  // ── Message routing ─────────────────────────────────────────────────────
283
-
284
- private async handleTranscript(
285
- connectionId: string,
286
- transcript: string,
287
- ): Promise<void> {
196
+ async handleTranscript(connectionId, transcript) {
288
197
  const conn = this.connections.get(connectionId);
289
198
  if (!conn) return;
290
199
  const runtime = this.runtime;
291
-
292
- // Echo transcript back so the UI can show it
293
200
  conn.ws.send(
294
- JSON.stringify({ type: "transcript", text: transcript, final: true }),
201
+ JSON.stringify({ type: "transcript", text: transcript, final: true })
295
202
  );
296
-
297
- // Attach latest camera frame as image attachment if available
298
203
  const latestFrame = this.visionPipeline.getLatestFrame(connectionId);
299
- const attachments: Content["attachments"] = latestFrame
300
- ? [
301
- {
302
- id: crypto.randomUUID(),
303
- url: `data:image/${latestFrame.header.format};base64,${latestFrame.data.toString("base64")}`,
304
- title: "XR camera frame",
305
- contentType: "image",
306
- source: "xr-camera",
307
- },
308
- ]
309
- : [];
310
-
204
+ const attachments = latestFrame ? [
205
+ {
206
+ id: crypto.randomUUID(),
207
+ url: `data:image/${latestFrame.header.format};base64,${latestFrame.data.toString("base64")}`,
208
+ title: "XR camera frame",
209
+ contentType: "image",
210
+ source: "xr-camera"
211
+ }
212
+ ] : [];
311
213
  const memory = createMessageMemory({
312
214
  entityId: conn.entityId,
313
215
  agentId: runtime.agentId,
@@ -315,69 +217,51 @@ export class XRSessionService extends Service {
315
217
  content: {
316
218
  text: transcript,
317
219
  source: `xr-${conn.deviceType}`,
318
- attachments,
319
- },
220
+ attachments
221
+ }
320
222
  });
321
-
322
223
  await runtime.createMemory(memory, "messages");
323
-
324
- const callback: HandlerCallback = async (
325
- response: Content,
326
- ): Promise<Memory[]> => {
224
+ const callback = async (response) => {
327
225
  const text = response.text?.trim() ?? "";
328
226
  if (text.length === 0) return [];
329
-
330
- // Send text response immediately
331
227
  conn.ws.send(JSON.stringify({ type: "agent_text", text }));
332
-
333
- // Generate TTS and send audio
334
228
  try {
335
229
  const audio = await runtime.useModel(ModelType.TEXT_TO_SPEECH, text);
336
- const audioBuf = Buffer.isBuffer(audio)
337
- ? audio
338
- : Buffer.from(audio as ArrayBuffer);
230
+ const audioBuf = Buffer.isBuffer(audio) ? audio : Buffer.from(audio);
339
231
  this.sendAudio(connectionId, audioBuf);
340
232
  } catch (err) {
341
233
  console.error("[plugin-xr] TTS error:", err);
342
234
  }
343
-
344
- // Persist agent response as memory
345
235
  const responseMemory = createMessageMemory({
346
236
  entityId: runtime.agentId,
347
237
  agentId: runtime.agentId,
348
238
  roomId: conn.roomId,
349
- content: { text, source: `xr-agent`, inReplyTo: memory.id },
239
+ content: { text, source: `xr-agent`, inReplyTo: memory.id }
350
240
  });
351
241
  await runtime.createMemory(responseMemory, "messages");
352
242
  return [responseMemory];
353
243
  };
354
-
355
244
  if (runtime.messageService) {
356
245
  await runtime.messageService.handleMessage(runtime, memory, callback);
357
246
  }
358
247
  }
359
-
360
248
  // ── Entity / room bootstrap ─────────────────────────────────────────────
361
-
362
- private async ensureEntities(
363
- runtime: IAgentRuntime,
364
- conn: XRConnection,
365
- ): Promise<void> {
249
+ async ensureEntities(runtime, conn) {
366
250
  try {
367
251
  await runtime.createEntity({
368
252
  id: conn.entityId,
369
253
  agentId: runtime.agentId,
370
254
  names: [`XR-${conn.deviceType}`],
371
- metadata: { source: `xr-${conn.deviceType}` },
255
+ metadata: { source: `xr-${conn.deviceType}` }
372
256
  });
373
257
  await runtime.createRoom({
374
258
  id: conn.roomId,
375
259
  name: `XR session (${conn.deviceType} ${conn.id.slice(0, 8)})`,
376
260
  source: "xr",
377
261
  type: ChannelType.GROUP,
378
- worldId: undefined,
379
- channelId: undefined,
380
- messageServerId: undefined,
262
+ worldId: void 0,
263
+ channelId: void 0,
264
+ messageServerId: void 0
381
265
  });
382
266
  await runtime.addParticipant(conn.entityId, conn.roomId);
383
267
  await runtime.addParticipant(runtime.agentId, conn.roomId);
@@ -386,3 +270,10 @@ export class XRSessionService extends Service {
386
270
  }
387
271
  }
388
272
  }
273
+ export {
274
+ XRSessionService,
275
+ XR_SERVICE_TYPE,
276
+ XR_WS_PORT_DEFAULT,
277
+ XR_WS_PORT_ENV
278
+ };
279
+ //# sourceMappingURL=xr-session-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/services/xr-session-service.ts"],"sourcesContent":["import type {\n Content,\n HandlerCallback,\n IAgentRuntime,\n Memory,\n UUID,\n} from \"@elizaos/core\";\nimport {\n ChannelType,\n createMessageMemory,\n ModelType,\n Service,\n} from \"@elizaos/core\";\nimport { type WebSocket, WebSocketServer } from \"ws\";\nimport {\n decodeBinaryFrame,\n encodeBinaryFrame,\n type XRClientControl,\n type XRDeviceType,\n type XRPanelConfig,\n type XRServerControl,\n type XRTTSAudioHeader,\n} from \"../protocol.js\";\nimport { AudioPipeline } from \"./audio-pipeline.js\";\nimport { VisionPipeline } from \"./vision-pipeline.js\";\n\nexport const XR_SERVICE_TYPE = \"xr-session\";\nexport const XR_WS_PORT_DEFAULT = 31338;\nexport const XR_WS_PORT_ENV = \"XR_WS_PORT\";\n\nexport interface XRConnection {\n id: string;\n ws: WebSocket;\n deviceType: XRDeviceType;\n entityId: UUID;\n roomId: UUID;\n connectedAt: Date;\n}\n\nexport class XRSessionService extends Service {\n static override serviceType = XR_SERVICE_TYPE;\n\n readonly capabilityDescription =\n \"Streams audio and camera from XR headsets (Quest 3, XReal) to the agent and returns voice responses.\";\n\n private wss!: WebSocketServer;\n private connections = new Map<string, XRConnection>();\n private audioPipeline!: AudioPipeline;\n private visionPipeline!: VisionPipeline;\n\n static override async start(runtime: IAgentRuntime): Promise<Service> {\n const svc = new XRSessionService(runtime);\n await svc.initialize(runtime);\n return svc;\n }\n\n private async initialize(runtime: IAgentRuntime): Promise<void> {\n this.visionPipeline = new VisionPipeline();\n this.audioPipeline = new AudioPipeline(\n runtime,\n (connectionId, transcript) =>\n this.handleTranscript(connectionId, transcript),\n );\n\n const port = Number(\n runtime.getSetting(XR_WS_PORT_ENV) ?? XR_WS_PORT_DEFAULT,\n );\n this.wss = new WebSocketServer({ port });\n\n this.wss.on(\"connection\", (ws: WebSocket) => this.onConnect(runtime, ws));\n this.wss.on(\"error\", (err: Error) =>\n console.error(\"[plugin-xr] WebSocket server error:\", err),\n );\n\n console.info(\n `[plugin-xr] WebSocket server listening on ws://localhost:${port}`,\n );\n }\n\n override async stop(): Promise<void> {\n for (const conn of this.connections.values()) {\n this.audioPipeline.clear(conn.id);\n this.visionPipeline.clear(conn.id);\n conn.ws.close();\n }\n this.connections.clear();\n await new Promise<void>((resolve) => this.wss.close(() => resolve()));\n }\n\n // ── Public accessors used by provider / action ──────────────────────────\n\n getConnections(): XRConnection[] {\n return [...this.connections.values()];\n }\n\n hasActiveConnections(): boolean {\n return this.connections.size > 0;\n }\n\n getVisionPipeline(): VisionPipeline {\n return this.visionPipeline;\n }\n\n sendText(connectionId: string, text: string): void {\n const conn = this.connections.get(connectionId);\n if (!conn || conn.ws.readyState !== conn.ws.OPEN) return;\n conn.ws.send(JSON.stringify({ type: \"agent_text\", text }));\n }\n\n sendControl(connectionId: string, msg: XRServerControl): void {\n const conn = this.connections.get(connectionId);\n if (!conn || conn.ws.readyState !== conn.ws.OPEN) return;\n conn.ws.send(JSON.stringify(msg));\n }\n\n broadcastControl(msg: XRServerControl): void {\n for (const conn of this.connections.values()) {\n if (conn.ws.readyState === conn.ws.OPEN) {\n conn.ws.send(JSON.stringify(msg));\n }\n }\n }\n\n openView(\n connectionId: string,\n viewId: string,\n agentBaseUrl: string,\n config?: XRPanelConfig,\n ): void {\n this.sendControl(connectionId, {\n type: \"view_open\",\n viewId,\n agentBaseUrl,\n config,\n });\n }\n\n closeView(connectionId: string, viewId: string): void {\n this.sendControl(connectionId, { type: \"view_close\", viewId });\n }\n\n switchView(connectionId: string, viewId: string): void {\n this.sendControl(connectionId, { type: \"view_switch\", viewId });\n }\n\n resizeView(\n connectionId: string,\n viewId: string,\n config: XRPanelConfig,\n ): void {\n this.sendControl(connectionId, { type: \"view_resize\", viewId, config });\n }\n\n sendViewsCatalog(\n connectionId: string,\n views: Array<{\n id: string;\n label: string;\n icon?: string;\n description?: string;\n }>,\n ): void {\n this.sendControl(connectionId, { type: \"views_catalog\", views });\n }\n\n sendAudio(connectionId: string, audio: Buffer, sampleRate = 24000): void {\n const conn = this.connections.get(connectionId);\n if (!conn || conn.ws.readyState !== conn.ws.OPEN) return;\n const header: XRTTSAudioHeader = {\n type: \"tts_audio\",\n sampleRate,\n channels: 1,\n encoding: \"mp3\",\n };\n conn.ws.send(encodeBinaryFrame(header, audio), { binary: true });\n }\n\n // ── WebSocket connection lifecycle ──────────────────────────────────────\n\n private onConnect(runtime: IAgentRuntime, ws: WebSocket): void {\n const connId = crypto.randomUUID();\n\n ws.on(\"message\", (data: unknown, isBinary: boolean) => {\n try {\n if (isBinary) {\n this.handleBinaryMessage(connId, data as Buffer);\n } else {\n const raw =\n typeof data === \"string\"\n ? data\n : Buffer.isBuffer(data)\n ? data.toString(\"utf8\")\n : String(data);\n this.handleTextMessage(runtime, connId, ws, raw);\n }\n } catch (err) {\n console.error(\"[plugin-xr] message handler error:\", err);\n }\n });\n\n ws.on(\"close\", () => {\n this.audioPipeline.flush(connId);\n this.audioPipeline.clear(connId);\n this.visionPipeline.clear(connId);\n this.connections.delete(connId);\n console.info(`[plugin-xr] device disconnected: ${connId}`);\n });\n\n ws.on(\"error\", (err: Error) =>\n console.error(`[plugin-xr] ws error on ${connId}:`, err),\n );\n }\n\n private handleTextMessage(\n runtime: IAgentRuntime,\n connId: string,\n ws: WebSocket,\n raw: string,\n ): void {\n const msg = JSON.parse(raw) as XRClientControl;\n\n if (msg.type === \"hello\") {\n const entityId = crypto.randomUUID() as UUID;\n const roomId = crypto.randomUUID() as UUID;\n const conn: XRConnection = {\n id: connId,\n ws,\n deviceType: msg.deviceType,\n entityId,\n roomId,\n connectedAt: new Date(),\n };\n this.connections.set(connId, conn);\n ws.send(JSON.stringify({ type: \"ready\", sessionId: connId }));\n void this.ensureEntities(runtime, conn);\n console.info(`[plugin-xr] ${msg.deviceType} connected: ${connId}`);\n return;\n }\n\n if (msg.type === \"ping\") {\n ws.send(JSON.stringify({ type: \"pong\" }));\n return;\n }\n\n if (msg.type === \"view_ready\") {\n console.info(`[plugin-xr] view ready on ${connId}: ${msg.viewId}`);\n return;\n }\n\n if (msg.type === \"view_closed\") {\n console.info(`[plugin-xr] view closed on ${connId}: ${msg.viewId}`);\n return;\n }\n\n if (msg.type === \"view_event\") {\n console.info(\n `[plugin-xr] view event on ${connId}:`,\n msg.viewId,\n msg.event,\n );\n return;\n }\n }\n\n private handleBinaryMessage(connId: string, data: Buffer): void {\n const conn = this.connections.get(connId);\n if (!conn) return;\n\n const { header, payload } = decodeBinaryFrame(data);\n\n if (header.type === \"audio\") {\n this.audioPipeline.push(connId, header, payload);\n return;\n }\n\n if (header.type === \"frame\") {\n this.visionPipeline.storeFrame(connId, header, payload);\n return;\n }\n }\n\n // ── Message routing ─────────────────────────────────────────────────────\n\n private async handleTranscript(\n connectionId: string,\n transcript: string,\n ): Promise<void> {\n const conn = this.connections.get(connectionId);\n if (!conn) return;\n const runtime = this.runtime;\n\n // Echo transcript back so the UI can show it\n conn.ws.send(\n JSON.stringify({ type: \"transcript\", text: transcript, final: true }),\n );\n\n // Attach latest camera frame as image attachment if available\n const latestFrame = this.visionPipeline.getLatestFrame(connectionId);\n const attachments: Content[\"attachments\"] = latestFrame\n ? [\n {\n id: crypto.randomUUID(),\n url: `data:image/${latestFrame.header.format};base64,${latestFrame.data.toString(\"base64\")}`,\n title: \"XR camera frame\",\n contentType: \"image\",\n source: \"xr-camera\",\n },\n ]\n : [];\n\n const memory = createMessageMemory({\n entityId: conn.entityId,\n agentId: runtime.agentId,\n roomId: conn.roomId,\n content: {\n text: transcript,\n source: `xr-${conn.deviceType}`,\n attachments,\n },\n });\n\n await runtime.createMemory(memory, \"messages\");\n\n const callback: HandlerCallback = async (\n response: Content,\n ): Promise<Memory[]> => {\n const text = response.text?.trim() ?? \"\";\n if (text.length === 0) return [];\n\n // Send text response immediately\n conn.ws.send(JSON.stringify({ type: \"agent_text\", text }));\n\n // Generate TTS and send audio\n try {\n const audio = await runtime.useModel(ModelType.TEXT_TO_SPEECH, text);\n const audioBuf = Buffer.isBuffer(audio)\n ? audio\n : Buffer.from(audio as ArrayBuffer);\n this.sendAudio(connectionId, audioBuf);\n } catch (err) {\n console.error(\"[plugin-xr] TTS error:\", err);\n }\n\n // Persist agent response as memory\n const responseMemory = createMessageMemory({\n entityId: runtime.agentId,\n agentId: runtime.agentId,\n roomId: conn.roomId,\n content: { text, source: `xr-agent`, inReplyTo: memory.id },\n });\n await runtime.createMemory(responseMemory, \"messages\");\n return [responseMemory];\n };\n\n if (runtime.messageService) {\n await runtime.messageService.handleMessage(runtime, memory, callback);\n }\n }\n\n // ── Entity / room bootstrap ─────────────────────────────────────────────\n\n private async ensureEntities(\n runtime: IAgentRuntime,\n conn: XRConnection,\n ): Promise<void> {\n try {\n await runtime.createEntity({\n id: conn.entityId,\n agentId: runtime.agentId,\n names: [`XR-${conn.deviceType}`],\n metadata: { source: `xr-${conn.deviceType}` },\n });\n await runtime.createRoom({\n id: conn.roomId,\n name: `XR session (${conn.deviceType} ${conn.id.slice(0, 8)})`,\n source: \"xr\",\n type: ChannelType.GROUP,\n worldId: undefined,\n channelId: undefined,\n messageServerId: undefined,\n });\n await runtime.addParticipant(conn.entityId, conn.roomId);\n await runtime.addParticipant(runtime.agentId, conn.roomId);\n } catch (err) {\n console.error(\"[plugin-xr] entity setup error:\", err);\n }\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-xr",
3
- "version": "2.0.3-beta.6",
3
+ "version": "2.0.3-beta.7",
4
4
  "type": "module",
5
5
  "description": "WebXR audio/video streaming for elizaOS — Quest 3 and XReal glasses",
6
6
  "main": "./dist/index.js",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
7
11
  "exports": {
8
12
  "./package.json": "./package.json",
9
13
  ".": {
@@ -22,6 +26,7 @@
22
26
  "lint": "bunx @biomejs/biome check src",
23
27
  "test": "bunx vitest run --config ./vitest.config.ts",
24
28
  "build": "bun run build:js && bun run build:types",
29
+ "prepack": "bun run build",
25
30
  "build:all": "bun run build && bun run simulator:build",
26
31
  "clean": "node ../../packages/scripts/rm-path-recursive.mjs dist simulator/dist",
27
32
  "build:js": "tsup --config ../tsup.plugin-packages.shared.ts",
@@ -30,8 +35,8 @@
30
35
  "simulator:watch": "cd simulator && bun run build:watch"
31
36
  },
32
37
  "dependencies": {
33
- "@elizaos/agent": "2.0.3-beta.6",
34
- "@elizaos/core": "2.0.3-beta.6",
38
+ "@elizaos/agent": "2.0.3-beta.7",
39
+ "@elizaos/core": "2.0.3-beta.7",
35
40
  "ws": "^8.18.0",
36
41
  "zod": "^4.4.3"
37
42
  },
@@ -53,5 +58,5 @@
53
58
  "publishConfig": {
54
59
  "access": "public"
55
60
  },
56
- "gitHead": "990dc996172b3e0fb525a75052a5ac28a4cd4de5"
61
+ "gitHead": "61094f10458d11055c75b3dd0bae374e3f66bac5"
57
62
  }