@elizaos/plugin-screenshare 2.0.3-beta.5 → 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 (47) hide show
  1. package/dist/components/ScreenshareSpatialView.d.ts +61 -0
  2. package/dist/components/ScreenshareSpatialView.d.ts.map +1 -0
  3. package/dist/components/ScreenshareSpatialView.js +206 -0
  4. package/dist/components/ScreenshareSpatialView.js.map +1 -0
  5. package/dist/components/ScreenshareView.d.ts +13 -0
  6. package/dist/components/ScreenshareView.d.ts.map +1 -0
  7. package/dist/components/ScreenshareView.js +263 -0
  8. package/dist/components/ScreenshareView.js.map +1 -0
  9. package/dist/index.d.ts +9 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +58 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/register-terminal-view.d.ts +15 -0
  14. package/dist/register-terminal-view.d.ts.map +1 -0
  15. package/dist/register-terminal-view.js +27 -0
  16. package/dist/register-terminal-view.js.map +1 -0
  17. package/dist/routes.d.ts +8 -0
  18. package/dist/routes.d.ts.map +1 -0
  19. package/dist/routes.js +639 -0
  20. package/dist/routes.js.map +1 -0
  21. package/dist/session-store.d.ts +44 -0
  22. package/dist/session-store.d.ts.map +1 -0
  23. package/dist/session-store.js +200 -0
  24. package/dist/session-store.js.map +1 -0
  25. package/dist/ui/ScreenshareOperatorSurface.d.ts +5 -0
  26. package/dist/ui/ScreenshareOperatorSurface.d.ts.map +1 -0
  27. package/dist/ui/ScreenshareOperatorSurface.helpers.d.ts +40 -0
  28. package/dist/ui/ScreenshareOperatorSurface.helpers.d.ts.map +1 -0
  29. package/dist/ui/ScreenshareOperatorSurface.helpers.js +47 -0
  30. package/dist/ui/ScreenshareOperatorSurface.helpers.js.map +1 -0
  31. package/dist/ui/ScreenshareOperatorSurface.interact.d.ts +2 -0
  32. package/dist/ui/ScreenshareOperatorSurface.interact.d.ts.map +1 -0
  33. package/dist/ui/ScreenshareOperatorSurface.interact.js +100 -0
  34. package/dist/ui/ScreenshareOperatorSurface.interact.js.map +1 -0
  35. package/dist/ui/ScreenshareOperatorSurface.js +746 -0
  36. package/dist/ui/ScreenshareOperatorSurface.js.map +1 -0
  37. package/dist/ui/index.d.ts +3 -0
  38. package/dist/ui/index.d.ts.map +1 -0
  39. package/dist/ui/index.js +10 -0
  40. package/dist/ui/index.js.map +1 -0
  41. package/dist/ui/screenshare-view-bundle.d.ts +3 -0
  42. package/dist/ui/screenshare-view-bundle.d.ts.map +1 -0
  43. package/dist/ui/screenshare-view-bundle.js +7 -0
  44. package/dist/ui/screenshare-view-bundle.js.map +1 -0
  45. package/dist/views/bundle.js +507 -0
  46. package/dist/views/bundle.js.map +1 -0
  47. package/package.json +8 -8
