@opengeni/react 1.0.1 → 2.2.0-canary.0
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/README.md +33 -10
- package/dist/artifacts-spreadsheet.js +1 -1
- package/dist/artifacts.js +1 -1
- package/dist/browser-viewer-GXUICIAG.js +14 -0
- package/dist/{chunk-R3AZOAB5.js → chunk-4MDLEHXL.js} +9 -115
- package/dist/chunk-4MDLEHXL.js.map +1 -0
- package/dist/{chunk-Y7OEDUJ5.js → chunk-5RZN3DD5.js} +1014 -420
- package/dist/chunk-5RZN3DD5.js.map +1 -0
- package/dist/chunk-5YK2ZDIG.js +116 -0
- package/dist/chunk-5YK2ZDIG.js.map +1 -0
- package/dist/chunk-H5YGYNXS.js +329 -0
- package/dist/chunk-H5YGYNXS.js.map +1 -0
- package/dist/{chunk-7WCLAEFV.js → chunk-ICA6R6TW.js} +2 -2
- package/dist/{chunk-7WCLAEFV.js.map → chunk-ICA6R6TW.js.map} +1 -1
- package/dist/{chunk-IGC6A2ZI.js → chunk-JOAVA2TW.js} +589 -217
- package/dist/chunk-JOAVA2TW.js.map +1 -0
- package/dist/{chunk-5UQPNLIO.js → chunk-LTCHJ4MS.js} +9 -9
- package/dist/chunk-LTCHJ4MS.js.map +1 -0
- package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
- package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
- package/dist/chunk-QGBJ6GHG.js +2300 -0
- package/dist/chunk-QGBJ6GHG.js.map +1 -0
- package/dist/{chunk-B6WPZSTT.js → chunk-UOLJWT5Y.js} +78 -16
- package/dist/chunk-UOLJWT5Y.js.map +1 -0
- package/dist/{chunk-MKPIAGVL.js → chunk-W6NFJXSA.js} +8 -19
- package/dist/chunk-W6NFJXSA.js.map +1 -0
- package/dist/{chunk-XBZWOM2K.js → chunk-X4A66EWZ.js} +8 -3
- package/dist/chunk-X4A66EWZ.js.map +1 -0
- package/dist/chunk-X4JAFD5R.js +3907 -0
- package/dist/chunk-X4JAFD5R.js.map +1 -0
- package/dist/{chunk-6KLX2RH5.js → chunk-XSA2QAKP.js} +334 -19
- package/dist/chunk-XSA2QAKP.js.map +1 -0
- package/dist/{chunk-HA46CYQK.js → chunk-XXWH2JLC.js} +792 -206
- package/dist/chunk-XXWH2JLC.js.map +1 -0
- package/dist/client.d.ts +2 -2
- package/dist/components/browser-viewer.d.ts +7 -1
- package/dist/components/computer-viewer.d.ts +4 -1
- package/dist/components/enrollment-consent.d.ts +6 -3
- package/dist/components/file-browser.d.ts +7 -1
- package/dist/components/human-input-form.d.ts +1 -1
- package/dist/components/human-input-surface.d.ts +1 -1
- package/dist/components/machine-card.d.ts +4 -1
- package/dist/components/machines/machine-detail.d.ts +4 -1
- package/dist/components/machines/machine-operation-policy.d.ts +11 -0
- package/dist/components/machines-dashboard.d.ts +3 -1
- package/dist/components/markdown.d.ts +20 -1
- package/dist/components/message-timeline.d.ts +1 -1
- package/dist/components/model-policy-picker.d.ts +2 -0
- package/dist/components/pierre-file.d.ts +1 -1
- package/dist/components/sandbox-files.d.ts +8 -2
- package/dist/components/sandbox-workspace.d.ts +33 -3
- package/dist/components/session-chrome.d.ts +15 -3
- package/dist/components/workspace-dock.d.ts +6 -2
- package/dist/composer.js +5 -5
- package/dist/computer-viewer-ZOP4Q7A7.js +16 -0
- package/dist/computer-viewer-ZOP4Q7A7.js.map +1 -0
- package/dist/hooks/channel-cache.d.ts +23 -0
- package/dist/hooks/shared-machines-list.d.ts +14 -0
- package/dist/hooks/use-attached-browsers.d.ts +2 -1
- package/dist/hooks/use-channels.d.ts +1 -0
- package/dist/hooks/use-composer.d.ts +37 -9
- package/dist/hooks/use-machine-chip.d.ts +3 -3
- package/dist/hooks/use-machines.d.ts +19 -1
- package/dist/hooks/use-sandbox-files.d.ts +1 -0
- package/dist/hooks/use-session-background-commands.d.ts +14 -0
- package/dist/hooks/use-turn-queue.d.ts +12 -0
- package/dist/hooks/use-workspace-sessions.d.ts +1 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +1096 -623
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +29 -181
- package/dist/interaction.js.map +1 -1
- package/dist/lib/interaction-errors.d.ts +3 -0
- package/dist/machines.d.ts +4 -2
- package/dist/machines.js +10 -2
- package/dist/model-policy.d.ts +1 -1
- package/dist/model-policy.js +1 -1
- package/dist/platform-activity-row-BJHUHXAT.js +169 -0
- package/dist/platform-activity-row-BJHUHXAT.js.map +1 -0
- package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-BSKUWHRI.js} +76 -16
- package/dist/queue-surface-implementation-BSKUWHRI.js.map +1 -0
- package/dist/realtime/realtime-control.d.ts +6 -3
- package/dist/realtime.js +36 -14
- package/dist/realtime.js.map +1 -1
- package/dist/session-ui.d.ts +1 -1
- package/dist/session-ui.js +6 -2
- package/dist/session.d.ts +2 -2
- package/dist/session.js +4 -4
- package/dist/timeline/index.d.ts +1 -1
- package/dist/timeline/platform-activity-row.d.ts +15 -0
- package/dist/timeline/screenshot-lightbox.d.ts +1 -1
- package/dist/timeline/shared.d.ts +4 -2
- package/dist/timeline/types.d.ts +48 -5
- package/dist/types/machines.d.ts +2 -2
- package/package.json +3 -3
- package/src/client.ts +12 -1
- package/src/components/artifacts/editable-spreadsheet.tsx +1 -1
- package/src/components/browser-viewer.tsx +361 -58
- package/src/components/chat-composer.tsx +1 -1
- package/src/components/composer.tsx +6 -6
- package/src/components/computer-viewer.tsx +368 -115
- package/src/components/enrollment-consent.tsx +64 -6
- package/src/components/file-browser.tsx +117 -2
- package/src/components/human-input-form.tsx +91 -55
- package/src/components/human-input-surface.tsx +1 -1
- package/src/components/machine-card.tsx +111 -0
- package/src/components/machine-input-display.ts +15 -0
- package/src/components/machines/machine-detail.tsx +47 -0
- package/src/components/machines/machine-operation-policy.tsx +179 -0
- package/src/components/machines-dashboard.tsx +6 -0
- package/src/components/markdown.tsx +174 -20
- package/src/components/message-timeline.tsx +162 -17
- package/src/components/model-policy-picker.tsx +9 -17
- package/src/components/pierre-file.tsx +1 -1
- package/src/components/queue-surface-implementation.tsx +82 -16
- package/src/components/sandbox-files.tsx +135 -19
- package/src/components/sandbox-workspace.tsx +204 -92
- package/src/components/session-chrome.tsx +415 -208
- package/src/components/session-status.tsx +1 -1
- package/src/components/user-message-body.tsx +168 -48
- package/src/components/workspace-dock.tsx +141 -175
- package/src/hooks/channel-cache.ts +104 -0
- package/src/hooks/shared-machines-list.ts +239 -0
- package/src/hooks/use-attached-browsers.ts +5 -1
- package/src/hooks/use-browser-frame-stream.ts +6 -1
- package/src/hooks/use-browser-session.ts +6 -4
- package/src/hooks/use-browser-sessions.ts +7 -1
- package/src/hooks/use-channels.ts +32 -10
- package/src/hooks/use-composer.ts +760 -291
- package/src/hooks/use-computer-frame-stream.ts +14 -9
- package/src/hooks/use-computer-session.ts +16 -14
- package/src/hooks/use-computer-sessions.ts +8 -1
- package/src/hooks/use-last-started-turn-policy.ts +1 -1
- package/src/hooks/use-machine-chip.ts +23 -6
- package/src/hooks/use-machines.ts +104 -6
- package/src/hooks/use-sandbox-files.ts +195 -140
- package/src/hooks/use-sandbox-git.ts +58 -29
- package/src/hooks/use-session-background-commands.ts +56 -0
- package/src/hooks/use-session-capabilities.ts +18 -0
- package/src/hooks/use-turn-queue.ts +111 -12
- package/src/hooks/use-workspace-sessions.ts +5 -1
- package/src/index.ts +26 -4
- package/src/lib/interaction-errors.ts +18 -0
- package/src/machines.ts +9 -1
- package/src/model-policy.ts +10 -2
- package/src/realtime/realtime-control.tsx +53 -17
- package/src/session-context.ts +1 -0
- package/src/session-ui.ts +6 -1
- package/src/session.ts +9 -1
- package/src/timeline/activity-rail.tsx +20 -75
- package/src/timeline/index.ts +4 -0
- package/src/timeline/platform-activity-row.tsx +201 -0
- package/src/timeline/projection.ts +476 -23
- package/src/timeline/screenshot-lightbox.tsx +48 -14
- package/src/timeline/shared.tsx +8 -2
- package/src/timeline/tool-renderers.tsx +104 -6
- package/src/timeline/turn-summary.tsx +6 -1
- package/src/timeline/types.ts +75 -2
- package/src/types/machines.ts +10 -0
- package/styles/compiled.css +115 -104
- package/dist/chunk-5UQPNLIO.js.map +0 -1
- package/dist/chunk-6KLX2RH5.js.map +0 -1
- package/dist/chunk-B6WPZSTT.js.map +0 -1
- package/dist/chunk-HA46CYQK.js.map +0 -1
- package/dist/chunk-IGC6A2ZI.js.map +0 -1
- package/dist/chunk-LLOLUHVG.js +0 -5937
- package/dist/chunk-LLOLUHVG.js.map +0 -1
- package/dist/chunk-MKPIAGVL.js.map +0 -1
- package/dist/chunk-R3AZOAB5.js.map +0 -1
- package/dist/chunk-XBZWOM2K.js.map +0 -1
- package/dist/chunk-Y7OEDUJ5.js.map +0 -1
- package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
- package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
- /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GXUICIAG.js.map} +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useMutationRunner,
|
|
3
|
-
usePageLiveActivity
|
|
4
|
-
usePolledValue
|
|
3
|
+
usePageLiveActivity
|
|
5
4
|
} from "./chunk-KZ73RL76.js";
|
|
6
5
|
import {
|
|
7
6
|
OpenGeniContext,
|
|
8
7
|
useOpenGeni
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NEXLLTP4.js";
|
|
10
9
|
import {
|
|
11
10
|
formatBytes,
|
|
12
11
|
formatRelativeTime
|
|
@@ -284,11 +283,15 @@ function MachineMetrics({ metrics, density = "compact", className }) {
|
|
|
284
283
|
|
|
285
284
|
// src/components/machine-card.tsx
|
|
286
285
|
import {
|
|
286
|
+
AlertTriangleIcon,
|
|
287
287
|
ArrowRightIcon,
|
|
288
288
|
CpuIcon,
|
|
289
|
+
CircleCheckIcon,
|
|
290
|
+
DownloadIcon,
|
|
289
291
|
LaptopIcon,
|
|
290
292
|
MonitorIcon,
|
|
291
293
|
MonitorOffIcon,
|
|
294
|
+
LoaderCircleIcon,
|
|
292
295
|
ServerIcon,
|
|
293
296
|
UsersIcon
|
|
294
297
|
} from "lucide-react";
|
|
@@ -505,6 +508,8 @@ function MachineCard({
|
|
|
505
508
|
machine,
|
|
506
509
|
onAttach,
|
|
507
510
|
attaching,
|
|
511
|
+
onUpdateAgent,
|
|
512
|
+
updatingAgent,
|
|
508
513
|
series,
|
|
509
514
|
onOpenDetail,
|
|
510
515
|
now,
|
|
@@ -517,6 +522,34 @@ function MachineCard({
|
|
|
517
522
|
const sampledAgo = machine.metrics ? formatRelativeTime(machine.metrics.sampledAt, new Date(clockNow)) : null;
|
|
518
523
|
const cpuPts = (series ?? []).map((s) => ({ t: new Date(s.sampledAt).getTime(), v: s.cpuPct }));
|
|
519
524
|
const openable = Boolean(onOpenDetail);
|
|
525
|
+
const runtime = machine.runtime;
|
|
526
|
+
const updateRunning = runtime?.versionState === "updating";
|
|
527
|
+
const dispatchConfirmationStalled = runtime?.update?.status === "requested" && clockNow - new Date(runtime.update.updatedAt).getTime() >= 3e4;
|
|
528
|
+
const canUpdate = Boolean(machine.enrollmentId && onUpdateAgent) && !offline && (runtime?.versionState === "outdated" || runtime?.versionState === "update_failed" || dispatchConfirmationStalled);
|
|
529
|
+
const updateLabel = (() => {
|
|
530
|
+
const update = runtime?.update;
|
|
531
|
+
if (!update) return null;
|
|
532
|
+
switch (update.status) {
|
|
533
|
+
case "requested":
|
|
534
|
+
return dispatchConfirmationStalled ? "Agent confirmation delayed" : "Confirming with agent";
|
|
535
|
+
case "accepted":
|
|
536
|
+
return "Update accepted";
|
|
537
|
+
case "waiting_for_idle":
|
|
538
|
+
return "Waiting for current work";
|
|
539
|
+
case "downloading":
|
|
540
|
+
case "verifying":
|
|
541
|
+
case "applying":
|
|
542
|
+
return `${update.status}\u2026`;
|
|
543
|
+
case "restarting":
|
|
544
|
+
return "Restarting agent";
|
|
545
|
+
case "succeeded":
|
|
546
|
+
return `Updated \xB7 v${update.targetVersion}`;
|
|
547
|
+
case "failed": {
|
|
548
|
+
const detail = update.errorCode?.replaceAll("_", " ");
|
|
549
|
+
return update.rolledBack ? `Update rolled back safely${detail ? ` \xB7 ${detail}` : ""}` : `Update failed${detail ? ` \xB7 ${detail}` : ""}`;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
})();
|
|
520
553
|
return /* @__PURE__ */ jsxs5(
|
|
521
554
|
"div",
|
|
522
555
|
{
|
|
@@ -556,6 +589,8 @@ function MachineCard({
|
|
|
556
589
|
) : null
|
|
557
590
|
] }),
|
|
558
591
|
/* @__PURE__ */ jsxs5("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-og-xs text-og-fg-subtle", children: [
|
|
592
|
+
/* @__PURE__ */ jsx5("span", { "data-machine-scope": machine.scope, className: "capitalize", children: machine.scope === "user" ? "personal" : machine.scope }),
|
|
593
|
+
/* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
|
|
559
594
|
/* @__PURE__ */ jsx5("span", { className: "capitalize", children: machine.isSessionGroup ? "session sandbox" : machine.kind }),
|
|
560
595
|
/* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
|
|
561
596
|
/* @__PURE__ */ jsxs5("span", { className: "font-og-mono", children: [
|
|
@@ -595,6 +630,51 @@ function MachineCard({
|
|
|
595
630
|
]
|
|
596
631
|
}
|
|
597
632
|
) : null,
|
|
633
|
+
machine.connectionAuthority.duplicateRunnerDeniedCount > 0 ? /* @__PURE__ */ jsxs5(
|
|
634
|
+
"p",
|
|
635
|
+
{
|
|
636
|
+
"data-runner-conflict": true,
|
|
637
|
+
className: "flex items-center gap-1.5 rounded-og-md border border-og-status-failed/30 bg-og-status-failed/5 px-2.5 py-1.5 text-og-xs text-og-status-failed",
|
|
638
|
+
children: [
|
|
639
|
+
/* @__PURE__ */ jsx5(AlertTriangleIcon, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
640
|
+
"Competing agent process blocked. Open diagnostics for details."
|
|
641
|
+
]
|
|
642
|
+
}
|
|
643
|
+
) : null,
|
|
644
|
+
runtime ? /* @__PURE__ */ jsxs5(
|
|
645
|
+
"div",
|
|
646
|
+
{
|
|
647
|
+
"data-agent-runtime": true,
|
|
648
|
+
className: "flex items-center justify-between gap-3 rounded-og-md border border-og-border/70 bg-og-surface-2/35 px-2.5 py-2 text-og-xs",
|
|
649
|
+
children: [
|
|
650
|
+
/* @__PURE__ */ jsxs5("div", { className: "min-w-0", children: [
|
|
651
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5 text-og-fg-muted", children: [
|
|
652
|
+
runtime.versionState === "current" ? /* @__PURE__ */ jsx5(CircleCheckIcon, { className: "size-3.5 text-og-status-idle", "aria-hidden": true }) : updateRunning ? /* @__PURE__ */ jsx5(LoaderCircleIcon, { className: "size-3.5 animate-og-spin text-og-accent", "aria-hidden": true }) : /* @__PURE__ */ jsx5(DownloadIcon, { className: "size-3.5", "aria-hidden": true }),
|
|
653
|
+
/* @__PURE__ */ jsxs5("span", { className: "truncate", children: [
|
|
654
|
+
"Agent",
|
|
655
|
+
" ",
|
|
656
|
+
runtime.installedVersion ? `v${runtime.installedVersion}` : "version unknown"
|
|
657
|
+
] })
|
|
658
|
+
] }),
|
|
659
|
+
/* @__PURE__ */ jsx5("p", { className: "mt-0.5 truncate text-og-fg-subtle", children: updateLabel ?? (runtime.versionState === "current" ? `Current \xB7 ${runtime.updateChannel ?? "channel unknown"}` : runtime.desiredVersion ? `Promoted v${runtime.desiredVersion}` : "No promoted version configured") })
|
|
660
|
+
] }),
|
|
661
|
+
canUpdate ? /* @__PURE__ */ jsx5(
|
|
662
|
+
"button",
|
|
663
|
+
{
|
|
664
|
+
type: "button",
|
|
665
|
+
"data-update-agent": true,
|
|
666
|
+
disabled: updatingAgent,
|
|
667
|
+
onClick: (event) => {
|
|
668
|
+
event.stopPropagation();
|
|
669
|
+
onUpdateAgent?.(machine);
|
|
670
|
+
},
|
|
671
|
+
className: "shrink-0 rounded-og-sm border border-og-border px-2 py-1 font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:text-og-fg disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:min-h-11",
|
|
672
|
+
children: updatingAgent ? "Starting\u2026" : dispatchConfirmationStalled ? "Retry delivery" : runtime.versionState === "update_failed" ? "Retry" : "Update"
|
|
673
|
+
}
|
|
674
|
+
) : null
|
|
675
|
+
]
|
|
676
|
+
}
|
|
677
|
+
) : null,
|
|
598
678
|
/* @__PURE__ */ jsx5(MachineMetrics, { metrics: machine.metrics }),
|
|
599
679
|
cpuPts.length > 1 ? /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-1 rounded-og-md bg-og-surface-2/40 p-2.5", children: [
|
|
600
680
|
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: [
|
|
@@ -888,6 +968,7 @@ function MetricHistoryChart({
|
|
|
888
968
|
|
|
889
969
|
// src/components/machines/machine-detail.tsx
|
|
890
970
|
import {
|
|
971
|
+
AlertTriangleIcon as AlertTriangleIcon3,
|
|
891
972
|
ArrowLeftIcon,
|
|
892
973
|
CpuIcon as CpuIcon2,
|
|
893
974
|
LaptopIcon as LaptopIcon2,
|
|
@@ -979,12 +1060,177 @@ function pointsFor(def, samples) {
|
|
|
979
1060
|
return ptsFrom(samples, def.pick);
|
|
980
1061
|
}
|
|
981
1062
|
|
|
982
|
-
// src/components/machines/machine-
|
|
1063
|
+
// src/components/machines/machine-operation-policy.tsx
|
|
1064
|
+
import { AlertTriangleIcon as AlertTriangleIcon2, Loader2Icon } from "lucide-react";
|
|
1065
|
+
import { useEffect, useState as useState2 } from "react";
|
|
983
1066
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1067
|
+
function fieldValue(value) {
|
|
1068
|
+
return value === null ? "" : String(value);
|
|
1069
|
+
}
|
|
1070
|
+
function parseByteCount(label, value) {
|
|
1071
|
+
const trimmed = value.trim();
|
|
1072
|
+
if (!trimmed) return null;
|
|
1073
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
1074
|
+
throw new Error(`${label} must be a whole number of bytes or blank`);
|
|
1075
|
+
}
|
|
1076
|
+
const parsed = Number(trimmed);
|
|
1077
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
1078
|
+
throw new Error(`${label} must be a positive safe-integer byte count or blank`);
|
|
1079
|
+
}
|
|
1080
|
+
return parsed;
|
|
1081
|
+
}
|
|
1082
|
+
function parseCpuMillicores(value) {
|
|
1083
|
+
const trimmed = value.trim();
|
|
1084
|
+
if (!trimmed) return null;
|
|
1085
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
1086
|
+
throw new Error("CPU maximum must be a whole number of millicores or blank");
|
|
1087
|
+
}
|
|
1088
|
+
const parsed = Number(trimmed);
|
|
1089
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0 || parsed > 4294967295) {
|
|
1090
|
+
throw new Error("CPU maximum must be between 1 and 4294967295 millicores or blank");
|
|
1091
|
+
}
|
|
1092
|
+
return parsed;
|
|
1093
|
+
}
|
|
1094
|
+
function MachineOperationPolicyEditor({
|
|
1095
|
+
policy,
|
|
1096
|
+
memorySupported,
|
|
1097
|
+
cpuSupported,
|
|
1098
|
+
saving = false,
|
|
1099
|
+
onSave
|
|
1100
|
+
}) {
|
|
1101
|
+
const [memoryMaxBytes, setMemoryMaxBytes] = useState2(fieldValue(policy.memoryMaxBytes));
|
|
1102
|
+
const [memoryHighBytes, setMemoryHighBytes] = useState2(fieldValue(policy.memoryHighBytes));
|
|
1103
|
+
const [cpuMaxMillicores, setCpuMaxMillicores] = useState2(fieldValue(policy.cpuMaxMillicores));
|
|
1104
|
+
const [validationError, setValidationError] = useState2(null);
|
|
1105
|
+
useEffect(() => {
|
|
1106
|
+
setMemoryMaxBytes(fieldValue(policy.memoryMaxBytes));
|
|
1107
|
+
setMemoryHighBytes(fieldValue(policy.memoryHighBytes));
|
|
1108
|
+
setCpuMaxMillicores(fieldValue(policy.cpuMaxMillicores));
|
|
1109
|
+
setValidationError(null);
|
|
1110
|
+
}, [policy.memoryMaxBytes, policy.memoryHighBytes, policy.cpuMaxMillicores, policy.revision]);
|
|
1111
|
+
const submit = async (event) => {
|
|
1112
|
+
event.preventDefault();
|
|
1113
|
+
try {
|
|
1114
|
+
const max = parseByteCount("Hard ceiling", memoryMaxBytes);
|
|
1115
|
+
const high = parseByteCount("Reclaim threshold", memoryHighBytes);
|
|
1116
|
+
if (max !== null && high !== null && high > max) {
|
|
1117
|
+
throw new Error("Reclaim threshold cannot exceed the hard ceiling");
|
|
1118
|
+
}
|
|
1119
|
+
const cpuMax = parseCpuMillicores(cpuMaxMillicores);
|
|
1120
|
+
setValidationError(null);
|
|
1121
|
+
await onSave({
|
|
1122
|
+
memoryMaxBytes: max,
|
|
1123
|
+
memoryHighBytes: high,
|
|
1124
|
+
cpuMaxMillicores: cpuMax,
|
|
1125
|
+
expectedRevision: policy.revision
|
|
1126
|
+
});
|
|
1127
|
+
} catch (error) {
|
|
1128
|
+
setValidationError(error instanceof Error ? error.message : String(error));
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
const configured = policy.memoryMaxBytes !== null || policy.memoryHighBytes !== null || policy.cpuMaxMillicores !== null;
|
|
1132
|
+
const memoryConfigured = policy.memoryMaxBytes !== null || policy.memoryHighBytes !== null;
|
|
1133
|
+
const unsupportedMemory = memoryConfigured && !memorySupported;
|
|
1134
|
+
const unsupportedCpu = policy.cpuMaxMillicores !== null && (!memorySupported || !cpuSupported);
|
|
1135
|
+
return /* @__PURE__ */ jsxs7(
|
|
1136
|
+
"section",
|
|
1137
|
+
{
|
|
1138
|
+
"data-machine-operation-policy": true,
|
|
1139
|
+
className: "rounded-og-lg border border-og-border bg-og-surface-1 p-4 shadow-og-sm",
|
|
1140
|
+
children: [
|
|
1141
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1", children: [
|
|
1142
|
+
/* @__PURE__ */ jsx7("h2", { className: "text-og-sm font-semibold text-og-fg", children: "Per-command resource policy" }),
|
|
1143
|
+
/* @__PURE__ */ jsx7("p", { className: "text-og-xs leading-relaxed text-og-fg-muted", children: "Optional limits applied separately to each newly admitted exec and Git command. Running commands keep their admitted policy. Blank means unrestricted. The runner or host may apply a stricter explicit policy; browser, computer-use, and terminal capabilities remain unchanged." })
|
|
1144
|
+
] }),
|
|
1145
|
+
configured && (unsupportedMemory || unsupportedCpu) ? /* @__PURE__ */ jsxs7("div", { className: "mt-3 flex gap-2 rounded-og-md border border-og-status-failed/40 bg-og-status-failed/5 p-3 text-og-xs text-og-status-failed", children: [
|
|
1146
|
+
/* @__PURE__ */ jsx7(AlertTriangleIcon2, { className: "mt-0.5 size-3.5 shrink-0", "aria-hidden": true }),
|
|
1147
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
1148
|
+
unsupportedCpu ? "This runner cannot enforce the configured CPU limit." : "This runner cannot enforce the configured memory limit.",
|
|
1149
|
+
" ",
|
|
1150
|
+
"Command execution fails closed until the current runner, OS, and service configuration can enforce it, or the unsupported limit is cleared. You can still save limits now for later enforcement."
|
|
1151
|
+
] })
|
|
1152
|
+
] }) : null,
|
|
1153
|
+
/* @__PURE__ */ jsxs7("form", { className: "mt-4 grid gap-3 sm:grid-cols-2", onSubmit: submit, children: [
|
|
1154
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex flex-col gap-1.5 text-og-xs text-og-fg-muted", children: [
|
|
1155
|
+
"Hard ceiling (bytes)",
|
|
1156
|
+
/* @__PURE__ */ jsx7(
|
|
1157
|
+
"input",
|
|
1158
|
+
{
|
|
1159
|
+
inputMode: "numeric",
|
|
1160
|
+
pattern: "[0-9]*",
|
|
1161
|
+
value: memoryMaxBytes,
|
|
1162
|
+
onChange: (event) => setMemoryMaxBytes(event.target.value),
|
|
1163
|
+
placeholder: "Unlimited",
|
|
1164
|
+
disabled: saving,
|
|
1165
|
+
className: "min-h-9 rounded-og-sm border border-og-border bg-og-bg px-2.5 font-og-mono text-og-sm text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/50 disabled:opacity-60"
|
|
1166
|
+
}
|
|
1167
|
+
)
|
|
1168
|
+
] }),
|
|
1169
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex flex-col gap-1.5 text-og-xs text-og-fg-muted", children: [
|
|
1170
|
+
"Reclaim threshold (bytes)",
|
|
1171
|
+
/* @__PURE__ */ jsx7(
|
|
1172
|
+
"input",
|
|
1173
|
+
{
|
|
1174
|
+
inputMode: "numeric",
|
|
1175
|
+
pattern: "[0-9]*",
|
|
1176
|
+
value: memoryHighBytes,
|
|
1177
|
+
onChange: (event) => setMemoryHighBytes(event.target.value),
|
|
1178
|
+
placeholder: "Unlimited",
|
|
1179
|
+
disabled: saving,
|
|
1180
|
+
className: "min-h-9 rounded-og-sm border border-og-border bg-og-bg px-2.5 font-og-mono text-og-sm text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/50 disabled:opacity-60"
|
|
1181
|
+
}
|
|
1182
|
+
)
|
|
1183
|
+
] }),
|
|
1184
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex flex-col gap-1.5 text-og-xs text-og-fg-muted", children: [
|
|
1185
|
+
"CPU maximum (millicores)",
|
|
1186
|
+
/* @__PURE__ */ jsx7(
|
|
1187
|
+
"input",
|
|
1188
|
+
{
|
|
1189
|
+
inputMode: "numeric",
|
|
1190
|
+
pattern: "[0-9]*",
|
|
1191
|
+
value: cpuMaxMillicores,
|
|
1192
|
+
onChange: (event) => setCpuMaxMillicores(event.target.value),
|
|
1193
|
+
placeholder: "Unlimited",
|
|
1194
|
+
disabled: saving,
|
|
1195
|
+
className: "min-h-9 rounded-og-sm border border-og-border bg-og-bg px-2.5 font-og-mono text-og-sm text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/50 disabled:opacity-60"
|
|
1196
|
+
}
|
|
1197
|
+
),
|
|
1198
|
+
/* @__PURE__ */ jsx7("span", { children: "1000 millicores = one CPU core. Blank is unlimited." })
|
|
1199
|
+
] }),
|
|
1200
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex min-h-9 items-center justify-between gap-3 sm:col-span-2", children: [
|
|
1201
|
+
/* @__PURE__ */ jsx7(
|
|
1202
|
+
"span",
|
|
1203
|
+
{
|
|
1204
|
+
role: validationError ? "alert" : void 0,
|
|
1205
|
+
className: "text-og-xs text-og-status-failed",
|
|
1206
|
+
children: validationError
|
|
1207
|
+
}
|
|
1208
|
+
),
|
|
1209
|
+
/* @__PURE__ */ jsxs7(
|
|
1210
|
+
"button",
|
|
1211
|
+
{
|
|
1212
|
+
type: "submit",
|
|
1213
|
+
disabled: saving,
|
|
1214
|
+
className: "inline-flex min-h-9 items-center gap-1.5 rounded-og-sm bg-og-accent px-3 py-1.5 text-og-xs font-medium text-og-accent-fg transition-colors hover:bg-og-accent-strong disabled:cursor-not-allowed disabled:opacity-60",
|
|
1215
|
+
children: [
|
|
1216
|
+
saving ? /* @__PURE__ */ jsx7(Loader2Icon, { className: "size-3.5 animate-spin", "aria-hidden": true }) : null,
|
|
1217
|
+
"Save policy"
|
|
1218
|
+
]
|
|
1219
|
+
}
|
|
1220
|
+
)
|
|
1221
|
+
] })
|
|
1222
|
+
] })
|
|
1223
|
+
]
|
|
1224
|
+
}
|
|
1225
|
+
);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// src/components/machines/machine-detail.tsx
|
|
1229
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
984
1230
|
function KindIcon2({ kind, session }) {
|
|
985
|
-
if (session) return /* @__PURE__ */
|
|
986
|
-
if (kind === "modal") return /* @__PURE__ */
|
|
987
|
-
return /* @__PURE__ */
|
|
1231
|
+
if (session) return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
1232
|
+
if (kind === "modal") return /* @__PURE__ */ jsx8(CpuIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
1233
|
+
return /* @__PURE__ */ jsx8(LaptopIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
988
1234
|
}
|
|
989
1235
|
function MachineDetail({
|
|
990
1236
|
machine,
|
|
@@ -994,6 +1240,8 @@ function MachineDetail({
|
|
|
994
1240
|
loadingSeries,
|
|
995
1241
|
onBack,
|
|
996
1242
|
onRemove,
|
|
1243
|
+
onUpdateOperationPolicy,
|
|
1244
|
+
updatingOperationPolicy,
|
|
997
1245
|
now = Date.now(),
|
|
998
1246
|
className
|
|
999
1247
|
}) {
|
|
@@ -1001,31 +1249,33 @@ function MachineDetail({
|
|
|
1001
1249
|
const tone = HEALTH_TOKEN[health.level];
|
|
1002
1250
|
const latest = machine.metrics;
|
|
1003
1251
|
const sampledAgo = latest ? formatRelativeTime(latest.sampledAt, new Date(now)) : null;
|
|
1252
|
+
const authority = machine.connectionAuthority;
|
|
1253
|
+
const duplicateDeniedAgo = authority.duplicateRunnerDeniedAt ? formatRelativeTime(authority.duplicateRunnerDeniedAt, new Date(now)) : null;
|
|
1004
1254
|
const visible = METRICS.filter((m) => !(m.key === "gpu" && latest?.gpuUtilPct == null));
|
|
1005
1255
|
const tileCols = visible.length >= 5 ? "grid-cols-2 sm:grid-cols-3 lg:grid-cols-5" : "grid-cols-2 sm:grid-cols-4";
|
|
1006
|
-
return /* @__PURE__ */
|
|
1007
|
-
/* @__PURE__ */
|
|
1008
|
-
/* @__PURE__ */
|
|
1009
|
-
onBack && /* @__PURE__ */
|
|
1256
|
+
return /* @__PURE__ */ jsxs8("div", { className: cn("og-root mx-auto flex w-full max-w-5xl flex-col gap-5", className), children: [
|
|
1257
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-3", children: [
|
|
1258
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
1259
|
+
onBack && /* @__PURE__ */ jsx8(
|
|
1010
1260
|
"button",
|
|
1011
1261
|
{
|
|
1012
1262
|
type: "button",
|
|
1013
1263
|
onClick: onBack,
|
|
1014
1264
|
className: "flex size-7 shrink-0 items-center justify-center rounded-og-sm border border-og-border bg-og-surface-1 text-og-fg-muted transition-colors hover:bg-og-surface-2 hover:text-og-fg",
|
|
1015
1265
|
"aria-label": "Back to machines",
|
|
1016
|
-
children: /* @__PURE__ */
|
|
1266
|
+
children: /* @__PURE__ */ jsx8(ArrowLeftIcon, { className: "size-3.5", "aria-hidden": true })
|
|
1017
1267
|
}
|
|
1018
1268
|
),
|
|
1019
|
-
/* @__PURE__ */
|
|
1020
|
-
/* @__PURE__ */
|
|
1021
|
-
/* @__PURE__ */
|
|
1269
|
+
/* @__PURE__ */ jsx8(KindIcon2, { kind: machine.kind, session: machine.isSessionGroup }),
|
|
1270
|
+
/* @__PURE__ */ jsx8("h1", { className: "truncate text-og-md font-semibold text-og-fg", children: machine.name }),
|
|
1271
|
+
/* @__PURE__ */ jsxs8("span", { className: "hidden shrink-0 rounded-og-sm border border-og-border bg-og-surface-1 px-1.5 py-0.5 font-og-mono text-og-xs text-og-fg-subtle sm:inline", children: [
|
|
1022
1272
|
machine.os,
|
|
1023
1273
|
" \xB7 ",
|
|
1024
1274
|
machine.arch
|
|
1025
1275
|
] })
|
|
1026
1276
|
] }),
|
|
1027
|
-
/* @__PURE__ */
|
|
1028
|
-
onRemove && machine.enrollmentId && !machine.isSessionGroup ? /* @__PURE__ */
|
|
1277
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1278
|
+
onRemove && machine.enrollmentId && !machine.isSessionGroup ? /* @__PURE__ */ jsxs8(
|
|
1029
1279
|
"button",
|
|
1030
1280
|
{
|
|
1031
1281
|
type: "button",
|
|
@@ -1034,12 +1284,12 @@ function MachineDetail({
|
|
|
1034
1284
|
onClick: () => onRemove(machine),
|
|
1035
1285
|
className: "inline-flex min-h-9 items-center gap-1.5 rounded-og-sm border border-og-status-failed/40 px-2.5 py-1 font-medium text-og-xs text-og-status-failed transition-colors hover:bg-og-status-failed/10 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-status-failed/50 pointer-coarse:min-h-11",
|
|
1036
1286
|
children: [
|
|
1037
|
-
/* @__PURE__ */
|
|
1038
|
-
/* @__PURE__ */
|
|
1287
|
+
/* @__PURE__ */ jsx8(Trash2Icon, { className: "size-3.5", "aria-hidden": true }),
|
|
1288
|
+
/* @__PURE__ */ jsx8("span", { className: "hidden sm:inline", children: "Remove machine" })
|
|
1039
1289
|
]
|
|
1040
1290
|
}
|
|
1041
1291
|
) : null,
|
|
1042
|
-
/* @__PURE__ */
|
|
1292
|
+
/* @__PURE__ */ jsx8("div", { className: "flex items-center gap-0.5 rounded-og-md border border-og-border bg-og-surface-1 p-0.5", children: METRIC_WINDOWS.map((w) => /* @__PURE__ */ jsx8(
|
|
1043
1293
|
"button",
|
|
1044
1294
|
{
|
|
1045
1295
|
type: "button",
|
|
@@ -1055,7 +1305,7 @@ function MachineDetail({
|
|
|
1055
1305
|
)) })
|
|
1056
1306
|
] })
|
|
1057
1307
|
] }),
|
|
1058
|
-
/* @__PURE__ */
|
|
1308
|
+
/* @__PURE__ */ jsxs8(
|
|
1059
1309
|
"div",
|
|
1060
1310
|
{
|
|
1061
1311
|
className: cn(
|
|
@@ -1063,11 +1313,11 @@ function MachineDetail({
|
|
|
1063
1313
|
tone.soft
|
|
1064
1314
|
),
|
|
1065
1315
|
children: [
|
|
1066
|
-
/* @__PURE__ */
|
|
1067
|
-
/* @__PURE__ */
|
|
1068
|
-
/* @__PURE__ */
|
|
1069
|
-
/* @__PURE__ */
|
|
1070
|
-
healthPulses(health.level) && /* @__PURE__ */
|
|
1316
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": true, className: cn("absolute inset-y-0 left-0 w-1", tone.dot) }),
|
|
1317
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap items-center justify-between gap-3 pl-1", children: [
|
|
1318
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
|
|
1319
|
+
/* @__PURE__ */ jsxs8("span", { className: "relative flex size-3", children: [
|
|
1320
|
+
healthPulses(health.level) && /* @__PURE__ */ jsx8(
|
|
1071
1321
|
"span",
|
|
1072
1322
|
{
|
|
1073
1323
|
className: cn(
|
|
@@ -1076,18 +1326,18 @@ function MachineDetail({
|
|
|
1076
1326
|
)
|
|
1077
1327
|
}
|
|
1078
1328
|
),
|
|
1079
|
-
/* @__PURE__ */
|
|
1329
|
+
/* @__PURE__ */ jsx8("span", { className: cn("relative inline-flex size-3 rounded-full", tone.dot) })
|
|
1080
1330
|
] }),
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
/* @__PURE__ */
|
|
1083
|
-
/* @__PURE__ */
|
|
1331
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
|
|
1332
|
+
/* @__PURE__ */ jsx8("span", { className: cn("text-og-md font-semibold", tone.text), children: health.label }),
|
|
1333
|
+
/* @__PURE__ */ jsx8("span", { className: "text-og-sm text-og-fg-muted", children: health.reason })
|
|
1084
1334
|
] })
|
|
1085
1335
|
] }),
|
|
1086
|
-
/* @__PURE__ */
|
|
1087
|
-
sampledAgo && /* @__PURE__ */
|
|
1088
|
-
/* @__PURE__ */
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1336
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-5 pr-1", children: [
|
|
1337
|
+
sampledAgo && /* @__PURE__ */ jsxs8("div", { className: "flex flex-col items-end gap-0.5", children: [
|
|
1338
|
+
/* @__PURE__ */ jsx8("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "Sampled" }),
|
|
1339
|
+
/* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-1 font-og-mono text-og-sm tabular-nums text-og-fg", children: [
|
|
1340
|
+
/* @__PURE__ */ jsx8(
|
|
1091
1341
|
RadioIcon,
|
|
1092
1342
|
{
|
|
1093
1343
|
className: cn("size-3", health.stale ? "text-og-fg-subtle" : tone.text),
|
|
@@ -1097,13 +1347,13 @@ function MachineDetail({
|
|
|
1097
1347
|
sampledAgo === "now" ? "live" : `${sampledAgo} ago`
|
|
1098
1348
|
] })
|
|
1099
1349
|
] }),
|
|
1100
|
-
machine.lastSeenAt && /* @__PURE__ */
|
|
1101
|
-
/* @__PURE__ */
|
|
1102
|
-
/* @__PURE__ */
|
|
1350
|
+
machine.lastSeenAt && /* @__PURE__ */ jsxs8("div", { className: "hidden flex-col items-end gap-0.5 sm:flex", children: [
|
|
1351
|
+
/* @__PURE__ */ jsx8("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "Last seen" }),
|
|
1352
|
+
/* @__PURE__ */ jsx8("span", { className: "font-og-mono text-og-sm tabular-nums text-og-fg-muted", children: formatRelativeTime(machine.lastSeenAt, new Date(now)) })
|
|
1103
1353
|
] })
|
|
1104
1354
|
] })
|
|
1105
1355
|
] }),
|
|
1106
|
-
latest && /* @__PURE__ */
|
|
1356
|
+
latest && /* @__PURE__ */ jsx8(
|
|
1107
1357
|
"div",
|
|
1108
1358
|
{
|
|
1109
1359
|
className: cn(
|
|
@@ -1112,30 +1362,64 @@ function MachineDetail({
|
|
|
1112
1362
|
),
|
|
1113
1363
|
children: visible.map((m) => {
|
|
1114
1364
|
const pts = pointsFor(m, series);
|
|
1115
|
-
return /* @__PURE__ */
|
|
1116
|
-
/* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
1118
|
-
/* @__PURE__ */
|
|
1119
|
-
m.sub && /* @__PURE__ */
|
|
1365
|
+
return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1.5 bg-og-surface-1 p-3", children: [
|
|
1366
|
+
/* @__PURE__ */ jsx8("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: m.title }),
|
|
1367
|
+
/* @__PURE__ */ jsx8("span", { className: "font-og-mono text-og-md font-medium tabular-nums text-og-fg", children: m.current(latest) }),
|
|
1368
|
+
/* @__PURE__ */ jsx8(MetricSparkline, { points: pts, color: m.color, yMax: m.yMax, height: 22 }),
|
|
1369
|
+
m.sub && /* @__PURE__ */ jsx8("span", { className: "truncate font-og-mono text-[10px] text-og-fg-subtle", children: m.sub(latest) })
|
|
1120
1370
|
] }, m.key);
|
|
1121
1371
|
})
|
|
1122
1372
|
}
|
|
1123
|
-
)
|
|
1373
|
+
),
|
|
1374
|
+
authority.state !== "not_applicable" ? /* @__PURE__ */ jsxs8(
|
|
1375
|
+
"div",
|
|
1376
|
+
{
|
|
1377
|
+
"data-connection-authority": authority.state,
|
|
1378
|
+
className: "flex flex-wrap items-center justify-between gap-2 rounded-og-md border border-og-border bg-og-surface-1/75 px-3 py-2 text-og-xs",
|
|
1379
|
+
children: [
|
|
1380
|
+
/* @__PURE__ */ jsxs8("span", { className: "text-og-fg-muted", children: [
|
|
1381
|
+
"Runner ",
|
|
1382
|
+
authority.state.replace("_", " "),
|
|
1383
|
+
" \xB7 generation ",
|
|
1384
|
+
authority.generation,
|
|
1385
|
+
authority.supersededCount > 0 ? ` \xB7 ${authority.supersededCount} earlier ${authority.supersededCount === 1 ? "runner" : "runners"} fenced` : ""
|
|
1386
|
+
] }),
|
|
1387
|
+
authority.duplicateRunnerDeniedCount > 0 ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1.5 text-og-status-failed", children: [
|
|
1388
|
+
/* @__PURE__ */ jsx8(AlertTriangleIcon3, { className: "size-3.5", "aria-hidden": true }),
|
|
1389
|
+
"Blocked ",
|
|
1390
|
+
authority.duplicateRunnerDeniedCount,
|
|
1391
|
+
" competing runner",
|
|
1392
|
+
authority.duplicateRunnerDeniedCount === 1 ? "" : "s",
|
|
1393
|
+
duplicateDeniedAgo ? ` \xB7 ${duplicateDeniedAgo === "now" ? "now" : `${duplicateDeniedAgo} ago`}` : ""
|
|
1394
|
+
] }) : null
|
|
1395
|
+
]
|
|
1396
|
+
}
|
|
1397
|
+
) : null
|
|
1124
1398
|
]
|
|
1125
1399
|
}
|
|
1126
1400
|
),
|
|
1127
|
-
|
|
1401
|
+
onUpdateOperationPolicy && machine.enrollmentId && machine.operationPolicy ? /* @__PURE__ */ jsx8(
|
|
1402
|
+
MachineOperationPolicyEditor,
|
|
1403
|
+
{
|
|
1404
|
+
policy: machine.operationPolicy,
|
|
1405
|
+
memorySupported: machine.runtime?.capabilities.operationResourcePolicy === true,
|
|
1406
|
+
cpuSupported: machine.runtime?.capabilities.operationCpuQuota === true,
|
|
1407
|
+
saving: updatingOperationPolicy,
|
|
1408
|
+
onSave: (request) => onUpdateOperationPolicy(machine, request)
|
|
1409
|
+
}
|
|
1410
|
+
) : null,
|
|
1411
|
+
/* @__PURE__ */ jsx8("div", { className: "grid grid-cols-1 gap-3 lg:grid-cols-2", children: visible.map((m) => {
|
|
1128
1412
|
const pts = pointsFor(m, series);
|
|
1129
|
-
return /* @__PURE__ */
|
|
1413
|
+
return /* @__PURE__ */ jsxs8(
|
|
1130
1414
|
"div",
|
|
1131
1415
|
{
|
|
1132
1416
|
className: "flex flex-col gap-3 rounded-og-lg border border-og-border bg-og-surface-1 p-4 shadow-og-sm",
|
|
1133
1417
|
children: [
|
|
1134
|
-
/* @__PURE__ */
|
|
1135
|
-
/* @__PURE__ */
|
|
1136
|
-
latest && /* @__PURE__ */
|
|
1418
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-baseline justify-between", children: [
|
|
1419
|
+
/* @__PURE__ */ jsx8("span", { className: "text-og-sm font-medium text-og-fg", children: m.title }),
|
|
1420
|
+
latest && /* @__PURE__ */ jsx8("span", { className: "font-og-mono text-og-sm tabular-nums text-og-fg-muted", children: m.current(latest) })
|
|
1137
1421
|
] }),
|
|
1138
|
-
/* @__PURE__ */
|
|
1422
|
+
/* @__PURE__ */ jsx8(
|
|
1139
1423
|
MetricHistoryChart,
|
|
1140
1424
|
{
|
|
1141
1425
|
points: pts,
|
|
@@ -1158,20 +1442,20 @@ function MachineDetail({
|
|
|
1158
1442
|
|
|
1159
1443
|
// src/components/machines-dashboard.tsx
|
|
1160
1444
|
import { LaptopIcon as LaptopIcon3, PlusIcon, RefreshCwIcon } from "lucide-react";
|
|
1161
|
-
import { jsx as
|
|
1445
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1162
1446
|
function EmptyState({ onEnroll }) {
|
|
1163
|
-
return /* @__PURE__ */
|
|
1447
|
+
return /* @__PURE__ */ jsxs9(
|
|
1164
1448
|
"div",
|
|
1165
1449
|
{
|
|
1166
1450
|
"data-machines-empty": true,
|
|
1167
1451
|
className: "flex flex-col items-center justify-center gap-3 rounded-og-lg border border-dashed border-og-border bg-og-surface-1 px-6 py-12 text-center",
|
|
1168
1452
|
children: [
|
|
1169
|
-
/* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1172
|
-
/* @__PURE__ */
|
|
1453
|
+
/* @__PURE__ */ jsx9("span", { className: "flex size-10 items-center justify-center rounded-full bg-og-surface-2 text-og-fg-subtle", children: /* @__PURE__ */ jsx9(LaptopIcon3, { className: "size-5", "aria-hidden": true }) }),
|
|
1454
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
|
|
1455
|
+
/* @__PURE__ */ jsx9("p", { className: "text-og-base font-medium text-og-fg", children: "No machines yet" }),
|
|
1456
|
+
/* @__PURE__ */ jsx9("p", { className: "max-w-xs text-og-sm text-og-fg-muted", children: "Connect your own computer to run the agent on it \u2014 your files, your terminal, your desktop." })
|
|
1173
1457
|
] }),
|
|
1174
|
-
onEnroll ? /* @__PURE__ */
|
|
1458
|
+
onEnroll ? /* @__PURE__ */ jsxs9(
|
|
1175
1459
|
"button",
|
|
1176
1460
|
{
|
|
1177
1461
|
type: "button",
|
|
@@ -1179,7 +1463,7 @@ function EmptyState({ onEnroll }) {
|
|
|
1179
1463
|
onClick: onEnroll,
|
|
1180
1464
|
className: "inline-flex items-center gap-1.5 rounded-og-sm bg-og-accent px-3 py-1.5 text-og-sm font-medium text-og-accent-fg transition-colors hover:bg-og-accent-strong pointer-coarse:min-h-11",
|
|
1181
1465
|
children: [
|
|
1182
|
-
/* @__PURE__ */
|
|
1466
|
+
/* @__PURE__ */ jsx9(PlusIcon, { className: "size-3.5", "aria-hidden": true }),
|
|
1183
1467
|
"Connect a machine"
|
|
1184
1468
|
]
|
|
1185
1469
|
}
|
|
@@ -1194,13 +1478,13 @@ function Header({
|
|
|
1194
1478
|
onRefresh,
|
|
1195
1479
|
loading
|
|
1196
1480
|
}) {
|
|
1197
|
-
return /* @__PURE__ */
|
|
1198
|
-
/* @__PURE__ */
|
|
1199
|
-
/* @__PURE__ */
|
|
1200
|
-
/* @__PURE__ */
|
|
1481
|
+
return /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
|
|
1482
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-baseline gap-2", children: [
|
|
1483
|
+
/* @__PURE__ */ jsx9("h2", { className: "text-og-base font-semibold text-og-fg", children: "Machines" }),
|
|
1484
|
+
/* @__PURE__ */ jsx9("span", { className: "font-og-mono text-og-xs text-og-fg-subtle", children: count })
|
|
1201
1485
|
] }),
|
|
1202
|
-
/* @__PURE__ */
|
|
1203
|
-
onRefresh ? /* @__PURE__ */
|
|
1486
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1.5", children: [
|
|
1487
|
+
onRefresh ? /* @__PURE__ */ jsx9(
|
|
1204
1488
|
"button",
|
|
1205
1489
|
{
|
|
1206
1490
|
type: "button",
|
|
@@ -1208,10 +1492,10 @@ function Header({
|
|
|
1208
1492
|
onClick: onRefresh,
|
|
1209
1493
|
title: "Refresh",
|
|
1210
1494
|
className: "rounded-og-sm p-1.5 text-og-fg-subtle transition-colors hover:bg-og-surface-2 hover:text-og-fg",
|
|
1211
|
-
children: /* @__PURE__ */
|
|
1495
|
+
children: /* @__PURE__ */ jsx9(RefreshCwIcon, { className: cn("size-3.5", loading && "animate-og-spin"), "aria-hidden": true })
|
|
1212
1496
|
}
|
|
1213
1497
|
) : null,
|
|
1214
|
-
onEnroll ? /* @__PURE__ */
|
|
1498
|
+
onEnroll ? /* @__PURE__ */ jsxs9(
|
|
1215
1499
|
"button",
|
|
1216
1500
|
{
|
|
1217
1501
|
type: "button",
|
|
@@ -1219,7 +1503,7 @@ function Header({
|
|
|
1219
1503
|
onClick: onEnroll,
|
|
1220
1504
|
className: "inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2.5 py-1 text-og-sm font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:text-og-fg pointer-coarse:min-h-11",
|
|
1221
1505
|
children: [
|
|
1222
|
-
/* @__PURE__ */
|
|
1506
|
+
/* @__PURE__ */ jsx9(PlusIcon, { className: "size-3.5", "aria-hidden": true }),
|
|
1223
1507
|
"Connect a machine"
|
|
1224
1508
|
]
|
|
1225
1509
|
}
|
|
@@ -1234,6 +1518,8 @@ function MachinesDashboard({
|
|
|
1234
1518
|
error,
|
|
1235
1519
|
onAttach,
|
|
1236
1520
|
attachingSandboxId,
|
|
1521
|
+
onUpdateAgent,
|
|
1522
|
+
updatingEnrollmentId,
|
|
1237
1523
|
seriesByMachine,
|
|
1238
1524
|
onOpenDetail,
|
|
1239
1525
|
now,
|
|
@@ -1242,19 +1528,19 @@ function MachinesDashboard({
|
|
|
1242
1528
|
className
|
|
1243
1529
|
}) {
|
|
1244
1530
|
const isEmpty = !loading && !error && machines.length === 0;
|
|
1245
|
-
return /* @__PURE__ */
|
|
1246
|
-
/* @__PURE__ */
|
|
1247
|
-
error ? /* @__PURE__ */
|
|
1531
|
+
return /* @__PURE__ */ jsxs9("section", { "data-machines-dashboard": true, className: cn("og-root flex flex-col gap-3", className), children: [
|
|
1532
|
+
/* @__PURE__ */ jsx9(Header, { count: machines.length, onEnroll, onRefresh, loading }),
|
|
1533
|
+
error ? /* @__PURE__ */ jsxs9(
|
|
1248
1534
|
"div",
|
|
1249
1535
|
{
|
|
1250
1536
|
"data-machines-error": true,
|
|
1251
1537
|
className: "flex flex-wrap items-center justify-between gap-2 rounded-og-md border border-og-status-failed/30 bg-og-status-failed/10 px-3 py-2 text-og-sm text-og-status-failed",
|
|
1252
1538
|
children: [
|
|
1253
|
-
/* @__PURE__ */
|
|
1539
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
1254
1540
|
"Could not load machines: ",
|
|
1255
1541
|
error.message
|
|
1256
1542
|
] }),
|
|
1257
|
-
onRefresh ? /* @__PURE__ */
|
|
1543
|
+
onRefresh ? /* @__PURE__ */ jsxs9(
|
|
1258
1544
|
"button",
|
|
1259
1545
|
{
|
|
1260
1546
|
type: "button",
|
|
@@ -1263,7 +1549,7 @@ function MachinesDashboard({
|
|
|
1263
1549
|
disabled: loading,
|
|
1264
1550
|
className: "inline-flex items-center gap-1.5 rounded-og-sm border border-og-status-failed/30 px-2 py-1 text-og-xs font-medium transition-colors hover:border-og-status-failed/50 disabled:cursor-not-allowed disabled:opacity-60 pointer-coarse:min-h-11",
|
|
1265
1551
|
children: [
|
|
1266
|
-
/* @__PURE__ */
|
|
1552
|
+
/* @__PURE__ */ jsx9(RefreshCwIcon, { className: cn("size-3.5", loading && "animate-og-spin"), "aria-hidden": true }),
|
|
1267
1553
|
loading ? "Retrying\u2026" : "Retry"
|
|
1268
1554
|
]
|
|
1269
1555
|
}
|
|
@@ -1271,13 +1557,13 @@ function MachinesDashboard({
|
|
|
1271
1557
|
]
|
|
1272
1558
|
}
|
|
1273
1559
|
) : null,
|
|
1274
|
-
loading && machines.length === 0 ? /* @__PURE__ */
|
|
1560
|
+
loading && machines.length === 0 ? /* @__PURE__ */ jsx9("div", { "data-machines-loading": true, className: "grid gap-3 sm:grid-cols-2", children: [0, 1].map((i) => /* @__PURE__ */ jsx9(
|
|
1275
1561
|
"div",
|
|
1276
1562
|
{
|
|
1277
1563
|
className: "h-36 animate-og-pulse rounded-og-lg border border-og-border bg-og-surface-1"
|
|
1278
1564
|
},
|
|
1279
1565
|
i
|
|
1280
|
-
)) }) : isEmpty ? /* @__PURE__ */
|
|
1566
|
+
)) }) : isEmpty ? /* @__PURE__ */ jsx9(EmptyState, { onEnroll }) : /* @__PURE__ */ jsx9("div", { className: "grid gap-3 sm:grid-cols-2 xl:grid-cols-3", "data-machines-grid": true, children: machines.map((machine) => /* @__PURE__ */ jsx9(
|
|
1281
1567
|
MachineCard,
|
|
1282
1568
|
{
|
|
1283
1569
|
machine: {
|
|
@@ -1286,6 +1572,8 @@ function MachinesDashboard({
|
|
|
1286
1572
|
},
|
|
1287
1573
|
onAttach,
|
|
1288
1574
|
attaching: attachingSandboxId === machine.sandboxId,
|
|
1575
|
+
onUpdateAgent,
|
|
1576
|
+
updatingAgent: updatingEnrollmentId === machine.enrollmentId,
|
|
1289
1577
|
series: seriesByMachine?.[machine.sandboxId],
|
|
1290
1578
|
onOpenDetail,
|
|
1291
1579
|
now
|
|
@@ -1297,11 +1585,11 @@ function MachinesDashboard({
|
|
|
1297
1585
|
|
|
1298
1586
|
// src/components/machine-dock-bar.tsx
|
|
1299
1587
|
import { LaptopIcon as LaptopIcon4, CpuIcon as CpuIcon3, UsersIcon as UsersIcon2 } from "lucide-react";
|
|
1300
|
-
import { jsx as
|
|
1588
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1301
1589
|
function MachineDockBar({ name, kind, state, className }) {
|
|
1302
1590
|
const Icon = kind === "selfhosted" ? LaptopIcon4 : CpuIcon3;
|
|
1303
1591
|
const stateBadge = MACHINE_STATE_BADGE_META[state];
|
|
1304
|
-
return /* @__PURE__ */
|
|
1592
|
+
return /* @__PURE__ */ jsxs10(
|
|
1305
1593
|
"div",
|
|
1306
1594
|
{
|
|
1307
1595
|
"data-machine-dock-bar": true,
|
|
@@ -1310,10 +1598,10 @@ function MachineDockBar({ name, kind, state, className }) {
|
|
|
1310
1598
|
className
|
|
1311
1599
|
),
|
|
1312
1600
|
children: [
|
|
1313
|
-
/* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
stateBadge ? /* @__PURE__ */
|
|
1601
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1602
|
+
/* @__PURE__ */ jsx10(Icon, { className: "size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
|
|
1603
|
+
/* @__PURE__ */ jsx10("span", { className: "truncate text-[11px] font-medium text-og-fg", children: name }),
|
|
1604
|
+
stateBadge ? /* @__PURE__ */ jsx10(
|
|
1317
1605
|
"span",
|
|
1318
1606
|
{
|
|
1319
1607
|
"data-state-badge": state,
|
|
@@ -1325,7 +1613,7 @@ function MachineDockBar({ name, kind, state, className }) {
|
|
|
1325
1613
|
}
|
|
1326
1614
|
) : null
|
|
1327
1615
|
] }),
|
|
1328
|
-
/* @__PURE__ */
|
|
1616
|
+
/* @__PURE__ */ jsx10(
|
|
1329
1617
|
ConnectionStatusPill,
|
|
1330
1618
|
{
|
|
1331
1619
|
status: connectionStatusForState(state),
|
|
@@ -1343,7 +1631,7 @@ function SharedMachineDisclosure({
|
|
|
1343
1631
|
className
|
|
1344
1632
|
}) {
|
|
1345
1633
|
const others = Math.max(0, sharedSessionCount - 1);
|
|
1346
|
-
return /* @__PURE__ */
|
|
1634
|
+
return /* @__PURE__ */ jsxs10(
|
|
1347
1635
|
"div",
|
|
1348
1636
|
{
|
|
1349
1637
|
"data-shared-disclosure": true,
|
|
@@ -1353,8 +1641,8 @@ function SharedMachineDisclosure({
|
|
|
1353
1641
|
className
|
|
1354
1642
|
),
|
|
1355
1643
|
children: [
|
|
1356
|
-
/* @__PURE__ */
|
|
1357
|
-
/* @__PURE__ */
|
|
1644
|
+
/* @__PURE__ */ jsx10(UsersIcon2, { className: "size-3.5 shrink-0 text-og-accent", "aria-hidden": true }),
|
|
1645
|
+
/* @__PURE__ */ jsxs10("span", { children: [
|
|
1358
1646
|
"Shared \u2014 ",
|
|
1359
1647
|
others === 1 ? "another session is" : `${others} other sessions are`,
|
|
1360
1648
|
" on this machine. They see the same terminal, files, and desktop."
|
|
@@ -1366,7 +1654,7 @@ function SharedMachineDisclosure({
|
|
|
1366
1654
|
|
|
1367
1655
|
// src/components/enrollment-device-flow.tsx
|
|
1368
1656
|
import { CopyIcon, ExternalLinkIcon, LaptopIcon as LaptopIcon5, TerminalIcon } from "lucide-react";
|
|
1369
|
-
import { Fragment as Fragment2, jsx as
|
|
1657
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1370
1658
|
var PHASE_TO_STATE = {
|
|
1371
1659
|
pending: "enrolling",
|
|
1372
1660
|
authorized: "online",
|
|
@@ -1382,7 +1670,7 @@ function PhaseLabel({ phase }) {
|
|
|
1382
1670
|
expired: "Code expired",
|
|
1383
1671
|
disabled: "Enrollment disabled"
|
|
1384
1672
|
};
|
|
1385
|
-
return /* @__PURE__ */
|
|
1673
|
+
return /* @__PURE__ */ jsx11("span", { children: text[phase] });
|
|
1386
1674
|
}
|
|
1387
1675
|
function EnrollmentDeviceFlow({
|
|
1388
1676
|
userCode,
|
|
@@ -1399,7 +1687,7 @@ function EnrollmentDeviceFlow({
|
|
|
1399
1687
|
const href = verificationUriComplete ?? verificationUri;
|
|
1400
1688
|
const codeIsPlaceholder = !/[A-Za-z0-9]/.test(userCode);
|
|
1401
1689
|
const awaitingCode = phase === "pending" && codeIsPlaceholder;
|
|
1402
|
-
return /* @__PURE__ */
|
|
1690
|
+
return /* @__PURE__ */ jsxs11(
|
|
1403
1691
|
"div",
|
|
1404
1692
|
{
|
|
1405
1693
|
"data-enrollment-device-flow": true,
|
|
@@ -1408,28 +1696,28 @@ function EnrollmentDeviceFlow({
|
|
|
1408
1696
|
className
|
|
1409
1697
|
),
|
|
1410
1698
|
children: [
|
|
1411
|
-
/* @__PURE__ */
|
|
1412
|
-
/* @__PURE__ */
|
|
1413
|
-
/* @__PURE__ */
|
|
1414
|
-
/* @__PURE__ */
|
|
1699
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-3", children: [
|
|
1700
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
1701
|
+
/* @__PURE__ */ jsx11("span", { className: "flex size-7 items-center justify-center rounded-full bg-og-surface-2 text-og-fg-muted", children: /* @__PURE__ */ jsx11(LaptopIcon5, { className: "size-4", "aria-hidden": true }) }),
|
|
1702
|
+
/* @__PURE__ */ jsx11("h2", { className: "text-og-menu font-semibold text-og-fg", children: "Connect a machine" })
|
|
1415
1703
|
] }),
|
|
1416
|
-
/* @__PURE__ */
|
|
1704
|
+
/* @__PURE__ */ jsx11(
|
|
1417
1705
|
ConnectionStatusPill,
|
|
1418
1706
|
{
|
|
1419
1707
|
status: PHASE_TO_STATE[phase] === "online" ? "online" : PHASE_TO_STATE[phase] === "offline" ? "offline" : "reconnecting",
|
|
1420
|
-
label: /* @__PURE__ */
|
|
1708
|
+
label: /* @__PURE__ */ jsx11(PhaseLabel, { phase }),
|
|
1421
1709
|
size: "sm"
|
|
1422
1710
|
}
|
|
1423
1711
|
)
|
|
1424
1712
|
] }),
|
|
1425
|
-
installCommand ? /* @__PURE__ */
|
|
1426
|
-
/* @__PURE__ */
|
|
1427
|
-
/* @__PURE__ */
|
|
1428
|
-
/* @__PURE__ */
|
|
1429
|
-
/* @__PURE__ */
|
|
1713
|
+
installCommand ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1.5", children: [
|
|
1714
|
+
/* @__PURE__ */ jsx11("span", { className: "text-[11px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "1 \xB7 Run on the machine" }),
|
|
1715
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-2 overflow-hidden rounded-og-md border border-og-border bg-og-bg px-2.5 py-1.5", children: [
|
|
1716
|
+
/* @__PURE__ */ jsxs11("code", { className: "flex min-w-0 items-center gap-2 overflow-x-auto font-og-mono text-[12px] text-og-fg", children: [
|
|
1717
|
+
/* @__PURE__ */ jsx11(TerminalIcon, { className: "size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
|
|
1430
1718
|
installCommand
|
|
1431
1719
|
] }),
|
|
1432
|
-
/* @__PURE__ */
|
|
1720
|
+
/* @__PURE__ */ jsx11(
|
|
1433
1721
|
"button",
|
|
1434
1722
|
{
|
|
1435
1723
|
type: "button",
|
|
@@ -1437,15 +1725,15 @@ function EnrollmentDeviceFlow({
|
|
|
1437
1725
|
onClick: onCopyInstall,
|
|
1438
1726
|
title: "Copy command",
|
|
1439
1727
|
className: "shrink-0 rounded-og-sm p-1.5 text-og-fg-subtle transition-colors hover:bg-og-surface-2 hover:text-og-fg",
|
|
1440
|
-
children: /* @__PURE__ */
|
|
1728
|
+
children: /* @__PURE__ */ jsx11(CopyIcon, { className: "size-4", "aria-hidden": true })
|
|
1441
1729
|
}
|
|
1442
1730
|
)
|
|
1443
1731
|
] })
|
|
1444
1732
|
] }) : null,
|
|
1445
|
-
/* @__PURE__ */
|
|
1446
|
-
/* @__PURE__ */
|
|
1447
|
-
/* @__PURE__ */
|
|
1448
|
-
awaitingCode ? /* @__PURE__ */
|
|
1733
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1.5", children: [
|
|
1734
|
+
/* @__PURE__ */ jsx11("span", { className: "text-[11px] font-medium uppercase tracking-wide text-og-fg-subtle", children: installCommand ? "2 \xB7 Approve the machine" : "Approve the machine" }),
|
|
1735
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-3 rounded-og-md border border-og-border bg-og-bg px-3 py-2.5", children: [
|
|
1736
|
+
awaitingCode ? /* @__PURE__ */ jsx11("span", { "data-user-code": true, className: "font-og-mono text-[13px] text-og-fg-subtle", children: "Run the command above \u2014 your code appears here" }) : /* @__PURE__ */ jsx11(
|
|
1449
1737
|
"span",
|
|
1450
1738
|
{
|
|
1451
1739
|
"data-user-code": true,
|
|
@@ -1453,7 +1741,7 @@ function EnrollmentDeviceFlow({
|
|
|
1453
1741
|
children: userCode
|
|
1454
1742
|
}
|
|
1455
1743
|
),
|
|
1456
|
-
/* @__PURE__ */
|
|
1744
|
+
/* @__PURE__ */ jsx11(
|
|
1457
1745
|
"button",
|
|
1458
1746
|
{
|
|
1459
1747
|
type: "button",
|
|
@@ -1462,12 +1750,12 @@ function EnrollmentDeviceFlow({
|
|
|
1462
1750
|
disabled: awaitingCode,
|
|
1463
1751
|
title: "Copy code",
|
|
1464
1752
|
className: "shrink-0 rounded-og-sm p-1.5 text-og-fg-subtle transition-colors hover:bg-og-surface-2 hover:text-og-fg disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-og-fg-subtle",
|
|
1465
|
-
children: /* @__PURE__ */
|
|
1753
|
+
children: /* @__PURE__ */ jsx11(CopyIcon, { className: "size-4", "aria-hidden": true })
|
|
1466
1754
|
}
|
|
1467
1755
|
)
|
|
1468
1756
|
] })
|
|
1469
1757
|
] }),
|
|
1470
|
-
/* @__PURE__ */
|
|
1758
|
+
/* @__PURE__ */ jsxs11(
|
|
1471
1759
|
"a",
|
|
1472
1760
|
{
|
|
1473
1761
|
href,
|
|
@@ -1478,23 +1766,23 @@ function EnrollmentDeviceFlow({
|
|
|
1478
1766
|
className: "inline-flex items-center justify-center gap-1.5 rounded-og-sm bg-og-accent px-3 py-2 text-og-menu font-medium text-og-accent-fg transition-colors hover:bg-og-accent-strong",
|
|
1479
1767
|
children: [
|
|
1480
1768
|
"Open approval page",
|
|
1481
|
-
/* @__PURE__ */
|
|
1769
|
+
/* @__PURE__ */ jsx11(ExternalLinkIcon, { className: "size-3.5", "aria-hidden": true })
|
|
1482
1770
|
]
|
|
1483
1771
|
}
|
|
1484
1772
|
),
|
|
1485
|
-
/* @__PURE__ */
|
|
1773
|
+
/* @__PURE__ */ jsx11("p", { className: "text-center text-[11px] text-og-fg-subtle", children: awaitingCode ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
1486
1774
|
"The one-liner prints a short code. Open",
|
|
1487
1775
|
" ",
|
|
1488
|
-
/* @__PURE__ */
|
|
1776
|
+
/* @__PURE__ */ jsx11("span", { className: "font-og-mono text-og-fg-muted", children: verificationUri }),
|
|
1489
1777
|
" and confirm the code shown there matches."
|
|
1490
|
-
] }) : /* @__PURE__ */
|
|
1778
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
1491
1779
|
"Confirm code ",
|
|
1492
|
-
/* @__PURE__ */
|
|
1780
|
+
/* @__PURE__ */ jsx11("span", { className: "font-og-mono text-og-fg-muted", children: userCode }),
|
|
1493
1781
|
" \u2014 the one printed by the one-liner \u2014 at",
|
|
1494
1782
|
" ",
|
|
1495
|
-
/* @__PURE__ */
|
|
1783
|
+
/* @__PURE__ */ jsx11("span", { className: "font-og-mono text-og-fg-muted", children: verificationUri }),
|
|
1496
1784
|
".",
|
|
1497
|
-
typeof expiresInSeconds === "number" ? /* @__PURE__ */
|
|
1785
|
+
typeof expiresInSeconds === "number" ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
1498
1786
|
" Expires in ",
|
|
1499
1787
|
Math.max(0, Math.round(expiresInSeconds / 60)),
|
|
1500
1788
|
" min."
|
|
@@ -1506,7 +1794,7 @@ function EnrollmentDeviceFlow({
|
|
|
1506
1794
|
}
|
|
1507
1795
|
|
|
1508
1796
|
// src/components/enrollment-consent.tsx
|
|
1509
|
-
import { useState as
|
|
1797
|
+
import { useState as useState3 } from "react";
|
|
1510
1798
|
import {
|
|
1511
1799
|
CircleAlertIcon,
|
|
1512
1800
|
LaptopIcon as LaptopIcon6,
|
|
@@ -1516,13 +1804,13 @@ import {
|
|
|
1516
1804
|
TerminalIcon as TerminalIcon2,
|
|
1517
1805
|
UsersIcon as UsersIcon3
|
|
1518
1806
|
} from "lucide-react";
|
|
1519
|
-
import { jsx as
|
|
1807
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1520
1808
|
function Capability({ icon, title, body }) {
|
|
1521
|
-
return /* @__PURE__ */
|
|
1522
|
-
/* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */
|
|
1809
|
+
return /* @__PURE__ */ jsxs12("li", { className: "flex items-start gap-2.5", children: [
|
|
1810
|
+
/* @__PURE__ */ jsx12("span", { className: "mt-0.5 shrink-0 text-og-status-failed", children: icon }),
|
|
1811
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-0", children: [
|
|
1812
|
+
/* @__PURE__ */ jsx12("span", { className: "block text-og-base font-medium text-og-fg", children: title }),
|
|
1813
|
+
/* @__PURE__ */ jsx12("span", { className: "block text-og-sm text-og-fg-muted", children: body })
|
|
1526
1814
|
] })
|
|
1527
1815
|
] });
|
|
1528
1816
|
}
|
|
@@ -1530,26 +1818,42 @@ function EnrollmentConsent({
|
|
|
1530
1818
|
userCode,
|
|
1531
1819
|
machine,
|
|
1532
1820
|
phase = "review",
|
|
1821
|
+
allowOrganizationScope = false,
|
|
1533
1822
|
onApprove,
|
|
1534
1823
|
onDeny,
|
|
1535
1824
|
errorMessage,
|
|
1536
1825
|
className
|
|
1537
1826
|
}) {
|
|
1538
|
-
const [allowScreenControl, setAllowScreenControl] =
|
|
1827
|
+
const [allowScreenControl, setAllowScreenControl] = useState3(machine.requestsScreenControl);
|
|
1828
|
+
const [scope, setScope] = useState3("user");
|
|
1539
1829
|
const busy = phase === "approving";
|
|
1830
|
+
const scopeCopy = {
|
|
1831
|
+
user: {
|
|
1832
|
+
label: "Personal",
|
|
1833
|
+
body: "Only you can use this machine, from any workspace you can access in this organization."
|
|
1834
|
+
},
|
|
1835
|
+
workspace: {
|
|
1836
|
+
label: "Workspace",
|
|
1837
|
+
body: "Everyone with access to this workspace can use this machine."
|
|
1838
|
+
},
|
|
1839
|
+
organization: {
|
|
1840
|
+
label: "Organization",
|
|
1841
|
+
body: "Members of this organization can use this machine from their workspaces."
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1540
1844
|
if (phase === "approved") {
|
|
1541
|
-
return /* @__PURE__ */
|
|
1845
|
+
return /* @__PURE__ */ jsx12(
|
|
1542
1846
|
ConsentResult,
|
|
1543
1847
|
{
|
|
1544
1848
|
className,
|
|
1545
1849
|
tone: "ok",
|
|
1546
1850
|
title: "Machine connected",
|
|
1547
|
-
body: `${machine.machineName} is now
|
|
1851
|
+
body: `${machine.machineName} is now connected with ${scopeCopy[scope].label.toLowerCase()} access. You can close this page \u2014 it will appear in your Machines dashboard.`
|
|
1548
1852
|
}
|
|
1549
1853
|
);
|
|
1550
1854
|
}
|
|
1551
1855
|
if (phase === "denied") {
|
|
1552
|
-
return /* @__PURE__ */
|
|
1856
|
+
return /* @__PURE__ */ jsx12(
|
|
1553
1857
|
ConsentResult,
|
|
1554
1858
|
{
|
|
1555
1859
|
className,
|
|
@@ -1560,7 +1864,7 @@ function EnrollmentConsent({
|
|
|
1560
1864
|
);
|
|
1561
1865
|
}
|
|
1562
1866
|
if (phase === "error") {
|
|
1563
|
-
return /* @__PURE__ */
|
|
1867
|
+
return /* @__PURE__ */ jsx12(
|
|
1564
1868
|
ConsentResult,
|
|
1565
1869
|
{
|
|
1566
1870
|
className,
|
|
@@ -1570,7 +1874,7 @@ function EnrollmentConsent({
|
|
|
1570
1874
|
}
|
|
1571
1875
|
);
|
|
1572
1876
|
}
|
|
1573
|
-
return /* @__PURE__ */
|
|
1877
|
+
return /* @__PURE__ */ jsxs12(
|
|
1574
1878
|
"div",
|
|
1575
1879
|
{
|
|
1576
1880
|
"data-enrollment-consent": true,
|
|
@@ -1579,65 +1883,104 @@ function EnrollmentConsent({
|
|
|
1579
1883
|
className
|
|
1580
1884
|
),
|
|
1581
1885
|
children: [
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
/* @__PURE__ */
|
|
1584
|
-
/* @__PURE__ */
|
|
1585
|
-
/* @__PURE__ */
|
|
1586
|
-
/* @__PURE__ */
|
|
1886
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3", children: [
|
|
1887
|
+
/* @__PURE__ */ jsx12("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-full bg-og-status-failed/15 text-og-status-failed", children: /* @__PURE__ */ jsx12(ShieldAlertIcon, { className: "size-5", "aria-hidden": true }) }),
|
|
1888
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
|
|
1889
|
+
/* @__PURE__ */ jsx12("h1", { className: "text-og-md font-semibold text-og-fg", children: "Give the agent your whole machine?" }),
|
|
1890
|
+
/* @__PURE__ */ jsxs12("p", { className: "mt-1 text-og-base text-og-fg-muted", children: [
|
|
1587
1891
|
"Approving lets the OpenGeni agent run on",
|
|
1588
1892
|
" ",
|
|
1589
|
-
/* @__PURE__ */
|
|
1893
|
+
/* @__PURE__ */ jsx12("span", { className: "font-medium text-og-fg", children: machine.machineName }),
|
|
1590
1894
|
" with full access. This is your real computer \u2014 not a sandbox."
|
|
1591
1895
|
] })
|
|
1592
1896
|
] })
|
|
1593
1897
|
] }),
|
|
1594
|
-
/* @__PURE__ */
|
|
1595
|
-
/* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
1898
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2 rounded-og-md border border-og-border bg-og-surface-2 px-3 py-2 text-og-sm", children: [
|
|
1899
|
+
/* @__PURE__ */ jsx12(LaptopIcon6, { className: "size-4 text-og-fg-subtle", "aria-hidden": true }),
|
|
1900
|
+
/* @__PURE__ */ jsx12("span", { className: "font-medium text-og-fg", children: machine.machineName }),
|
|
1901
|
+
/* @__PURE__ */ jsxs12("span", { className: "font-og-mono text-og-fg-subtle", children: [
|
|
1598
1902
|
machine.os,
|
|
1599
1903
|
"/",
|
|
1600
1904
|
machine.arch
|
|
1601
1905
|
] }),
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__PURE__ */
|
|
1906
|
+
/* @__PURE__ */ jsx12("span", { "aria-hidden": true, className: "text-og-fg-subtle", children: "\xB7" }),
|
|
1907
|
+
/* @__PURE__ */ jsxs12("span", { className: "text-og-fg-subtle", children: [
|
|
1604
1908
|
"code ",
|
|
1605
|
-
/* @__PURE__ */
|
|
1909
|
+
/* @__PURE__ */ jsx12("span", { className: "font-og-mono font-medium text-og-fg", children: userCode })
|
|
1606
1910
|
] })
|
|
1607
1911
|
] }),
|
|
1608
|
-
/* @__PURE__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1912
|
+
/* @__PURE__ */ jsxs12("ul", { className: "flex flex-col gap-3", children: [
|
|
1913
|
+
/* @__PURE__ */ jsx12(
|
|
1610
1914
|
Capability,
|
|
1611
1915
|
{
|
|
1612
|
-
icon: /* @__PURE__ */
|
|
1916
|
+
icon: /* @__PURE__ */ jsx12(TerminalIcon2, { className: "size-4", "aria-hidden": true }),
|
|
1613
1917
|
title: "Read, write & run anything",
|
|
1614
1918
|
body: "The agent can read and modify any file, run any command, and use your git credentials \u2014 as if it were you at the keyboard."
|
|
1615
1919
|
}
|
|
1616
1920
|
),
|
|
1617
|
-
machine.canOfferDisplay ? /* @__PURE__ */
|
|
1921
|
+
machine.canOfferDisplay ? /* @__PURE__ */ jsx12(
|
|
1618
1922
|
Capability,
|
|
1619
1923
|
{
|
|
1620
|
-
icon: /* @__PURE__ */
|
|
1924
|
+
icon: /* @__PURE__ */ jsx12(MonitorIcon2, { className: "size-4", "aria-hidden": true }),
|
|
1621
1925
|
title: "See your screen",
|
|
1622
1926
|
body: "The agent can capture this machine's display to watch what it is doing."
|
|
1623
1927
|
}
|
|
1624
1928
|
) : null,
|
|
1625
|
-
/* @__PURE__ */
|
|
1929
|
+
/* @__PURE__ */ jsx12(
|
|
1626
1930
|
Capability,
|
|
1627
1931
|
{
|
|
1628
|
-
icon: /* @__PURE__ */
|
|
1629
|
-
title:
|
|
1630
|
-
body:
|
|
1932
|
+
icon: /* @__PURE__ */ jsx12(UsersIcon3, { className: "size-4", "aria-hidden": true }),
|
|
1933
|
+
title: `${scopeCopy[scope].label} access while connected`,
|
|
1934
|
+
body: `${scopeCopy[scope].body} Disconnect the agent to revoke access instantly.`
|
|
1631
1935
|
}
|
|
1632
1936
|
)
|
|
1633
1937
|
] }),
|
|
1634
|
-
|
|
1938
|
+
/* @__PURE__ */ jsxs12("fieldset", { className: "flex flex-col gap-2", disabled: busy, children: [
|
|
1939
|
+
/* @__PURE__ */ jsx12("legend", { className: "mb-1 text-og-sm font-medium text-og-fg", children: "Who can use this machine?" }),
|
|
1940
|
+
["user", "workspace", "organization"].map((candidate) => {
|
|
1941
|
+
const disabled = candidate === "organization" && !allowOrganizationScope;
|
|
1942
|
+
return /* @__PURE__ */ jsxs12(
|
|
1943
|
+
"label",
|
|
1944
|
+
{
|
|
1945
|
+
"data-enrollment-scope": candidate,
|
|
1946
|
+
"data-disabled": disabled ? "true" : "false",
|
|
1947
|
+
className: cn(
|
|
1948
|
+
"flex items-start gap-2.5 rounded-og-md border border-og-border bg-og-bg px-3 py-2.5",
|
|
1949
|
+
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
|
|
1950
|
+
),
|
|
1951
|
+
children: [
|
|
1952
|
+
/* @__PURE__ */ jsx12(
|
|
1953
|
+
"input",
|
|
1954
|
+
{
|
|
1955
|
+
type: "radio",
|
|
1956
|
+
name: "enrollment-scope",
|
|
1957
|
+
value: candidate,
|
|
1958
|
+
checked: scope === candidate,
|
|
1959
|
+
disabled: disabled || busy,
|
|
1960
|
+
onChange: () => setScope(candidate),
|
|
1961
|
+
className: "mt-0.5 size-4 accent-og-accent"
|
|
1962
|
+
}
|
|
1963
|
+
),
|
|
1964
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-0", children: [
|
|
1965
|
+
/* @__PURE__ */ jsxs12("span", { className: "block text-og-base font-medium text-og-fg", children: [
|
|
1966
|
+
scopeCopy[candidate].label,
|
|
1967
|
+
disabled ? " \xB7 organization admin required" : ""
|
|
1968
|
+
] }),
|
|
1969
|
+
/* @__PURE__ */ jsx12("span", { className: "block text-og-sm text-og-fg-muted", children: scopeCopy[candidate].body })
|
|
1970
|
+
] })
|
|
1971
|
+
]
|
|
1972
|
+
},
|
|
1973
|
+
candidate
|
|
1974
|
+
);
|
|
1975
|
+
})
|
|
1976
|
+
] }),
|
|
1977
|
+
machine.canOfferDisplay ? /* @__PURE__ */ jsxs12(
|
|
1635
1978
|
"label",
|
|
1636
1979
|
{
|
|
1637
1980
|
"data-screen-control-toggle": true,
|
|
1638
1981
|
className: "flex cursor-pointer items-start gap-3 rounded-og-md border border-og-border bg-og-bg px-3 py-2.5",
|
|
1639
1982
|
children: [
|
|
1640
|
-
/* @__PURE__ */
|
|
1983
|
+
/* @__PURE__ */ jsx12(
|
|
1641
1984
|
"input",
|
|
1642
1985
|
{
|
|
1643
1986
|
type: "checkbox",
|
|
@@ -1647,21 +1990,21 @@ function EnrollmentConsent({
|
|
|
1647
1990
|
className: "mt-0.5 size-4 accent-og-accent"
|
|
1648
1991
|
}
|
|
1649
1992
|
),
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */
|
|
1652
|
-
/* @__PURE__ */
|
|
1993
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-0", children: [
|
|
1994
|
+
/* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1.5 text-og-base font-medium text-og-fg", children: [
|
|
1995
|
+
/* @__PURE__ */ jsx12(ScreenShareIcon, { className: "size-3.5 text-og-fg-muted", "aria-hidden": true }),
|
|
1653
1996
|
"Also let the agent control my mouse & keyboard"
|
|
1654
1997
|
] }),
|
|
1655
|
-
/* @__PURE__ */
|
|
1998
|
+
/* @__PURE__ */ jsx12("span", { className: "mt-0.5 block text-og-sm text-og-fg-muted", children: "Optional. Enables computer-use \u2014 the agent can move the pointer, type, and click on this machine's desktop. Leave off to let it only watch." })
|
|
1656
1999
|
] })
|
|
1657
2000
|
]
|
|
1658
2001
|
}
|
|
1659
|
-
) : /* @__PURE__ */
|
|
1660
|
-
/* @__PURE__ */
|
|
2002
|
+
) : /* @__PURE__ */ jsxs12("p", { className: "flex items-start gap-2 rounded-og-md border border-og-border bg-og-bg px-3 py-2 text-og-sm text-og-fg-muted", children: [
|
|
2003
|
+
/* @__PURE__ */ jsx12(CircleAlertIcon, { className: "mt-px size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
|
|
1661
2004
|
"This machine has no display, so screen control isn't available \u2014 files, terminal, and git only."
|
|
1662
2005
|
] }),
|
|
1663
|
-
/* @__PURE__ */
|
|
1664
|
-
/* @__PURE__ */
|
|
2006
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
2007
|
+
/* @__PURE__ */ jsx12(
|
|
1665
2008
|
"button",
|
|
1666
2009
|
{
|
|
1667
2010
|
type: "button",
|
|
@@ -1672,13 +2015,13 @@ function EnrollmentConsent({
|
|
|
1672
2015
|
children: "Cancel"
|
|
1673
2016
|
}
|
|
1674
2017
|
),
|
|
1675
|
-
/* @__PURE__ */
|
|
2018
|
+
/* @__PURE__ */ jsx12(
|
|
1676
2019
|
"button",
|
|
1677
2020
|
{
|
|
1678
2021
|
type: "button",
|
|
1679
2022
|
"data-approve": true,
|
|
1680
2023
|
disabled: busy,
|
|
1681
|
-
onClick: () => onApprove?.(allowScreenControl),
|
|
2024
|
+
onClick: () => onApprove?.(allowScreenControl, scope),
|
|
1682
2025
|
className: "flex-1 rounded-og-sm bg-og-status-failed px-3 py-2 text-og-sm font-semibold text-og-accent-fg transition-colors hover:opacity-90 disabled:opacity-50 pointer-coarse:min-h-11",
|
|
1683
2026
|
children: busy ? "Connecting\u2026" : "Grant full access"
|
|
1684
2027
|
}
|
|
@@ -1696,7 +2039,7 @@ function ConsentResult({
|
|
|
1696
2039
|
}) {
|
|
1697
2040
|
const ring = tone === "ok" ? "border-og-status-running/30" : tone === "danger" ? "border-og-status-failed/30" : "border-og-border";
|
|
1698
2041
|
const iconClass = tone === "ok" ? "text-og-status-running" : tone === "danger" ? "text-og-status-failed" : "text-og-fg-subtle";
|
|
1699
|
-
return /* @__PURE__ */
|
|
2042
|
+
return /* @__PURE__ */ jsxs12(
|
|
1700
2043
|
"div",
|
|
1701
2044
|
{
|
|
1702
2045
|
"data-enrollment-result": tone,
|
|
@@ -1706,33 +2049,33 @@ function ConsentResult({
|
|
|
1706
2049
|
className
|
|
1707
2050
|
),
|
|
1708
2051
|
children: [
|
|
1709
|
-
/* @__PURE__ */
|
|
2052
|
+
/* @__PURE__ */ jsx12(
|
|
1710
2053
|
"span",
|
|
1711
2054
|
{
|
|
1712
2055
|
className: cn(
|
|
1713
2056
|
"flex size-10 items-center justify-center rounded-full bg-og-surface-2",
|
|
1714
2057
|
iconClass
|
|
1715
2058
|
),
|
|
1716
|
-
children: /* @__PURE__ */
|
|
2059
|
+
children: /* @__PURE__ */ jsx12(LaptopIcon6, { className: "size-5", "aria-hidden": true })
|
|
1717
2060
|
}
|
|
1718
2061
|
),
|
|
1719
|
-
/* @__PURE__ */
|
|
1720
|
-
/* @__PURE__ */
|
|
2062
|
+
/* @__PURE__ */ jsx12("h1", { className: "text-og-md font-semibold text-og-fg", children: title }),
|
|
2063
|
+
/* @__PURE__ */ jsx12("p", { className: "max-w-sm text-og-base text-og-fg-muted", children: body })
|
|
1721
2064
|
]
|
|
1722
2065
|
}
|
|
1723
2066
|
);
|
|
1724
2067
|
}
|
|
1725
2068
|
|
|
1726
2069
|
// src/hooks/use-machines.ts
|
|
1727
|
-
import { useCallback as
|
|
2070
|
+
import { useCallback as useCallback3, useRef as useRef3, useState as useState6 } from "react";
|
|
1728
2071
|
|
|
1729
2072
|
// src/provider.tsx
|
|
1730
2073
|
import {
|
|
1731
2074
|
OpenGeniApiContractMismatchError,
|
|
1732
2075
|
OPENGENI_API_CONTRACT_REVISION
|
|
1733
2076
|
} from "@opengeni/sdk";
|
|
1734
|
-
import { useCallback, useEffect, useMemo, useRef as useRef2, useState as
|
|
1735
|
-
import { jsx as
|
|
2077
|
+
import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState4 } from "react";
|
|
2078
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1736
2079
|
var CONTRACT_RELOAD_STORAGE_PREFIX = "opengeni.reloadForApiContract:";
|
|
1737
2080
|
function OpenGeniProvider({
|
|
1738
2081
|
client,
|
|
@@ -1741,13 +2084,13 @@ function OpenGeniProvider({
|
|
|
1741
2084
|
onWorkspaceInteractionEvent,
|
|
1742
2085
|
children
|
|
1743
2086
|
}) {
|
|
1744
|
-
const [workspaceControlEvent, setWorkspaceControlEvent] =
|
|
2087
|
+
const [workspaceControlEvent, setWorkspaceControlEvent] = useState4(
|
|
1745
2088
|
null
|
|
1746
2089
|
);
|
|
1747
|
-
const [workspaceControlConnectionState, setWorkspaceControlConnectionState] =
|
|
1748
|
-
const [workspaceInteractionEvent, setWorkspaceInteractionEvent] =
|
|
1749
|
-
const [workspaceInteractionConnectionState, setWorkspaceInteractionConnectionState] =
|
|
1750
|
-
const [contractMismatch, setContractMismatch] =
|
|
2090
|
+
const [workspaceControlConnectionState, setWorkspaceControlConnectionState] = useState4("idle");
|
|
2091
|
+
const [workspaceInteractionEvent, setWorkspaceInteractionEvent] = useState4(null);
|
|
2092
|
+
const [workspaceInteractionConnectionState, setWorkspaceInteractionConnectionState] = useState4("idle");
|
|
2093
|
+
const [contractMismatch, setContractMismatch] = useState4(
|
|
1751
2094
|
null
|
|
1752
2095
|
);
|
|
1753
2096
|
const callbackRef = useRef2(onWorkspaceControlEvent);
|
|
@@ -1778,9 +2121,9 @@ function OpenGeniProvider({
|
|
|
1778
2121
|
}
|
|
1779
2122
|
}, [client]);
|
|
1780
2123
|
const registerSessionReconciler = useMemo(
|
|
1781
|
-
() => (sessionId, key,
|
|
2124
|
+
() => (sessionId, key, reconcile2) => {
|
|
1782
2125
|
const sessionReconcilers = reconcilersRef.current.get(sessionId) ?? /* @__PURE__ */ new Map();
|
|
1783
|
-
sessionReconcilers.set(key,
|
|
2126
|
+
sessionReconcilers.set(key, reconcile2);
|
|
1784
2127
|
reconcilersRef.current.set(sessionId, sessionReconcilers);
|
|
1785
2128
|
return () => {
|
|
1786
2129
|
const current = reconcilersRef.current.get(sessionId);
|
|
@@ -1798,7 +2141,7 @@ function OpenGeniProvider({
|
|
|
1798
2141
|
await withTimeout(verifyApiContract(), 1e4, "API contract reconciliation");
|
|
1799
2142
|
const callbacks = [...reconcilersRef.current.get(sessionId)?.values() ?? []];
|
|
1800
2143
|
await withTimeout(
|
|
1801
|
-
Promise.all(callbacks.map((
|
|
2144
|
+
Promise.all(callbacks.map((reconcile2) => reconcile2())).then(() => void 0),
|
|
1802
2145
|
15e3,
|
|
1803
2146
|
"session reconciliation"
|
|
1804
2147
|
);
|
|
@@ -1812,7 +2155,7 @@ function OpenGeniProvider({
|
|
|
1812
2155
|
},
|
|
1813
2156
|
[verifyApiContract]
|
|
1814
2157
|
);
|
|
1815
|
-
|
|
2158
|
+
useEffect2(() => {
|
|
1816
2159
|
if (!supportsWorkspaceLiveStream) return;
|
|
1817
2160
|
const openLiveStream = client.streamWorkspaceLiveEvents;
|
|
1818
2161
|
setWorkspaceControlEvent(null);
|
|
@@ -1882,7 +2225,7 @@ function OpenGeniProvider({
|
|
|
1882
2225
|
})();
|
|
1883
2226
|
return () => controller.abort();
|
|
1884
2227
|
}, [client, pageLive, supportsWorkspaceLiveStream, verifyApiContract, workspaceId]);
|
|
1885
|
-
|
|
2228
|
+
useEffect2(() => {
|
|
1886
2229
|
if (supportsWorkspaceLiveStream) return;
|
|
1887
2230
|
if (!pageLive) {
|
|
1888
2231
|
setWorkspaceControlConnectionState("idle");
|
|
@@ -1925,7 +2268,7 @@ function OpenGeniProvider({
|
|
|
1925
2268
|
})();
|
|
1926
2269
|
return () => controller.abort();
|
|
1927
2270
|
}, [client, pageLive, supportsWorkspaceLiveStream, verifyApiContract, workspaceId]);
|
|
1928
|
-
|
|
2271
|
+
useEffect2(() => {
|
|
1929
2272
|
if (supportsWorkspaceLiveStream) return;
|
|
1930
2273
|
setWorkspaceInteractionEvent(null);
|
|
1931
2274
|
if (!pageLive) {
|
|
@@ -1989,9 +2332,9 @@ function OpenGeniProvider({
|
|
|
1989
2332
|
reconcileSession
|
|
1990
2333
|
]
|
|
1991
2334
|
);
|
|
1992
|
-
return /* @__PURE__ */
|
|
2335
|
+
return /* @__PURE__ */ jsxs13(OpenGeniContext.Provider, { value, children: [
|
|
1993
2336
|
children,
|
|
1994
|
-
contractMismatch ? /* @__PURE__ */
|
|
2337
|
+
contractMismatch ? /* @__PURE__ */ jsx13(ApiContractMismatchScreen, { mismatch: contractMismatch }) : null
|
|
1995
2338
|
] });
|
|
1996
2339
|
}
|
|
1997
2340
|
function withTimeout(promise, timeoutMs, label) {
|
|
@@ -2009,23 +2352,23 @@ function withTimeout(promise, timeoutMs, label) {
|
|
|
2009
2352
|
});
|
|
2010
2353
|
}
|
|
2011
2354
|
function ApiContractMismatchScreen({ mismatch }) {
|
|
2012
|
-
return /* @__PURE__ */
|
|
2355
|
+
return /* @__PURE__ */ jsx13(
|
|
2013
2356
|
"div",
|
|
2014
2357
|
{
|
|
2015
2358
|
className: "og-root fixed inset-0 z-[2147483647] grid place-items-center bg-og-bg/95 p-6 backdrop-blur-sm",
|
|
2016
2359
|
role: "alert",
|
|
2017
2360
|
"aria-live": "assertive",
|
|
2018
2361
|
"data-opengeni-api-contract-mismatch": true,
|
|
2019
|
-
children: /* @__PURE__ */
|
|
2020
|
-
/* @__PURE__ */
|
|
2021
|
-
/* @__PURE__ */
|
|
2022
|
-
/* @__PURE__ */
|
|
2362
|
+
children: /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-md rounded-xl border border-og-border bg-og-surface p-6 shadow-2xl", children: [
|
|
2363
|
+
/* @__PURE__ */ jsx13("p", { className: "text-og-menu font-semibold text-og-fg", children: "OpenGeni updated" }),
|
|
2364
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-2 text-og-menu leading-6 text-og-muted", children: "This tab cannot safely continue with the new server version. Reload it before sending or controlling work." }),
|
|
2365
|
+
/* @__PURE__ */ jsxs13("p", { className: "mt-3 font-mono text-og-control text-og-subtle", children: [
|
|
2023
2366
|
"Client ",
|
|
2024
2367
|
mismatch.expected,
|
|
2025
2368
|
" \xB7 API ",
|
|
2026
2369
|
mismatch.actual
|
|
2027
2370
|
] }),
|
|
2028
|
-
/* @__PURE__ */
|
|
2371
|
+
/* @__PURE__ */ jsx13(
|
|
2029
2372
|
"button",
|
|
2030
2373
|
{
|
|
2031
2374
|
type: "button",
|
|
@@ -2046,8 +2389,205 @@ function reloadForContractMismatchOnce(mismatch) {
|
|
|
2046
2389
|
window.setTimeout(() => window.location.reload(), 150);
|
|
2047
2390
|
}
|
|
2048
2391
|
|
|
2392
|
+
// src/hooks/shared-machines-list.ts
|
|
2393
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useState as useState5 } from "react";
|
|
2394
|
+
var EMPTY_MACHINES = {
|
|
2395
|
+
activeSandboxId: null,
|
|
2396
|
+
activeEpoch: 0,
|
|
2397
|
+
machines: []
|
|
2398
|
+
};
|
|
2399
|
+
var shares = /* @__PURE__ */ new Map();
|
|
2400
|
+
function emit(share) {
|
|
2401
|
+
for (const subscriber of share.subscribers) {
|
|
2402
|
+
subscriber.onChange();
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
function effective(share) {
|
|
2406
|
+
let enabled = false;
|
|
2407
|
+
let pollIntervalMs;
|
|
2408
|
+
for (const subscriber of share.subscribers) {
|
|
2409
|
+
if (!subscriber.enabled || !subscriber.pageLive) continue;
|
|
2410
|
+
enabled = true;
|
|
2411
|
+
if (subscriber.pollIntervalMs !== void 0 && subscriber.pollIntervalMs > 0) {
|
|
2412
|
+
pollIntervalMs = pollIntervalMs === void 0 ? subscriber.pollIntervalMs : Math.min(pollIntervalMs, subscriber.pollIntervalMs);
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
return { enabled, pollIntervalMs };
|
|
2416
|
+
}
|
|
2417
|
+
function latestLoad(share) {
|
|
2418
|
+
let load = null;
|
|
2419
|
+
for (const subscriber of share.subscribers) {
|
|
2420
|
+
if (subscriber.enabled && subscriber.pageLive) load = subscriber.load;
|
|
2421
|
+
}
|
|
2422
|
+
return load;
|
|
2423
|
+
}
|
|
2424
|
+
function stopTimer(share) {
|
|
2425
|
+
if (share.timer !== null) {
|
|
2426
|
+
clearTimeout(share.timer);
|
|
2427
|
+
share.timer = null;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
function cancelDispose(share) {
|
|
2431
|
+
if (share.disposeTimer !== null) {
|
|
2432
|
+
clearTimeout(share.disposeTimer);
|
|
2433
|
+
share.disposeTimer = null;
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
function arm(share) {
|
|
2437
|
+
stopTimer(share);
|
|
2438
|
+
const { enabled, pollIntervalMs } = effective(share);
|
|
2439
|
+
if (!enabled || pollIntervalMs === void 0) return;
|
|
2440
|
+
share.timer = setTimeout(() => {
|
|
2441
|
+
share.timer = null;
|
|
2442
|
+
void run(share).finally(() => arm(share));
|
|
2443
|
+
}, pollIntervalMs);
|
|
2444
|
+
}
|
|
2445
|
+
async function runFresh(share) {
|
|
2446
|
+
const load = latestLoad(share);
|
|
2447
|
+
if (!load) return;
|
|
2448
|
+
const ticket = ++share.generation;
|
|
2449
|
+
const abort = new AbortController();
|
|
2450
|
+
share.abort = abort;
|
|
2451
|
+
try {
|
|
2452
|
+
const data = await load(abort.signal);
|
|
2453
|
+
if (ticket !== share.generation || abort.signal.aborted) return;
|
|
2454
|
+
share.snapshot = { data, loading: false, error: null };
|
|
2455
|
+
emit(share);
|
|
2456
|
+
} catch (cause) {
|
|
2457
|
+
if (ticket !== share.generation || abort.signal.aborted) return;
|
|
2458
|
+
share.snapshot = {
|
|
2459
|
+
data: share.snapshot.data,
|
|
2460
|
+
loading: false,
|
|
2461
|
+
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
2462
|
+
};
|
|
2463
|
+
emit(share);
|
|
2464
|
+
} finally {
|
|
2465
|
+
if (share.abort === abort) share.abort = null;
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
function run(share, force = false) {
|
|
2469
|
+
if (!force && share.inFlight) return share.inFlight;
|
|
2470
|
+
if (force && share.inFlight) {
|
|
2471
|
+
if (share.trailing) return share.trailing;
|
|
2472
|
+
let trailing;
|
|
2473
|
+
trailing = share.inFlight.then(async () => {
|
|
2474
|
+
if (!effective(share).enabled) return;
|
|
2475
|
+
await run(share);
|
|
2476
|
+
}).finally(() => {
|
|
2477
|
+
if (share.trailing === trailing) share.trailing = null;
|
|
2478
|
+
});
|
|
2479
|
+
share.trailing = trailing;
|
|
2480
|
+
return trailing;
|
|
2481
|
+
}
|
|
2482
|
+
let promise;
|
|
2483
|
+
promise = runFresh(share).finally(() => {
|
|
2484
|
+
if (share.inFlight === promise) share.inFlight = null;
|
|
2485
|
+
});
|
|
2486
|
+
share.inFlight = promise;
|
|
2487
|
+
return promise;
|
|
2488
|
+
}
|
|
2489
|
+
function reconcile(share) {
|
|
2490
|
+
const { enabled } = effective(share);
|
|
2491
|
+
if (!enabled) {
|
|
2492
|
+
share.generation += 1;
|
|
2493
|
+
share.abort?.abort();
|
|
2494
|
+
share.abort = null;
|
|
2495
|
+
share.inFlight = null;
|
|
2496
|
+
stopTimer(share);
|
|
2497
|
+
if (share.snapshot.loading) {
|
|
2498
|
+
share.snapshot = { ...share.snapshot, loading: false };
|
|
2499
|
+
emit(share);
|
|
2500
|
+
}
|
|
2501
|
+
return;
|
|
2502
|
+
}
|
|
2503
|
+
if (share.snapshot.data !== null || share.snapshot.error) {
|
|
2504
|
+
arm(share);
|
|
2505
|
+
return;
|
|
2506
|
+
}
|
|
2507
|
+
share.snapshot = { ...share.snapshot, loading: true };
|
|
2508
|
+
emit(share);
|
|
2509
|
+
void run(share).finally(() => arm(share));
|
|
2510
|
+
}
|
|
2511
|
+
function getOrCreate(shareKey) {
|
|
2512
|
+
const existing = shares.get(shareKey);
|
|
2513
|
+
if (existing) {
|
|
2514
|
+
cancelDispose(existing);
|
|
2515
|
+
return existing;
|
|
2516
|
+
}
|
|
2517
|
+
const created = {
|
|
2518
|
+
snapshot: { data: null, loading: true, error: null },
|
|
2519
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
2520
|
+
timer: null,
|
|
2521
|
+
disposeTimer: null,
|
|
2522
|
+
abort: null,
|
|
2523
|
+
inFlight: null,
|
|
2524
|
+
trailing: null,
|
|
2525
|
+
generation: 0
|
|
2526
|
+
};
|
|
2527
|
+
shares.set(shareKey, created);
|
|
2528
|
+
return created;
|
|
2529
|
+
}
|
|
2530
|
+
async function refreshSharedMachinesList(shareKey) {
|
|
2531
|
+
const share = shares.get(shareKey);
|
|
2532
|
+
if (!share) return;
|
|
2533
|
+
await run(share, true);
|
|
2534
|
+
}
|
|
2535
|
+
function useSharedMachinesList(shareKey, load, options = {}) {
|
|
2536
|
+
const enabled = options.enabled ?? true;
|
|
2537
|
+
const pageLive = usePageLiveActivity();
|
|
2538
|
+
const [, setRevision] = useState5(0);
|
|
2539
|
+
const live = shares.get(shareKey)?.snapshot;
|
|
2540
|
+
const view = live ?? { data: null, loading: enabled && pageLive, error: null };
|
|
2541
|
+
useEffect3(() => {
|
|
2542
|
+
const share = getOrCreate(shareKey);
|
|
2543
|
+
const subscriber = {
|
|
2544
|
+
load,
|
|
2545
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
2546
|
+
enabled,
|
|
2547
|
+
pageLive,
|
|
2548
|
+
onChange: () => setRevision((revision) => revision + 1)
|
|
2549
|
+
};
|
|
2550
|
+
share.subscribers.add(subscriber);
|
|
2551
|
+
setRevision((revision) => revision + 1);
|
|
2552
|
+
reconcile(share);
|
|
2553
|
+
return () => {
|
|
2554
|
+
share.subscribers.delete(subscriber);
|
|
2555
|
+
if (share.subscribers.size > 0) {
|
|
2556
|
+
reconcile(share);
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
share.generation += 1;
|
|
2560
|
+
share.abort?.abort();
|
|
2561
|
+
share.abort = null;
|
|
2562
|
+
share.inFlight = null;
|
|
2563
|
+
share.trailing = null;
|
|
2564
|
+
stopTimer(share);
|
|
2565
|
+
cancelDispose(share);
|
|
2566
|
+
share.disposeTimer = setTimeout(() => {
|
|
2567
|
+
share.disposeTimer = null;
|
|
2568
|
+
if (share.subscribers.size === 0 && shares.get(shareKey) === share) {
|
|
2569
|
+
shares.delete(shareKey);
|
|
2570
|
+
}
|
|
2571
|
+
}, 0);
|
|
2572
|
+
};
|
|
2573
|
+
}, [shareKey, load, options.pollIntervalMs, enabled, pageLive]);
|
|
2574
|
+
const refresh = useCallback2(() => refreshSharedMachinesList(shareKey), [shareKey]);
|
|
2575
|
+
return { ...view, refresh };
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2049
2578
|
// src/hooks/use-machines.ts
|
|
2050
|
-
var
|
|
2579
|
+
var MACHINES_DASHBOARD_POLL_MS = 1e4;
|
|
2580
|
+
var MACHINES_SESSION_POLL_MS = 15e3;
|
|
2581
|
+
var MACHINES_COMPOSER_POLL_MS = 3e4;
|
|
2582
|
+
var machinesClientIds = /* @__PURE__ */ new WeakMap();
|
|
2583
|
+
var nextMachinesClientId = 1;
|
|
2584
|
+
function machinesClientId(client) {
|
|
2585
|
+
const existing = machinesClientIds.get(client);
|
|
2586
|
+
if (existing !== void 0) return existing;
|
|
2587
|
+
const id = nextMachinesClientId++;
|
|
2588
|
+
machinesClientIds.set(client, id);
|
|
2589
|
+
return id;
|
|
2590
|
+
}
|
|
2051
2591
|
function swapFailureMessage(result) {
|
|
2052
2592
|
if (result.reason?.trim()) return result.reason;
|
|
2053
2593
|
switch (result.code) {
|
|
@@ -2069,10 +2609,10 @@ function useMachines(options = {}) {
|
|
|
2069
2609
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2070
2610
|
const machinesClient = options.machinesClient ?? client;
|
|
2071
2611
|
const sessionId = options.sessionId;
|
|
2072
|
-
const identityKey = `${workspaceId}\0${sessionId ?? ""}`;
|
|
2612
|
+
const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${machinesClientId(machinesClient)}`;
|
|
2073
2613
|
const identityRef = useRef3(identityKey);
|
|
2074
2614
|
identityRef.current = identityKey;
|
|
2075
|
-
const load =
|
|
2615
|
+
const load = useCallback3(
|
|
2076
2616
|
async (signal) => {
|
|
2077
2617
|
return await machinesClient.listMachines(workspaceId, {
|
|
2078
2618
|
...sessionId ? { sessionId } : {},
|
|
@@ -2086,26 +2626,32 @@ function useMachines(options = {}) {
|
|
|
2086
2626
|
loading,
|
|
2087
2627
|
error,
|
|
2088
2628
|
refresh
|
|
2089
|
-
} =
|
|
2629
|
+
} = useSharedMachinesList(identityKey, load, {
|
|
2090
2630
|
pollIntervalMs: options.pollIntervalMs,
|
|
2091
2631
|
enabled: options.enabled
|
|
2092
2632
|
});
|
|
2093
|
-
const { run, mutating, mutationError, clearMutationError } = useMutationRunner(identityKey);
|
|
2094
|
-
const [attachState, setAttachState] =
|
|
2633
|
+
const { run: run2, mutating, mutationError, clearMutationError } = useMutationRunner(identityKey);
|
|
2634
|
+
const [attachState, setAttachState] = useState6(() => ({ identity: identityKey, sandboxId: null }));
|
|
2095
2635
|
const attachingSandboxId = attachState.identity === identityKey ? attachState.sandboxId : null;
|
|
2096
|
-
const [removeState, setRemoveState] =
|
|
2636
|
+
const [removeState, setRemoveState] = useState6(() => ({ identity: identityKey, enrollmentId: null }));
|
|
2097
2637
|
const removingEnrollmentId = removeState.identity === identityKey ? removeState.enrollmentId : null;
|
|
2098
|
-
const
|
|
2638
|
+
const [updateState, setUpdateState] = useState6(() => ({ identity: identityKey, enrollmentId: null }));
|
|
2639
|
+
const updatingEnrollmentId = updateState.identity === identityKey ? updateState.enrollmentId : null;
|
|
2640
|
+
const [operationPolicyState, setOperationPolicyState] = useState6(() => ({ identity: identityKey, enrollmentId: null }));
|
|
2641
|
+
const updatingOperationPolicyEnrollmentId = operationPolicyState.identity === identityKey ? operationPolicyState.enrollmentId : null;
|
|
2642
|
+
const data = loadedData ?? EMPTY_MACHINES;
|
|
2099
2643
|
const canAttach = sessionId !== void 0 && (typeof machinesClient.attachMachine === "function" || typeof machinesClient.swapActiveSandbox === "function");
|
|
2100
2644
|
const canRemove = typeof machinesClient.removeEnrollment === "function";
|
|
2101
|
-
const
|
|
2645
|
+
const canUpdateAgent = typeof machinesClient.updateMachineAgent === "function";
|
|
2646
|
+
const canUpdateOperationPolicy = typeof machinesClient.updateMachineOperationPolicy === "function";
|
|
2647
|
+
const attach = useCallback3(
|
|
2102
2648
|
async (sandboxId) => {
|
|
2103
2649
|
if (sessionId === void 0) return false;
|
|
2104
2650
|
const runSwap = machinesClient.attachMachine ? () => machinesClient.attachMachine(workspaceId, sessionId, sandboxId) : machinesClient.swapActiveSandbox ? () => machinesClient.swapActiveSandbox(workspaceId, sessionId, { target: sandboxId }) : null;
|
|
2105
2651
|
if (!runSwap) return false;
|
|
2106
2652
|
const ownedIdentity = identityKey;
|
|
2107
2653
|
setAttachState({ identity: ownedIdentity, sandboxId });
|
|
2108
|
-
const result = await
|
|
2654
|
+
const result = await run2(async () => {
|
|
2109
2655
|
const response = await runSwap();
|
|
2110
2656
|
if (response && typeof response === "object" && "swapped" in response && response.swapped === false) {
|
|
2111
2657
|
throw new Error(swapFailureMessage(response));
|
|
@@ -2118,21 +2664,21 @@ function useMachines(options = {}) {
|
|
|
2118
2664
|
}
|
|
2119
2665
|
return result === true;
|
|
2120
2666
|
},
|
|
2121
|
-
[machinesClient, workspaceId, sessionId, identityKey,
|
|
2667
|
+
[machinesClient, workspaceId, sessionId, identityKey, run2, refresh]
|
|
2122
2668
|
);
|
|
2123
|
-
const fetchSeries =
|
|
2669
|
+
const fetchSeries = useCallback3(
|
|
2124
2670
|
async (enrollmentId, window2 = "1h") => {
|
|
2125
2671
|
if (!machinesClient.machineMetricsSeries) return [];
|
|
2126
2672
|
return await machinesClient.machineMetricsSeries(workspaceId, enrollmentId, { window: window2 });
|
|
2127
2673
|
},
|
|
2128
2674
|
[machinesClient, workspaceId]
|
|
2129
2675
|
);
|
|
2130
|
-
const remove =
|
|
2676
|
+
const remove = useCallback3(
|
|
2131
2677
|
async (enrollmentId, request = {}) => {
|
|
2132
2678
|
if (!machinesClient.removeEnrollment) return null;
|
|
2133
2679
|
const ownedIdentity = identityKey;
|
|
2134
2680
|
setRemoveState({ identity: ownedIdentity, enrollmentId });
|
|
2135
|
-
const result = await
|
|
2681
|
+
const result = await run2(
|
|
2136
2682
|
() => machinesClient.removeEnrollment(workspaceId, enrollmentId, request)
|
|
2137
2683
|
);
|
|
2138
2684
|
if (identityRef.current === ownedIdentity) {
|
|
@@ -2143,7 +2689,37 @@ function useMachines(options = {}) {
|
|
|
2143
2689
|
}
|
|
2144
2690
|
return result;
|
|
2145
2691
|
},
|
|
2146
|
-
[machinesClient, workspaceId, identityKey,
|
|
2692
|
+
[machinesClient, workspaceId, identityKey, run2, refresh]
|
|
2693
|
+
);
|
|
2694
|
+
const updateAgent = useCallback3(
|
|
2695
|
+
async (enrollmentId) => {
|
|
2696
|
+
if (!machinesClient.updateMachineAgent) return null;
|
|
2697
|
+
const ownedIdentity = identityKey;
|
|
2698
|
+
setUpdateState({ identity: ownedIdentity, enrollmentId });
|
|
2699
|
+
const result = await run2(() => machinesClient.updateMachineAgent(workspaceId, enrollmentId));
|
|
2700
|
+
if (identityRef.current === ownedIdentity) {
|
|
2701
|
+
setUpdateState({ identity: ownedIdentity, enrollmentId: null });
|
|
2702
|
+
await refresh();
|
|
2703
|
+
}
|
|
2704
|
+
return result;
|
|
2705
|
+
},
|
|
2706
|
+
[machinesClient, workspaceId, identityKey, run2, refresh]
|
|
2707
|
+
);
|
|
2708
|
+
const updateOperationPolicy = useCallback3(
|
|
2709
|
+
async (enrollmentId, request) => {
|
|
2710
|
+
if (!machinesClient.updateMachineOperationPolicy) return null;
|
|
2711
|
+
const ownedIdentity = identityKey;
|
|
2712
|
+
setOperationPolicyState({ identity: ownedIdentity, enrollmentId });
|
|
2713
|
+
const result = await run2(
|
|
2714
|
+
() => machinesClient.updateMachineOperationPolicy(workspaceId, enrollmentId, request)
|
|
2715
|
+
);
|
|
2716
|
+
if (identityRef.current === ownedIdentity) {
|
|
2717
|
+
setOperationPolicyState({ identity: ownedIdentity, enrollmentId: null });
|
|
2718
|
+
if (result) await refresh();
|
|
2719
|
+
}
|
|
2720
|
+
return result;
|
|
2721
|
+
},
|
|
2722
|
+
[machinesClient, workspaceId, identityKey, run2, refresh]
|
|
2147
2723
|
);
|
|
2148
2724
|
return {
|
|
2149
2725
|
machines: data.machines,
|
|
@@ -2160,6 +2736,12 @@ function useMachines(options = {}) {
|
|
|
2160
2736
|
remove,
|
|
2161
2737
|
canRemove,
|
|
2162
2738
|
removingEnrollmentId,
|
|
2739
|
+
updateAgent,
|
|
2740
|
+
canUpdateAgent,
|
|
2741
|
+
updatingEnrollmentId,
|
|
2742
|
+
updateOperationPolicy,
|
|
2743
|
+
canUpdateOperationPolicy,
|
|
2744
|
+
updatingOperationPolicyEnrollmentId,
|
|
2163
2745
|
mutationError,
|
|
2164
2746
|
clearMutationError
|
|
2165
2747
|
};
|
|
@@ -2168,6 +2750,9 @@ function useMachines(options = {}) {
|
|
|
2168
2750
|
export {
|
|
2169
2751
|
OpenGeniProvider,
|
|
2170
2752
|
connectionStatusForState,
|
|
2753
|
+
MACHINES_DASHBOARD_POLL_MS,
|
|
2754
|
+
MACHINES_SESSION_POLL_MS,
|
|
2755
|
+
MACHINES_COMPOSER_POLL_MS,
|
|
2171
2756
|
useMachines,
|
|
2172
2757
|
CONNECTION_STATUS_META,
|
|
2173
2758
|
MACHINE_STATE_BADGE_META,
|
|
@@ -2186,6 +2771,7 @@ export {
|
|
|
2186
2771
|
WINDOW_LABEL,
|
|
2187
2772
|
METRICS,
|
|
2188
2773
|
pointsFor,
|
|
2774
|
+
MachineOperationPolicyEditor,
|
|
2189
2775
|
MachineDetail,
|
|
2190
2776
|
MachinesDashboard,
|
|
2191
2777
|
MachineDockBar,
|
|
@@ -2193,4 +2779,4 @@ export {
|
|
|
2193
2779
|
EnrollmentDeviceFlow,
|
|
2194
2780
|
EnrollmentConsent
|
|
2195
2781
|
};
|
|
2196
|
-
//# sourceMappingURL=chunk-
|
|
2782
|
+
//# sourceMappingURL=chunk-XXWH2JLC.js.map
|