@@ -0,0 +1,746 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ Button,
4
+ client,
5
+ Input,
6
+ SurfaceEmptyState,
7
+ SurfaceSection,
8
+ selectLatestRunForApp,
9
+ useAppSelector
10
+ } from "@elizaos/ui";
11
+ import { useAgentElement } from "@elizaos/ui/agent-surface";
12
+ import {
13
+ CheckCircle2,
14
+ Copy,
15
+ ExternalLink,
16
+ MonitorUp,
17
+ PlugZap,
18
+ Power,
19
+ RefreshCw,
20
+ XCircle
21
+ } from "lucide-react";
22
+ import { useCallback, useEffect, useMemo, useState } from "react";
23
+ import {
24
+ buildViewerUrl,
25
+ fetchJson,
26
+ loadScreenshareTuiState
27
+ } from "./ScreenshareOperatorSurface.helpers";
28
+ const APP_NAME = "@elizaos/plugin-screenshare";
29
+ function parseViewerSession(viewerUrl) {
30
+ if (!viewerUrl) {
31
+ return null;
32
+ }
33
+ try {
34
+ const url = new URL(viewerUrl, window.location.origin);
35
+ const sessionId = url.searchParams.get("sessionId")?.trim();
36
+ const token = url.searchParams.get("token")?.trim();
37
+ return sessionId && token ? { sessionId, token } : null;
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+ function formatTime(value) {
43
+ if (!value) {
44
+ return "Not yet";
45
+ }
46
+ const date = new Date(value);
47
+ return Number.isNaN(date.getTime()) ? "Not yet" : date.toLocaleTimeString();
48
+ }
49
+ function ScreenshareMetric({
50
+ icon: Icon,
51
+ label,
52
+ value,
53
+ active
54
+ }) {
55
+ return /* @__PURE__ */ jsxs(
56
+ "div",
57
+ {
58
+ className: "flex min-h-16 flex-col items-center justify-center gap-1.5 px-3 py-2",
59
+ title: label,
60
+ role: "status",
61
+ "aria-label": `${label}: ${value}`,
62
+ children: [
63
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
64
+ /* @__PURE__ */ jsx(
65
+ "span",
66
+ {
67
+ className: `h-1.5 w-1.5 shrink-0 rounded-full ${active ? "bg-accent" : "bg-muted/40"}`,
68
+ "aria-hidden": true
69
+ }
70
+ ),
71
+ /* @__PURE__ */ jsx(
72
+ Icon,
73
+ {
74
+ className: `h-3.5 w-3.5 ${active ? "text-accent" : "text-muted"}`
75
+ }
76
+ )
77
+ ] }),
78
+ /* @__PURE__ */ jsx(
79
+ "span",
80
+ {
81
+ className: `truncate text-sm font-semibold ${active ? "text-txt" : "text-muted-strong"}`,
82
+ children: value
83
+ }
84
+ )
85
+ ]
86
+ }
87
+ );
88
+ }
89
+ function ScreenshareActionButton({
90
+ agentId,
91
+ label,
92
+ group,
93
+ description,
94
+ status,
95
+ ...buttonProps
96
+ }) {
97
+ const { ref, agentProps } = useAgentElement({
98
+ id: agentId,
99
+ role: "button",
100
+ label,
101
+ group,
102
+ description,
103
+ ...status ? { status } : {}
104
+ });
105
+ return /* @__PURE__ */ jsx(Button, { ref, "aria-label": label, ...agentProps, ...buttonProps });
106
+ }
107
+ function ScreenshareField({
108
+ agentId,
109
+ label,
110
+ group,
111
+ description,
112
+ role = "text-input",
113
+ ...inputProps
114
+ }) {
115
+ const { ref, agentProps } = useAgentElement({
116
+ id: agentId,
117
+ role,
118
+ label,
119
+ group,
120
+ description,
121
+ fillable: !inputProps.readOnly
122
+ });
123
+ return /* @__PURE__ */ jsx(Input, { ref, "aria-label": label, ...agentProps, ...inputProps });
124
+ }
125
+ function ScreenshareOperatorSurface({
126
+ appName,
127
+ focus = "all"
128
+ }) {
129
+ const appRuns = useAppSelector((s) => s.appRuns);
130
+ const setActionNotice = useAppSelector((s) => s.setActionNotice);
131
+ const { run } = useMemo(
132
+ () => selectLatestRunForApp(appName || APP_NAME, appRuns),
133
+ [appName, appRuns]
134
+ );
135
+ const launchedSession = useMemo(
136
+ () => parseViewerSession(run?.viewer?.url),
137
+ [run?.viewer?.url]
138
+ );
139
+ const [capabilities, setCapabilities] = useState(
140
+ null
141
+ );
142
+ const [hostSession, setHostSession] = useState(null);
143
+ const [hostToken, setHostToken] = useState(
144
+ launchedSession?.token ?? ""
145
+ );
146
+ const [remoteBase, setRemoteBase] = useState("");
147
+ const [remoteSessionId, setRemoteSessionId] = useState("");
148
+ const [remoteToken, setRemoteToken] = useState("");
149
+ const [busy, setBusy] = useState(null);
150
+ const loadCapabilities = useCallback(async () => {
151
+ const next = await fetchJson(
152
+ "/api/apps/screenshare/capabilities"
153
+ );
154
+ setCapabilities(next);
155
+ }, []);
156
+ const loadLaunchedSession = useCallback(async () => {
157
+ if (!launchedSession) {
158
+ return;
159
+ }
160
+ setHostToken(launchedSession.token);
161
+ const next = await fetchJson(
162
+ `/api/apps/screenshare/session/${encodeURIComponent(
163
+ launchedSession.sessionId
164
+ )}?token=${encodeURIComponent(launchedSession.token)}`
165
+ );
166
+ setHostSession(next.session);
167
+ }, [launchedSession]);
168
+ useEffect(() => {
169
+ void loadCapabilities().catch((error) => {
170
+ setActionNotice(
171
+ error instanceof Error ? error.message : "Failed to load capabilities.",
172
+ "error",
173
+ 3200
174
+ );
175
+ });
176
+ }, [loadCapabilities, setActionNotice]);
177
+ useEffect(() => {
178
+ void loadLaunchedSession().catch((error) => {
179
+ setActionNotice(
180
+ error instanceof Error ? error.message : "Failed to load screen share session.",
181
+ "error",
182
+ 3200
183
+ );
184
+ });
185
+ }, [loadLaunchedSession, setActionNotice]);
186
+ const startHostSession = useCallback(async () => {
187
+ setBusy("start");
188
+ try {
189
+ const response = await fetchJson(
190
+ "/api/apps/screenshare/session",
191
+ {
192
+ method: "POST",
193
+ body: JSON.stringify({ label: "This machine" })
194
+ }
195
+ );
196
+ setHostSession(response.session);
197
+ setHostToken(response.token);
198
+ setActionNotice("Screen share session started.", "success", 2400);
199
+ } catch (error) {
200
+ setActionNotice(
201
+ error instanceof Error ? error.message : "Failed to start session.",
202
+ "error",
203
+ 3600
204
+ );
205
+ } finally {
206
+ setBusy(null);
207
+ }
208
+ }, [setActionNotice]);
209
+ const stopHostSession = useCallback(async () => {
210
+ if (!hostSession || !hostToken) {
211
+ return;
212
+ }
213
+ setBusy("stop");
214
+ try {
215
+ const response = await fetchJson(
216
+ `/api/apps/screenshare/session/${encodeURIComponent(hostSession.id)}/stop`,
217
+ {
218
+ method: "POST",
219
+ body: JSON.stringify({ token: hostToken }),
220
+ headers: { "X-Screenshare-Token": hostToken }
221
+ }
222
+ );
223
+ setHostSession(response.session);
224
+ setActionNotice("Screen share session stopped.", "success", 2400);
225
+ } catch (error) {
226
+ setActionNotice(
227
+ error instanceof Error ? error.message : "Failed to stop session.",
228
+ "error",
229
+ 3600
230
+ );
231
+ } finally {
232
+ setBusy(null);
233
+ }
234
+ }, [hostSession, hostToken, setActionNotice]);
235
+ const copyHostDetails = useCallback(async () => {
236
+ if (!hostSession || !hostToken) {
237
+ return;
238
+ }
239
+ const url = buildViewerUrl({
240
+ sessionId: hostSession.id,
241
+ token: hostToken
242
+ });
243
+ try {
244
+ await navigator.clipboard.writeText(
245
+ JSON.stringify(
246
+ {
247
+ serverUrl: client.getBaseUrl() || window.location.origin,
248
+ sessionId: hostSession.id,
249
+ token: hostToken,
250
+ viewerUrl: url
251
+ },
252
+ null,
253
+ 2
254
+ )
255
+ );
256
+ setActionNotice("Screen share details copied.", "success", 1800);
257
+ } catch (error) {
258
+ setActionNotice(
259
+ error instanceof Error ? error.message : "Clipboard write failed.",
260
+ "error",
261
+ 3200
262
+ );
263
+ }
264
+ }, [hostSession, hostToken, setActionNotice]);
265
+ const openViewer = useCallback((url) => {
266
+ window.open(url, "_blank", "noopener,noreferrer");
267
+ }, []);
268
+ const hostViewerUrl = hostSession && hostToken ? buildViewerUrl({ sessionId: hostSession.id, token: hostToken }) : null;
269
+ const remoteViewerUrl = remoteSessionId.trim() && remoteToken.trim() ? buildViewerUrl({
270
+ baseUrl: remoteBase,
271
+ sessionId: remoteSessionId.trim(),
272
+ token: remoteToken.trim()
273
+ }) : null;
274
+ if (focus === "chat") {
275
+ return /* @__PURE__ */ jsx(SurfaceEmptyState, { title: "Screen Share", body: "" });
276
+ }
277
+ return /* @__PURE__ */ jsxs("section", { className: "flex min-h-0 flex-col gap-3 p-3", children: [
278
+ /* @__PURE__ */ jsxs(SurfaceSection, { title: "Host", children: [
279
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
280
+ /* @__PURE__ */ jsx(
281
+ ScreenshareMetric,
282
+ {
283
+ icon: MonitorUp,
284
+ label: "Session",
285
+ value: hostSession?.status ?? "idle",
286
+ active: hostSession?.status === "active"
287
+ }
288
+ ),
289
+ /* @__PURE__ */ jsx(
290
+ ScreenshareMetric,
291
+ {
292
+ icon: PlugZap,
293
+ label: "Platform",
294
+ value: capabilities?.platform ?? hostSession?.platform ?? "desktop",
295
+ active: Boolean(capabilities?.platform || hostSession?.platform)
296
+ }
297
+ ),
298
+ /* @__PURE__ */ jsx(
299
+ ScreenshareMetric,
300
+ {
301
+ icon: capabilities?.capabilities.headfulGui?.available ? CheckCircle2 : XCircle,
302
+ label: "GUI",
303
+ value: "GUI",
304
+ active: capabilities?.capabilities.headfulGui?.available
305
+ }
306
+ )
307
+ ] }),
308
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-col gap-2", children: [
309
+ /* @__PURE__ */ jsxs(
310
+ ScreenshareActionButton,
311
+ {
312
+ agentId: "action-start-host",
313
+ label: hostSession?.status === "active" ? "Rotate host session" : "Start host session",
314
+ group: "host",
315
+ description: "Start or rotate the screen share session for this machine",
316
+ type: "button",
317
+ size: "sm",
318
+ variant: "default",
319
+ className: "h-10 w-full justify-center gap-2",
320
+ onClick: () => void startHostSession(),
321
+ disabled: busy === "start",
322
+ children: [
323
+ /* @__PURE__ */ jsx(MonitorUp, { className: "h-4 w-4" }),
324
+ hostSession?.status === "active" ? "Rotate session" : "Start session"
325
+ ]
326
+ }
327
+ ),
328
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
329
+ /* @__PURE__ */ jsxs(
330
+ ScreenshareActionButton,
331
+ {
332
+ agentId: "action-open-host-viewer",
333
+ label: "Open host viewer",
334
+ group: "host",
335
+ description: "Open the viewer for the host screen share session",
336
+ type: "button",
337
+ size: "sm",
338
+ variant: "outline",
339
+ className: "h-9 justify-center gap-1.5",
340
+ onClick: () => hostViewerUrl && openViewer(hostViewerUrl),
341
+ disabled: !hostViewerUrl,
342
+ children: [
343
+ /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" }),
344
+ "Open"
345
+ ]
346
+ }
347
+ ),
348
+ /* @__PURE__ */ jsxs(
349
+ ScreenshareActionButton,
350
+ {
351
+ agentId: "action-copy-host-details",
352
+ label: "Copy host details",
353
+ group: "host",
354
+ description: "Copy the host session connection details to the clipboard",
355
+ type: "button",
356
+ size: "sm",
357
+ variant: "outline",
358
+ className: "h-9 justify-center gap-1.5",
359
+ onClick: () => void copyHostDetails(),
360
+ disabled: !hostSession || !hostToken,
361
+ children: [
362
+ /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" }),
363
+ "Copy"
364
+ ]
365
+ }
366
+ ),
367
+ /* @__PURE__ */ jsxs(
368
+ ScreenshareActionButton,
369
+ {
370
+ agentId: "action-stop-host",
371
+ label: "Stop host session",
372
+ group: "host",
373
+ description: "Stop the active host screen share session",
374
+ type: "button",
375
+ size: "sm",
376
+ variant: "outline",
377
+ className: "h-9 justify-center gap-1.5",
378
+ onClick: () => void stopHostSession(),
379
+ disabled: hostSession?.status !== "active",
380
+ children: [
381
+ /* @__PURE__ */ jsx(Power, { className: "h-4 w-4" }),
382
+ "Stop"
383
+ ]
384
+ }
385
+ )
386
+ ] })
387
+ ] }),
388
+ hostSession ? /* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-2 gap-2", children: [
389
+ /* @__PURE__ */ jsx(
390
+ ScreenshareMetric,
391
+ {
392
+ icon: MonitorUp,
393
+ label: "Frames",
394
+ value: hostSession.frameCount,
395
+ active: hostSession.frameCount > 0
396
+ }
397
+ ),
398
+ /* @__PURE__ */ jsx(
399
+ ScreenshareMetric,
400
+ {
401
+ icon: PlugZap,
402
+ label: "Inputs",
403
+ value: hostSession.inputCount,
404
+ active: hostSession.inputCount > 0
405
+ }
406
+ ),
407
+ /* @__PURE__ */ jsx(
408
+ ScreenshareMetric,
409
+ {
410
+ icon: RefreshCw,
411
+ label: "Last frame",
412
+ value: formatTime(hostSession.lastFrameAt),
413
+ active: hostSession.lastFrameAt !== null
414
+ }
415
+ ),
416
+ /* @__PURE__ */ jsx(
417
+ ScreenshareMetric,
418
+ {
419
+ icon: Power,
420
+ label: "Last input",
421
+ value: formatTime(hostSession.lastInputAt),
422
+ active: hostSession.lastInputAt !== null
423
+ }
424
+ )
425
+ ] }) : null
426
+ ] }),
427
+ /* @__PURE__ */ jsxs(SurfaceSection, { title: "Connect", children: [
428
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
429
+ /* @__PURE__ */ jsx(
430
+ ScreenshareField,
431
+ {
432
+ agentId: "input-remote-base",
433
+ label: "Remote server URL",
434
+ group: "connect",
435
+ description: "Server URL of the remote machine to connect to",
436
+ value: remoteBase,
437
+ onChange: (event) => setRemoteBase(event.target.value),
438
+ placeholder: "Server URL",
439
+ className: "h-9 border-0 bg-transparent text-xs"
440
+ }
441
+ ),
442
+ /* @__PURE__ */ jsx(
443
+ ScreenshareField,
444
+ {
445
+ agentId: "input-remote-session",
446
+ label: "Remote session id",
447
+ group: "connect",
448
+ description: "Session id of the remote screen share to connect to",
449
+ value: remoteSessionId,
450
+ onChange: (event) => setRemoteSessionId(event.target.value),
451
+ placeholder: "Session",
452
+ className: "h-9 border-0 bg-transparent text-xs"
453
+ }
454
+ ),
455
+ /* @__PURE__ */ jsx(
456
+ ScreenshareField,
457
+ {
458
+ agentId: "input-remote-token",
459
+ label: "Remote session token",
460
+ group: "connect",
461
+ description: "Token of the remote screen share to connect to",
462
+ value: remoteToken,
463
+ onChange: (event) => setRemoteToken(event.target.value),
464
+ placeholder: "Token",
465
+ className: "h-9 border-0 bg-transparent text-xs"
466
+ }
467
+ )
468
+ ] }),
469
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex gap-2", children: [
470
+ /* @__PURE__ */ jsxs(
471
+ ScreenshareActionButton,
472
+ {
473
+ agentId: "action-connect-remote",
474
+ label: "Connect to remote",
475
+ group: "connect",
476
+ description: "Open the viewer for the entered remote screen share",
477
+ type: "button",
478
+ size: "sm",
479
+ variant: remoteViewerUrl ? "default" : "outline",
480
+ className: "h-10 flex-1 justify-center gap-2",
481
+ onClick: () => remoteViewerUrl && openViewer(remoteViewerUrl),
482
+ disabled: !remoteViewerUrl,
483
+ children: [
484
+ /* @__PURE__ */ jsx(PlugZap, { className: "h-4 w-4" }),
485
+ "Connect"
486
+ ]
487
+ }
488
+ ),
489
+ /* @__PURE__ */ jsx(
490
+ ScreenshareActionButton,
491
+ {
492
+ agentId: "action-refresh-capabilities",
493
+ label: "Refresh capabilities",
494
+ group: "connect",
495
+ description: "Reload the host screen share capabilities",
496
+ type: "button",
497
+ size: "sm",
498
+ variant: "outline",
499
+ className: "h-10 w-10 justify-center gap-2 px-0",
500
+ onClick: () => void loadCapabilities(),
501
+ title: "Refresh capabilities",
502
+ children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" })
503
+ }
504
+ )
505
+ ] })
506
+ ] }),
507
+ capabilities ? /* @__PURE__ */ jsx(SurfaceSection, { title: "Capabilities", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2", children: Object.entries(capabilities.capabilities).map(
508
+ ([name, capability]) => /* @__PURE__ */ jsxs(
509
+ "div",
510
+ {
511
+ className: "flex min-h-14 items-center justify-center gap-2 px-3 py-2",
512
+ title: `${name}: ${capability.tool}`,
513
+ children: [
514
+ capability.available ? /* @__PURE__ */ jsx(CheckCircle2, { className: "h-4 w-4 text-accent" }) : /* @__PURE__ */ jsx(XCircle, { className: "h-4 w-4 text-muted" }),
515
+ /* @__PURE__ */ jsx(
516
+ "span",
517
+ {
518
+ className: capability.available ? "truncate text-xs font-semibold text-txt" : "truncate text-xs font-semibold text-muted-strong",
519
+ children: name
520
+ }
521
+ )
522
+ ]
523
+ },
524
+ name
525
+ )
526
+ ) }) }) : null
527
+ ] });
528
+ }
529
+ function ScreenshareTuiView() {
530
+ const [state, setState] = useState(null);
531
+ const [loading, setLoading] = useState(true);
532
+ const [lastAction, setLastAction] = useState("boot");
533
+ const [error, setError] = useState(null);
534
+ const refreshElement = useAgentElement({
535
+ id: "tui-refresh-sessions",
536
+ role: "button",
537
+ label: "Refresh sessions",
538
+ group: "tui-sessions",
539
+ description: "Reload the screen share sessions and capabilities",
540
+ status: loading ? "loading" : "idle"
541
+ });
542
+ const refresh = useCallback(async () => {
543
+ setLoading(true);
544
+ setError(null);
545
+ try {
546
+ const next = await loadScreenshareTuiState();
547
+ setState(next);
548
+ setLastAction("refresh");
549
+ } catch (caught) {
550
+ setState(null);
551
+ setError(
552
+ caught instanceof Error ? caught.message : "Screen share refresh failed"
553
+ );
554
+ } finally {
555
+ setLoading(false);
556
+ }
557
+ }, []);
558
+ useEffect(() => {
559
+ void refresh();
560
+ }, [refresh]);
561
+ const activeSessions = state?.sessions.sessions.filter((session) => session.status === "active") ?? [];
562
+ const viewState = {
563
+ viewType: "tui",
564
+ viewId: "screenshare",
565
+ platform: state?.capabilities.platform ?? null,
566
+ sessionCount: state?.sessions.sessions.length ?? 0,
567
+ activeSessionCount: activeSessions.length,
568
+ capabilities: state ? Object.fromEntries(
569
+ Object.entries(state.capabilities.capabilities).map(
570
+ ([name, capability]) => [name, capability.available]
571
+ )
572
+ ) : {},
573
+ loading,
574
+ lastAction,
575
+ error
576
+ };
577
+ return /* @__PURE__ */ jsxs(
578
+ "div",
579
+ {
580
+ "data-view-state": JSON.stringify(viewState),
581
+ style: {
582
+ minHeight: "100vh",
583
+ background: "#020617",
584
+ color: "#cbd5e1",
585
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace',
586
+ padding: 20
587
+ },
588
+ children: [
589
+ /* @__PURE__ */ jsxs(
590
+ "div",
591
+ {
592
+ "data-status": loading ? "loading" : "ready",
593
+ style: { color: "#94a3b8", marginBottom: 16 },
594
+ children: [
595
+ loading ? "loading" : state?.capabilities.platform ?? "unknown",
596
+ " |",
597
+ " ",
598
+ activeSessions.length,
599
+ " active sessions | ",
600
+ lastAction
601
+ ]
602
+ }
603
+ ),
604
+ /* @__PURE__ */ jsxs(
605
+ "div",
606
+ {
607
+ style: {
608
+ display: "grid",
609
+ gridTemplateColumns: "1fr",
610
+ gap: 16
611
+ },
612
+ children: [
613
+ /* @__PURE__ */ jsxs(
614
+ "section",
615
+ {
616
+ "aria-label": "Screen share sessions",
617
+ style: {
618
+ padding: "8px 0"
619
+ },
620
+ children: [
621
+ /* @__PURE__ */ jsxs(
622
+ "div",
623
+ {
624
+ style: {
625
+ display: "flex",
626
+ alignItems: "center",
627
+ justifyContent: "space-between",
628
+ marginBottom: 10
629
+ },
630
+ children: [
631
+ /* @__PURE__ */ jsx("strong", { style: { color: "#e2e8f0" }, children: "sessions" }),
632
+ /* @__PURE__ */ jsx(
633
+ "button",
634
+ {
635
+ ref: refreshElement.ref,
636
+ type: "button",
637
+ "aria-label": "Refresh sessions",
638
+ onClick: () => void refresh(),
639
+ disabled: loading,
640
+ style: {
641
+ background: "transparent",
642
+ color: "#a7f3d0",
643
+ border: 0,
644
+ padding: "4px 8px",
645
+ cursor: loading ? "not-allowed" : "pointer",
646
+ fontFamily: "inherit"
647
+ },
648
+ ...refreshElement.agentProps,
649
+ children: "refresh"
650
+ }
651
+ )
652
+ ]
653
+ }
654
+ ),
655
+ error && /* @__PURE__ */ jsx("div", { style: { color: "#fca5a5" }, children: error }),
656
+ (state?.sessions.sessions ?? []).map((session) => /* @__PURE__ */ jsxs(
657
+ "div",
658
+ {
659
+ style: {
660
+ padding: "8px 0"
661
+ },
662
+ children: [
663
+ /* @__PURE__ */ jsxs("div", { style: { color: "#e2e8f0" }, children: [
664
+ session.id,
665
+ " / ",
666
+ session.status
667
+ ] }),
668
+ /* @__PURE__ */ jsxs("div", { style: { color: "#94a3b8" }, children: [
669
+ session.label,
670
+ " frames ",
671
+ session.frameCount,
672
+ " inputs",
673
+ " ",
674
+ session.inputCount
675
+ ] }),
676
+ /* @__PURE__ */ jsxs("div", { style: { color: "#64748b" }, children: [
677
+ "last frame ",
678
+ formatTime(session.lastFrameAt),
679
+ " / last input",
680
+ " ",
681
+ formatTime(session.lastInputAt)
682
+ ] })
683
+ ]
684
+ },
685
+ session.id
686
+ ))
687
+ ]
688
+ }
689
+ ),
690
+ /* @__PURE__ */ jsxs(
691
+ "section",
692
+ {
693
+ "aria-label": "Screen share capabilities",
694
+ style: {
695
+ padding: "8px 0"
696
+ },
697
+ children: [
698
+ /* @__PURE__ */ jsx("strong", { style: { color: "#e2e8f0" }, children: "capabilities" }),
699
+ /* @__PURE__ */ jsxs("div", { style: { color: "#64748b", margin: "6px 0 14px" }, children: [
700
+ Object.values(state?.capabilities.capabilities ?? {}).filter(
701
+ (capability) => capability.available
702
+ ).length,
703
+ " ",
704
+ "live / ",
705
+ state?.sessions.sessions.length ?? 0,
706
+ " sessions"
707
+ ] }),
708
+ /* @__PURE__ */ jsxs("div", { children: [
709
+ /* @__PURE__ */ jsx("span", { style: { color: "#64748b" }, children: "platform" }),
710
+ " ",
711
+ state?.capabilities.platform ?? "unknown"
712
+ ] }),
713
+ Object.entries(state?.capabilities.capabilities ?? {}).map(
714
+ ([name, capability]) => /* @__PURE__ */ jsxs("div", { style: { padding: "6px 0" }, children: [
715
+ /* @__PURE__ */ jsx(
716
+ "span",
717
+ {
718
+ style: {
719
+ color: capability.available ? "#a7f3d0" : "#fca5a5"
720
+ },
721
+ children: capability.available ? "ok" : "off"
722
+ }
723
+ ),
724
+ " ",
725
+ name,
726
+ " via ",
727
+ capability.tool
728
+ ] }, name)
729
+ )
730
+ ]
731
+ }
732
+ )
733
+ ]
734
+ }
735
+ )
736
+ ]
737
+ }
738
+ );
739
+ }
740
+ import { ScreenshareView } from "../components/ScreenshareView.js";
741
+ export {
742
+ ScreenshareOperatorSurface,
743
+ ScreenshareTuiView,
744
+ ScreenshareView
745
+ };
746
+ //# sourceMappingURL=ScreenshareOperatorSurface.js.map