@opengeni/react 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-DEW2ZNF2.js → chunk-5C7RGAWA.js} +70 -37
- package/dist/chunk-5C7RGAWA.js.map +1 -0
- package/dist/index.d.ts +27 -5
- package/dist/index.js +949 -616
- package/dist/index.js.map +1 -1
- package/dist/{machines-BD6h9P_s.d.ts → machines-Bv9tG7qZ.d.ts} +1 -1
- package/dist/machines.d.ts +1 -1
- package/dist/machines.js +1 -1
- package/package.json +2 -2
- package/src/components/chat-composer.tsx +127 -60
- package/src/components/code-editor.tsx +15 -15
- package/src/components/desktop-viewer.tsx +40 -36
- package/src/components/diff-view.tsx +22 -22
- package/src/components/enrollment-consent.tsx +13 -13
- package/src/components/file-browser.tsx +74 -67
- package/src/components/fleet-tile.tsx +3 -3
- package/src/components/machine-card.tsx +6 -6
- package/src/components/machine-status-pill.tsx +3 -3
- package/src/components/machines-dashboard.tsx +28 -14
- package/src/components/markdown.tsx +6 -6
- package/src/components/message-timeline.tsx +70 -2
- package/src/components/pierre-diff.tsx +9 -10
- package/src/components/pierre-file.tsx +8 -8
- package/src/components/sandbox-files.tsx +37 -40
- package/src/components/sandbox-terminal.tsx +9 -11
- package/src/components/session-status.tsx +2 -2
- package/src/components/workspace-dock.tsx +153 -49
- package/src/hooks/use-file-attachments.ts +45 -15
- package/src/index.ts +2 -2
- package/src/lib/format.ts +32 -0
- package/src/lib/xterm-theme.ts +8 -11
- package/src/timeline/activity-rail.tsx +1 -1
- package/src/timeline/parsers.ts +104 -0
- package/src/timeline/projection.ts +4 -2
- package/src/timeline/screenshot-lightbox.tsx +1 -1
- package/src/timeline/shared.tsx +4 -1
- package/src/timeline/tool-diff.tsx +1 -1
- package/src/timeline/tool-renderers.tsx +46 -7
- package/src/timeline/turn-summary.tsx +21 -3
- package/styles/tokens.css +8 -0
- package/dist/chunk-DEW2ZNF2.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
connectionStatusForState,
|
|
17
17
|
formatBytes,
|
|
18
18
|
formatRelativeTime,
|
|
19
|
+
humanizeFailureReason,
|
|
19
20
|
stringifyPayload,
|
|
20
21
|
truncate,
|
|
21
22
|
tryParseJson,
|
|
@@ -26,7 +27,7 @@ import {
|
|
|
26
27
|
useOpenGeniClient,
|
|
27
28
|
usePolledValue,
|
|
28
29
|
useSessionEventTrigger
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-5C7RGAWA.js";
|
|
30
31
|
|
|
31
32
|
// src/hooks/use-session.ts
|
|
32
33
|
import { useCallback, useState } from "react";
|
|
@@ -732,7 +733,7 @@ function failureMessage(payload) {
|
|
|
732
733
|
for (const key of ["error", "message"]) {
|
|
733
734
|
const value = payload[key];
|
|
734
735
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
735
|
-
return value;
|
|
736
|
+
return humanizeFailureReason(value);
|
|
736
737
|
}
|
|
737
738
|
}
|
|
738
739
|
return null;
|
|
@@ -1028,6 +1029,88 @@ function unwrapMcpOutput(output) {
|
|
|
1028
1029
|
}
|
|
1029
1030
|
return { text: typeof output === "string" ? output : output == null ? "" : JSON.stringify(output), isError: false };
|
|
1030
1031
|
}
|
|
1032
|
+
function screenshotDataUrl(out) {
|
|
1033
|
+
if (typeof out === "string") {
|
|
1034
|
+
if (out.startsWith("data:image")) {
|
|
1035
|
+
return out;
|
|
1036
|
+
}
|
|
1037
|
+
if (out.startsWith("{") || out.startsWith("[")) {
|
|
1038
|
+
const parsed = tryParseJson(out);
|
|
1039
|
+
if (parsed !== void 0 && parsed !== out) {
|
|
1040
|
+
return screenshotDataUrl(parsed);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return null;
|
|
1044
|
+
}
|
|
1045
|
+
if (Array.isArray(out)) {
|
|
1046
|
+
for (const entry of out) {
|
|
1047
|
+
const url = screenshotDataUrl(entry);
|
|
1048
|
+
if (url) {
|
|
1049
|
+
return url;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
return null;
|
|
1053
|
+
}
|
|
1054
|
+
if (out === null || typeof out !== "object") {
|
|
1055
|
+
return null;
|
|
1056
|
+
}
|
|
1057
|
+
const record = out;
|
|
1058
|
+
const imageUrl = record.image_url ?? record.imageUrl;
|
|
1059
|
+
if (typeof imageUrl === "string" && imageUrl.startsWith("data:image")) {
|
|
1060
|
+
return imageUrl;
|
|
1061
|
+
}
|
|
1062
|
+
if (imageUrl && typeof imageUrl === "object") {
|
|
1063
|
+
const url = imageUrl.url;
|
|
1064
|
+
if (typeof url === "string" && url.startsWith("data:image")) {
|
|
1065
|
+
return url;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
const image = record.image;
|
|
1069
|
+
if (image && typeof image === "object") {
|
|
1070
|
+
const mediaType = typeof image.mediaType === "string" ? image.mediaType : "image/png";
|
|
1071
|
+
const base64 = bytesToBase64(image.data);
|
|
1072
|
+
if (base64) {
|
|
1073
|
+
return `data:${mediaType};base64,${base64}`;
|
|
1074
|
+
}
|
|
1075
|
+
if (typeof image.data === "string" && image.data.length > 0) {
|
|
1076
|
+
return `data:${mediaType};base64,${image.data}`;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
1081
|
+
function bytesToBase64(data) {
|
|
1082
|
+
const isByte = (n) => typeof n === "number" && Number.isInteger(n) && n >= 0 && n <= 255;
|
|
1083
|
+
let bytes = null;
|
|
1084
|
+
if (Array.isArray(data) && data.every(isByte)) {
|
|
1085
|
+
bytes = data;
|
|
1086
|
+
} else if (data && typeof data === "object") {
|
|
1087
|
+
const record = data;
|
|
1088
|
+
if (record.type === "Buffer" && Array.isArray(record.data) && record.data.every(isByte)) {
|
|
1089
|
+
bytes = record.data;
|
|
1090
|
+
} else {
|
|
1091
|
+
const keys = Object.keys(record);
|
|
1092
|
+
if (keys.length > 0 && keys.every((key) => /^\d+$/.test(key))) {
|
|
1093
|
+
const values = keys.sort((a, b) => Number(a) - Number(b)).map((key) => record[key]);
|
|
1094
|
+
if (values.every(isByte)) {
|
|
1095
|
+
bytes = values;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
if (!bytes || bytes.length === 0) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
try {
|
|
1104
|
+
let binary = "";
|
|
1105
|
+
const CHUNK = 32768;
|
|
1106
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
1107
|
+
binary += String.fromCharCode(...bytes.slice(i, i + CHUNK));
|
|
1108
|
+
}
|
|
1109
|
+
return typeof btoa === "function" ? btoa(binary) : Buffer.from(binary, "binary").toString("base64");
|
|
1110
|
+
} catch {
|
|
1111
|
+
return null;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1031
1114
|
|
|
1032
1115
|
// src/timeline/shared.tsx
|
|
1033
1116
|
import { CameraIcon, CameraOffIcon, ChevronRightIcon } from "lucide-react";
|
|
@@ -1131,7 +1214,7 @@ function LightboxRoot({ children }) {
|
|
|
1131
1214
|
}
|
|
1132
1215
|
)
|
|
1133
1216
|
] }),
|
|
1134
|
-
state.caption ? /* @__PURE__ */ jsx2("figcaption", { className: "max-w-2xl text-center font-og-mono text-og-xs text-white/55", children: state.caption }) : /* @__PURE__ */ jsx2("figcaption", { className: "font-og-mono text-
|
|
1217
|
+
state.caption ? /* @__PURE__ */ jsx2("figcaption", { className: "max-w-2xl text-center font-og-mono text-og-xs text-white/55", children: state.caption }) : /* @__PURE__ */ jsx2("figcaption", { className: "font-og-mono text-og-xs uppercase tracking-[0.1em] text-white/35", children: "Esc or click outside to close" })
|
|
1135
1218
|
] })
|
|
1136
1219
|
]
|
|
1137
1220
|
}
|
|
@@ -1172,7 +1255,10 @@ function ActivityDisclosure({
|
|
|
1172
1255
|
const previewVisible = preview != null && !open;
|
|
1173
1256
|
const rowClass = cn(
|
|
1174
1257
|
"group/disclosure flex w-full min-w-0 items-center gap-2 rounded-og-sm px-1.5 py-1.5 text-left text-og-base",
|
|
1175
|
-
"text-og-fg-muted transition-colors duration-150"
|
|
1258
|
+
"text-og-fg-muted transition-colors duration-150",
|
|
1259
|
+
// A tool row is a touch target on coarse pointers: grow its padding so the
|
|
1260
|
+
// hit area clears the 40px minimum without loosening the dense desktop rail.
|
|
1261
|
+
"pointer-coarse:py-2.5"
|
|
1176
1262
|
);
|
|
1177
1263
|
const inner = /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1178
1264
|
hasBody ? /* @__PURE__ */ jsx3(ChevronRightIcon, { className: "size-3.5 shrink-0 text-og-fg-subtle transition-transform duration-150 ease-og-in-out group-data-[state=open]/disclosure:rotate-90" }) : /* @__PURE__ */ jsx3("span", { className: "size-3.5 shrink-0" }),
|
|
@@ -1247,7 +1333,7 @@ function TermBlock({
|
|
|
1247
1333
|
const shown = full || !big ? output : lines.slice(-tailLines).join("\n");
|
|
1248
1334
|
const showMore = big && !full;
|
|
1249
1335
|
const showHeader = command != null || workdir != null;
|
|
1250
|
-
return /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-og-sm border border-og-border bg-og-bg/70", children: [
|
|
1336
|
+
return /* @__PURE__ */ jsxs2("div", { className: "min-w-0 overflow-hidden rounded-og-sm border border-og-border bg-og-bg/70", children: [
|
|
1251
1337
|
showHeader ? /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 border-b border-og-border/70 px-2.5 py-1.5", children: [
|
|
1252
1338
|
/* @__PURE__ */ jsx3("span", { className: "select-none text-og-status-idle", children: "$" }),
|
|
1253
1339
|
command != null ? /* @__PURE__ */ jsx3("span", { className: "min-w-0 flex-1 truncate font-og-mono text-og-sm text-og-fg-muted", children: command }) : /* @__PURE__ */ jsx3("span", { className: "flex-1" }),
|
|
@@ -1412,7 +1498,7 @@ function DiffView({
|
|
|
1412
1498
|
return /* @__PURE__ */ jsx4("div", { className, children: fallback });
|
|
1413
1499
|
}
|
|
1414
1500
|
if (diff.length === 0) {
|
|
1415
|
-
return /* @__PURE__ */ jsx4("div", { className: cn("p-3 text-
|
|
1501
|
+
return /* @__PURE__ */ jsx4("div", { className: cn("p-3 text-og-sm text-og-fg-subtle", className), children: emptyState ?? (isRepo ? "No changes" : "No repository mounted") });
|
|
1416
1502
|
}
|
|
1417
1503
|
return /* @__PURE__ */ jsx4("div", { className: cn("min-w-0 overflow-auto", className), "data-opengeni-diff": true, children: diff.map((file) => /* @__PURE__ */ jsx4(
|
|
1418
1504
|
FileDiffBlock,
|
|
@@ -1431,24 +1517,24 @@ function FileDiffBlock({
|
|
|
1431
1517
|
theme,
|
|
1432
1518
|
onSelect
|
|
1433
1519
|
}) {
|
|
1434
|
-
return /* @__PURE__ */ jsxs3("section", { className: "mb-2 overflow-hidden rounded border border-
|
|
1520
|
+
return /* @__PURE__ */ jsxs3("section", { className: "mb-2 overflow-hidden rounded-og-sm border border-og-border", children: [
|
|
1435
1521
|
/* @__PURE__ */ jsxs3(
|
|
1436
1522
|
"header",
|
|
1437
1523
|
{
|
|
1438
1524
|
className: cn(
|
|
1439
|
-
"flex items-center justify-between gap-2 border-b border-
|
|
1525
|
+
"flex items-center justify-between gap-2 border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-sm",
|
|
1440
1526
|
onSelect && "cursor-pointer"
|
|
1441
1527
|
),
|
|
1442
1528
|
onClick: onSelect,
|
|
1443
1529
|
children: [
|
|
1444
|
-
/* @__PURE__ */ jsx4("span", { className: "truncate font-mono", children: file.oldPath && file.oldPath !== file.path ? `${file.oldPath} \u2192 ${file.path}` : file.path }),
|
|
1530
|
+
/* @__PURE__ */ jsx4("span", { className: "truncate font-og-mono", children: file.oldPath && file.oldPath !== file.path ? `${file.oldPath} \u2192 ${file.path}` : file.path }),
|
|
1445
1531
|
/* @__PURE__ */ jsxs3("span", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1446
|
-
/* @__PURE__ */ jsx4("span", { className: "rounded bg-
|
|
1447
|
-
/* @__PURE__ */ jsxs3("span", { className: "text-
|
|
1532
|
+
/* @__PURE__ */ jsx4("span", { className: "rounded-og-xs bg-og-bg px-1 py-0.5 text-og-xs text-og-fg-subtle", children: STATUS_LABEL[file.status] }),
|
|
1533
|
+
/* @__PURE__ */ jsxs3("span", { className: "text-og-status-idle", children: [
|
|
1448
1534
|
"+",
|
|
1449
1535
|
file.additions
|
|
1450
1536
|
] }),
|
|
1451
|
-
/* @__PURE__ */ jsxs3("span", { className: "text-
|
|
1537
|
+
/* @__PURE__ */ jsxs3("span", { className: "text-og-status-failed", children: [
|
|
1452
1538
|
"\u2212",
|
|
1453
1539
|
file.deletions
|
|
1454
1540
|
] })
|
|
@@ -1456,12 +1542,12 @@ function FileDiffBlock({
|
|
|
1456
1542
|
]
|
|
1457
1543
|
}
|
|
1458
1544
|
),
|
|
1459
|
-
file.isBinary ? /* @__PURE__ */ jsx4("div", { className: "px-2 py-3 text-
|
|
1545
|
+
file.isBinary ? /* @__PURE__ */ jsx4("div", { className: "px-2 py-3 text-og-sm text-og-fg-subtle", children: "Binary file not shown" }) : file.truncated ? /* @__PURE__ */ jsx4("div", { className: "px-2 py-3 text-og-sm text-og-fg-subtle", children: "Diff too large \u2014 truncated" }) : layout === "split" ? /* @__PURE__ */ jsx4(SplitHunks, { file, theme }) : /* @__PURE__ */ jsx4(UnifiedHunks, { file, theme })
|
|
1460
1546
|
] });
|
|
1461
1547
|
}
|
|
1462
1548
|
function lineBg(type, theme) {
|
|
1463
|
-
if (type === "add") return theme?.addBackground ?? "var(--color-diff-add
|
|
1464
|
-
if (type === "del") return theme?.delBackground ?? "var(--color-diff-del
|
|
1549
|
+
if (type === "add") return theme?.addBackground ?? "var(--og-color-diff-add-bg)";
|
|
1550
|
+
if (type === "del") return theme?.delBackground ?? "var(--og-color-diff-del-bg)";
|
|
1465
1551
|
if (type === "meta") return void 0;
|
|
1466
1552
|
return theme?.contextBackground;
|
|
1467
1553
|
}
|
|
@@ -1471,11 +1557,11 @@ function marker(type) {
|
|
|
1471
1557
|
return " ";
|
|
1472
1558
|
}
|
|
1473
1559
|
function UnifiedHunks({ file, theme }) {
|
|
1474
|
-
return /* @__PURE__ */ jsx4("div", { className: "font-mono text-
|
|
1560
|
+
return /* @__PURE__ */ jsx4("div", { className: "font-og-mono text-og-xs", children: file.hunks.map((hunk, hi) => /* @__PURE__ */ jsxs3("div", { children: [
|
|
1475
1561
|
/* @__PURE__ */ jsx4(
|
|
1476
1562
|
"div",
|
|
1477
1563
|
{
|
|
1478
|
-
className: "px-2 py-0.5 text-
|
|
1564
|
+
className: "px-2 py-0.5 text-og-accent",
|
|
1479
1565
|
style: { color: theme?.metaForeground },
|
|
1480
1566
|
children: hunk.header
|
|
1481
1567
|
}
|
|
@@ -1486,9 +1572,9 @@ function UnifiedHunks({ file, theme }) {
|
|
|
1486
1572
|
className: "flex",
|
|
1487
1573
|
style: { backgroundColor: lineBg(line.type, theme) },
|
|
1488
1574
|
children: [
|
|
1489
|
-
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-
|
|
1490
|
-
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-
|
|
1491
|
-
/* @__PURE__ */ jsx4("span", { className: "w-4 shrink-0 select-none text-center text-
|
|
1575
|
+
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-og-fg-subtle", children: line.oldNo ?? "" }),
|
|
1576
|
+
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-og-fg-subtle", children: line.newNo ?? "" }),
|
|
1577
|
+
/* @__PURE__ */ jsx4("span", { className: "w-4 shrink-0 select-none text-center text-og-fg-subtle", children: marker(line.type) }),
|
|
1492
1578
|
/* @__PURE__ */ jsx4("span", { className: "whitespace-pre-wrap break-all px-1", children: line.text })
|
|
1493
1579
|
]
|
|
1494
1580
|
},
|
|
@@ -1497,7 +1583,7 @@ function UnifiedHunks({ file, theme }) {
|
|
|
1497
1583
|
] }, `${file.path}-h${hi}`)) });
|
|
1498
1584
|
}
|
|
1499
1585
|
function SplitHunks({ file, theme }) {
|
|
1500
|
-
return /* @__PURE__ */ jsx4("div", { className: "font-mono text-
|
|
1586
|
+
return /* @__PURE__ */ jsx4("div", { className: "font-og-mono text-og-xs", children: file.hunks.map((hunk, hi) => {
|
|
1501
1587
|
const left = [];
|
|
1502
1588
|
const right = [];
|
|
1503
1589
|
for (const line of hunk.lines) {
|
|
@@ -1512,7 +1598,7 @@ function SplitHunks({ file, theme }) {
|
|
|
1512
1598
|
}
|
|
1513
1599
|
const rows = Math.max(left.length, right.length);
|
|
1514
1600
|
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
1515
|
-
/* @__PURE__ */ jsx4("div", { className: "px-2 py-0.5 text-
|
|
1601
|
+
/* @__PURE__ */ jsx4("div", { className: "px-2 py-0.5 text-og-accent", style: { color: theme?.metaForeground }, children: hunk.header }),
|
|
1516
1602
|
Array.from({ length: rows }).map((_, ri) => {
|
|
1517
1603
|
const l = left[ri] ?? null;
|
|
1518
1604
|
const r = right[ri] ?? null;
|
|
@@ -1523,7 +1609,7 @@ function SplitHunks({ file, theme }) {
|
|
|
1523
1609
|
className: "flex w-1/2 min-w-0",
|
|
1524
1610
|
style: { backgroundColor: l ? lineBg(l.type, theme) : void 0 },
|
|
1525
1611
|
children: [
|
|
1526
|
-
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-
|
|
1612
|
+
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-og-fg-subtle", children: l?.oldNo ?? "" }),
|
|
1527
1613
|
/* @__PURE__ */ jsx4("span", { className: "whitespace-pre-wrap break-all px-1", children: l?.text ?? "" })
|
|
1528
1614
|
]
|
|
1529
1615
|
}
|
|
@@ -1531,10 +1617,10 @@ function SplitHunks({ file, theme }) {
|
|
|
1531
1617
|
/* @__PURE__ */ jsxs3(
|
|
1532
1618
|
"span",
|
|
1533
1619
|
{
|
|
1534
|
-
className: "flex w-1/2 min-w-0 border-l border-
|
|
1620
|
+
className: "flex w-1/2 min-w-0 border-l border-og-border",
|
|
1535
1621
|
style: { backgroundColor: r ? lineBg(r.type, theme) : void 0 },
|
|
1536
1622
|
children: [
|
|
1537
|
-
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-
|
|
1623
|
+
/* @__PURE__ */ jsx4("span", { className: "w-10 shrink-0 select-none px-1 text-right text-og-fg-subtle", children: r?.newNo ?? "" }),
|
|
1538
1624
|
/* @__PURE__ */ jsx4("span", { className: "whitespace-pre-wrap break-all px-1", children: r?.text ?? "" })
|
|
1539
1625
|
]
|
|
1540
1626
|
}
|
|
@@ -1619,12 +1705,12 @@ function PierreDiff({
|
|
|
1619
1705
|
themeType: themeType ?? "dark"
|
|
1620
1706
|
};
|
|
1621
1707
|
const pierreVars = {
|
|
1622
|
-
"--diffs-dark-bg": "var(--og-color-bg
|
|
1623
|
-
"--diffs-light-bg": "var(--og-color-bg
|
|
1624
|
-
"--diffs-bg-buffer-override": "var(--og-color-surface-1
|
|
1625
|
-
"--diffs-bg-separator-override": "var(--og-color-surface-1
|
|
1626
|
-
"--diffs-font-size": "
|
|
1627
|
-
"--diffs-line-height": "
|
|
1708
|
+
"--diffs-dark-bg": "var(--og-color-bg)",
|
|
1709
|
+
"--diffs-light-bg": "var(--og-color-bg)",
|
|
1710
|
+
"--diffs-bg-buffer-override": "var(--og-color-surface-1)",
|
|
1711
|
+
"--diffs-bg-separator-override": "var(--og-color-surface-1)",
|
|
1712
|
+
"--diffs-font-size": "var(--og-code-font-size)",
|
|
1713
|
+
"--diffs-line-height": "var(--og-code-line-height)"
|
|
1628
1714
|
};
|
|
1629
1715
|
return /* @__PURE__ */ jsx5(
|
|
1630
1716
|
"div",
|
|
@@ -1644,7 +1730,7 @@ function PierreDiff({
|
|
|
1644
1730
|
);
|
|
1645
1731
|
}
|
|
1646
1732
|
function DiffSkeleton() {
|
|
1647
|
-
return /* @__PURE__ */ jsx5("div", { className: "p-3 text-
|
|
1733
|
+
return /* @__PURE__ */ jsx5("div", { className: "p-3 text-og-sm text-og-fg-subtle", children: "Loading diff\u2026" });
|
|
1648
1734
|
}
|
|
1649
1735
|
|
|
1650
1736
|
// src/timeline/tool-diff.tsx
|
|
@@ -1672,7 +1758,7 @@ function LayoutToggle({ layout, onChange }) {
|
|
|
1672
1758
|
type: "button",
|
|
1673
1759
|
onClick: () => onChange(value),
|
|
1674
1760
|
className: cn(
|
|
1675
|
-
"rounded-
|
|
1761
|
+
"rounded-og-xs px-2 py-[3px] text-og-xs font-medium capitalize transition-colors",
|
|
1676
1762
|
layout === value ? "bg-og-surface-2 text-og-fg" : "text-og-fg-subtle hover:text-og-fg-muted"
|
|
1677
1763
|
),
|
|
1678
1764
|
children: value
|
|
@@ -2024,16 +2110,34 @@ function computerVerb(action) {
|
|
|
2024
2110
|
return action.type;
|
|
2025
2111
|
}
|
|
2026
2112
|
}
|
|
2113
|
+
function asComputerArgs(args) {
|
|
2114
|
+
if (!args) {
|
|
2115
|
+
return {};
|
|
2116
|
+
}
|
|
2117
|
+
const parsed = typeof args === "string" ? tryParseJson(args) : args;
|
|
2118
|
+
if (!parsed || typeof parsed !== "object") {
|
|
2119
|
+
return {};
|
|
2120
|
+
}
|
|
2121
|
+
const record = parsed;
|
|
2122
|
+
return {
|
|
2123
|
+
...typeof record.x === "number" ? { x: record.x } : {},
|
|
2124
|
+
...typeof record.y === "number" ? { y: record.y } : {},
|
|
2125
|
+
...typeof record.text === "string" ? { text: record.text } : {},
|
|
2126
|
+
...Array.isArray(record.keys) ? { keys: record.keys } : {},
|
|
2127
|
+
...typeof record.button === "string" ? { button: record.button } : {}
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2027
2130
|
function ComputerCallRenderer({ item }) {
|
|
2028
2131
|
const raw = item.raw ?? {};
|
|
2029
|
-
const
|
|
2132
|
+
const functionAction = !raw.action && item.name.startsWith("computer_") && item.name !== "computer_call" ? { type: item.name.slice("computer_".length), ...asComputerArgs(item.arguments) } : void 0;
|
|
2133
|
+
const action = raw.action ?? functionAction;
|
|
2030
2134
|
const actions = raw.actions ?? (action ? [action] : []);
|
|
2031
2135
|
const verb = computerVerb(action);
|
|
2032
2136
|
const out = item.output;
|
|
2033
2137
|
const running = item.status === "running";
|
|
2034
2138
|
const rejected = raw.providerData?.approvalStatus === "rejected";
|
|
2035
2139
|
const readOnly = typeof out === "string" && out.includes("read-only");
|
|
2036
|
-
const
|
|
2140
|
+
const shotUrl = screenshotDataUrl(out);
|
|
2037
2141
|
const empty = out === "" || out == null;
|
|
2038
2142
|
const batched = actions.length > 1 ? actions.map((a) => computerVerb(a)).join(" \xB7 ") : null;
|
|
2039
2143
|
const countSuffix = actions.length > 1 ? ` \xB7${actions.length}` : "";
|
|
@@ -2078,8 +2182,8 @@ function ComputerCallRenderer({ item }) {
|
|
|
2078
2182
|
}
|
|
2079
2183
|
const isFailed = item.status === "failed";
|
|
2080
2184
|
const isCancelled = item.status === "cancelled";
|
|
2081
|
-
if (
|
|
2082
|
-
const caption =
|
|
2185
|
+
if (shotUrl) {
|
|
2186
|
+
const caption = `${verb}${actions.length > 1 ? ` (+${actions.length - 1} more)` : ""}`;
|
|
2083
2187
|
return /* @__PURE__ */ jsxs5(
|
|
2084
2188
|
ActivityDisclosure,
|
|
2085
2189
|
{
|
|
@@ -2088,9 +2192,9 @@ function ComputerCallRenderer({ item }) {
|
|
|
2088
2192
|
title: `${verb}${countSuffix}`,
|
|
2089
2193
|
failed: isFailed,
|
|
2090
2194
|
cancelled: isCancelled,
|
|
2091
|
-
media: /* @__PURE__ */ jsx7(Thumbnail, { src:
|
|
2195
|
+
media: /* @__PURE__ */ jsx7(Thumbnail, { src: shotUrl, caption }),
|
|
2092
2196
|
children: [
|
|
2093
|
-
/* @__PURE__ */ jsx7(ScreenshotFigure, { src:
|
|
2197
|
+
/* @__PURE__ */ jsx7(ScreenshotFigure, { src: shotUrl, caption }),
|
|
2094
2198
|
batched ? /* @__PURE__ */ jsxs5(BodyNote, { children: [
|
|
2095
2199
|
"batched: ",
|
|
2096
2200
|
batched
|
|
@@ -2368,6 +2472,15 @@ var BASE_ENTRIES = [
|
|
|
2368
2472
|
{ match: "name", name: "write_stdin", render: WriteStdinRenderer },
|
|
2369
2473
|
{ match: "name", name: "apply_patch_call", render: ApplyPatchRenderer },
|
|
2370
2474
|
{ match: "name", name: "computer_call", render: ComputerCallRenderer },
|
|
2475
|
+
// Function-mode computer tools (codex / chat-wire transports).
|
|
2476
|
+
{ match: "name", name: "computer_screenshot", render: ComputerCallRenderer },
|
|
2477
|
+
{ match: "name", name: "computer_click", render: ComputerCallRenderer },
|
|
2478
|
+
{ match: "name", name: "computer_double_click", render: ComputerCallRenderer },
|
|
2479
|
+
{ match: "name", name: "computer_move", render: ComputerCallRenderer },
|
|
2480
|
+
{ match: "name", name: "computer_scroll", render: ComputerCallRenderer },
|
|
2481
|
+
{ match: "name", name: "computer_type", render: ComputerCallRenderer },
|
|
2482
|
+
{ match: "name", name: "computer_keypress", render: ComputerCallRenderer },
|
|
2483
|
+
{ match: "name", name: "computer_drag", render: ComputerCallRenderer },
|
|
2371
2484
|
{ match: "name", name: "web_search_call", render: WebSearchRenderer },
|
|
2372
2485
|
{ match: "name", name: "view_image", render: ViewImageRenderer },
|
|
2373
2486
|
{ match: "name", name: "environment_set_variable", render: SecretSetRenderer }
|
|
@@ -2497,7 +2610,7 @@ function WorkerRow({ item, onOpenSession }) {
|
|
|
2497
2610
|
type: "button",
|
|
2498
2611
|
onClick: () => item.workerSessionId && onOpenSession(item.workerSessionId),
|
|
2499
2612
|
className: cn(
|
|
2500
|
-
"shrink-0 self-center rounded-og-sm border border-og-border px-2.5 py-1 text-og-sm font-medium text-og-fg-muted",
|
|
2613
|
+
"shrink-0 self-center rounded-og-sm border border-og-border px-2.5 py-1 text-og-sm font-medium text-og-fg-muted pointer-coarse:py-2",
|
|
2501
2614
|
"outline-none transition-colors duration-150 hover:border-og-border-strong hover:text-og-fg",
|
|
2502
2615
|
"focus-visible:ring-2 focus-visible:ring-og-accent"
|
|
2503
2616
|
),
|
|
@@ -2524,6 +2637,9 @@ function TurnSummary({ items, outcome, failureText, durationMs, defaultOpen, chi
|
|
|
2524
2637
|
{
|
|
2525
2638
|
className: cn(
|
|
2526
2639
|
"group flex w-full items-center gap-2.5 rounded-og-md border px-3 py-2 text-left text-og-base transition-colors",
|
|
2640
|
+
// A folded turn is a touch target on coarse pointers: grow the row so
|
|
2641
|
+
// it clears the 40px minimum without disturbing the calm desktop rhythm.
|
|
2642
|
+
"pointer-coarse:py-2.5",
|
|
2527
2643
|
// Only a failed turn earns the one filled/tinted card in the timeline;
|
|
2528
2644
|
// complete and cancelled stay flat and calm.
|
|
2529
2645
|
outcome === "failed" ? "border-og-status-failed/30 bg-og-status-failed/[0.06] hover:border-og-status-failed/50" : "border-og-border bg-og-surface-1/50 hover:border-og-border-strong"
|
|
@@ -2547,7 +2663,19 @@ function TurnSummary({ items, outcome, failureText, durationMs, defaultOpen, chi
|
|
|
2547
2663
|
failureText
|
|
2548
2664
|
] }) : null,
|
|
2549
2665
|
outcome === "cancelled" ? /* @__PURE__ */ jsx9("span", { className: "text-og-fg-subtle", children: " \xB7 interrupted" }) : null
|
|
2550
|
-
] })
|
|
2666
|
+
] }),
|
|
2667
|
+
/* @__PURE__ */ jsx9(
|
|
2668
|
+
"span",
|
|
2669
|
+
{
|
|
2670
|
+
"aria-hidden": true,
|
|
2671
|
+
className: cn(
|
|
2672
|
+
"ml-auto shrink-0 pl-2 text-og-xs text-og-fg-subtle transition-opacity duration-150",
|
|
2673
|
+
"opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100",
|
|
2674
|
+
"pointer-coarse:opacity-100"
|
|
2675
|
+
),
|
|
2676
|
+
children: open ? "hide steps" : "show steps"
|
|
2677
|
+
}
|
|
2678
|
+
)
|
|
2551
2679
|
]
|
|
2552
2680
|
}
|
|
2553
2681
|
),
|
|
@@ -2566,8 +2694,8 @@ function summarizeTurn(items, durationMs) {
|
|
|
2566
2694
|
files += applyPatchOps(item.raw).length;
|
|
2567
2695
|
} else if (item.name === "exec_command") {
|
|
2568
2696
|
commands += 1;
|
|
2569
|
-
} else if (rawTypeOf(item) === "computer_call" || item.name === "computer_call") {
|
|
2570
|
-
if (
|
|
2697
|
+
} else if (rawTypeOf(item) === "computer_call" || item.name === "computer_call" || item.name === "computer_screenshot") {
|
|
2698
|
+
if (screenshotDataUrl(item.output) !== null) {
|
|
2571
2699
|
screenshots += 1;
|
|
2572
2700
|
}
|
|
2573
2701
|
}
|
|
@@ -2812,15 +2940,28 @@ function generateClientEventId() {
|
|
|
2812
2940
|
}
|
|
2813
2941
|
|
|
2814
2942
|
// src/hooks/use-file-attachments.ts
|
|
2815
|
-
import { useCallback as useCallback4, useState as useState10 } from "react";
|
|
2943
|
+
import { useCallback as useCallback4, useRef as useRef3, useState as useState10 } from "react";
|
|
2816
2944
|
var isImage = (file) => file.type.startsWith("image/");
|
|
2817
2945
|
function useFileAttachments(options = {}) {
|
|
2818
2946
|
const { client, workspaceId } = useOpenGeni(options);
|
|
2819
2947
|
const pasteFilter = options.pasteFilter ?? isImage;
|
|
2820
2948
|
const [attachments, setAttachments] = useState10([]);
|
|
2949
|
+
const sources = useRef3(/* @__PURE__ */ new Map());
|
|
2950
|
+
const startUpload = useCallback4((id, file) => {
|
|
2951
|
+
void client.uploadFile(workspaceId, {
|
|
2952
|
+
filename: file.name || "file",
|
|
2953
|
+
contentType: file.type || "application/octet-stream",
|
|
2954
|
+
data: file
|
|
2955
|
+
}).then((asset) => {
|
|
2956
|
+
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "ready", file: asset, name: asset.filename, contentType: asset.contentType, sizeBytes: asset.sizeBytes, error: void 0 } : attachment));
|
|
2957
|
+
}).catch((error) => {
|
|
2958
|
+
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "failed", error: error instanceof Error ? error.message : String(error) } : attachment));
|
|
2959
|
+
});
|
|
2960
|
+
}, [client, workspaceId]);
|
|
2821
2961
|
const addFiles = useCallback4((files) => {
|
|
2822
2962
|
for (const file of files) {
|
|
2823
2963
|
const id = crypto.randomUUID();
|
|
2964
|
+
sources.current.set(id, file);
|
|
2824
2965
|
const previewUrl = isImage(file) ? URL.createObjectURL(file) : void 0;
|
|
2825
2966
|
setAttachments((current) => [...current, {
|
|
2826
2967
|
id,
|
|
@@ -2830,17 +2971,17 @@ function useFileAttachments(options = {}) {
|
|
|
2830
2971
|
status: "uploading",
|
|
2831
2972
|
...previewUrl ? { previewUrl } : {}
|
|
2832
2973
|
}]);
|
|
2833
|
-
|
|
2834
|
-
filename: file.name || "file",
|
|
2835
|
-
contentType: file.type || "application/octet-stream",
|
|
2836
|
-
data: file
|
|
2837
|
-
}).then((asset) => {
|
|
2838
|
-
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "ready", file: asset, name: asset.filename, contentType: asset.contentType, sizeBytes: asset.sizeBytes } : attachment));
|
|
2839
|
-
}).catch((error) => {
|
|
2840
|
-
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "failed", error: error instanceof Error ? error.message : String(error) } : attachment));
|
|
2841
|
-
});
|
|
2974
|
+
startUpload(id, file);
|
|
2842
2975
|
}
|
|
2843
|
-
}, [
|
|
2976
|
+
}, [startUpload]);
|
|
2977
|
+
const retry = useCallback4((id) => {
|
|
2978
|
+
const file = sources.current.get(id);
|
|
2979
|
+
if (!file) {
|
|
2980
|
+
return;
|
|
2981
|
+
}
|
|
2982
|
+
setAttachments((current) => current.map((attachment) => attachment.id === id ? { ...attachment, status: "uploading", error: void 0 } : attachment));
|
|
2983
|
+
startUpload(id, file);
|
|
2984
|
+
}, [startUpload]);
|
|
2844
2985
|
const addFromPaste = useCallback4((event) => {
|
|
2845
2986
|
const clipboardFiles = event.clipboardData?.files;
|
|
2846
2987
|
if (!clipboardFiles) {
|
|
@@ -2852,6 +2993,7 @@ function useFileAttachments(options = {}) {
|
|
|
2852
2993
|
}
|
|
2853
2994
|
}, [addFiles, pasteFilter]);
|
|
2854
2995
|
const remove = useCallback4((id) => {
|
|
2996
|
+
sources.current.delete(id);
|
|
2855
2997
|
setAttachments((current) => {
|
|
2856
2998
|
const removed = current.find((attachment) => attachment.id === id);
|
|
2857
2999
|
if (removed?.previewUrl) {
|
|
@@ -2861,6 +3003,7 @@ function useFileAttachments(options = {}) {
|
|
|
2861
3003
|
});
|
|
2862
3004
|
}, []);
|
|
2863
3005
|
const clear = useCallback4(() => {
|
|
3006
|
+
sources.current.clear();
|
|
2864
3007
|
setAttachments((current) => {
|
|
2865
3008
|
for (const attachment of current) {
|
|
2866
3009
|
if (attachment.previewUrl) {
|
|
@@ -2876,13 +3019,14 @@ function useFileAttachments(options = {}) {
|
|
|
2876
3019
|
uploading: attachments.some((attachment) => attachment.status === "uploading"),
|
|
2877
3020
|
addFiles,
|
|
2878
3021
|
addFromPaste,
|
|
3022
|
+
retry,
|
|
2879
3023
|
remove,
|
|
2880
3024
|
clear
|
|
2881
3025
|
};
|
|
2882
3026
|
}
|
|
2883
3027
|
|
|
2884
3028
|
// src/hooks/use-turn-queue.ts
|
|
2885
|
-
import { useCallback as useCallback5, useEffect as useEffect5, useRef as
|
|
3029
|
+
import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef4, useState as useState11 } from "react";
|
|
2886
3030
|
function isTurnQueueEvent(event) {
|
|
2887
3031
|
return event.type.startsWith("turn.");
|
|
2888
3032
|
}
|
|
@@ -2926,8 +3070,8 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
2926
3070
|
const [loading, setLoading] = useState11(enabled);
|
|
2927
3071
|
const [error, setError] = useState11(null);
|
|
2928
3072
|
const mutation = useMutationRunner();
|
|
2929
|
-
const generation =
|
|
2930
|
-
const targetKeyRef =
|
|
3073
|
+
const generation = useRef4(0);
|
|
3074
|
+
const targetKeyRef = useRef4(null);
|
|
2931
3075
|
const load = useCallback5(async () => {
|
|
2932
3076
|
if (!sessionId) {
|
|
2933
3077
|
return;
|
|
@@ -3046,7 +3190,7 @@ function useTurnQueue(sessionId, options = {}) {
|
|
|
3046
3190
|
|
|
3047
3191
|
// src/hooks/use-goal.ts
|
|
3048
3192
|
import { OpenGeniApiError } from "@opengeni/sdk";
|
|
3049
|
-
import { useCallback as useCallback6, useEffect as useEffect6, useRef as
|
|
3193
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef5, useState as useState12 } from "react";
|
|
3050
3194
|
function isGoalEvent(event) {
|
|
3051
3195
|
return event.type.startsWith("goal.");
|
|
3052
3196
|
}
|
|
@@ -3059,8 +3203,8 @@ function useGoal(sessionId, options = {}) {
|
|
|
3059
3203
|
const [loading, setLoading] = useState12(enabled);
|
|
3060
3204
|
const [error, setError] = useState12(null);
|
|
3061
3205
|
const mutation = useMutationRunner();
|
|
3062
|
-
const generation =
|
|
3063
|
-
const targetKeyRef =
|
|
3206
|
+
const generation = useRef5(0);
|
|
3207
|
+
const targetKeyRef = useRef5(null);
|
|
3064
3208
|
const load = useCallback6(async () => {
|
|
3065
3209
|
if (!sessionId) {
|
|
3066
3210
|
return;
|
|
@@ -3465,7 +3609,7 @@ import {
|
|
|
3465
3609
|
OpenGeniApiError as OpenGeniApiError2,
|
|
3466
3610
|
applyUrlRotation
|
|
3467
3611
|
} from "@opengeni/sdk";
|
|
3468
|
-
import { useCallback as useCallback15, useEffect as useEffect7, useRef as
|
|
3612
|
+
import { useCallback as useCallback15, useEffect as useEffect7, useRef as useRef6, useState as useState13 } from "react";
|
|
3469
3613
|
function desktopAttachable(cell) {
|
|
3470
3614
|
if (cell.transport !== null) return true;
|
|
3471
3615
|
return cell.reason === "lease_cold" || cell.reason === "not_provisioned" || cell.reason === null;
|
|
@@ -3500,8 +3644,8 @@ function useSessionCapabilities(sessionId, options = {}) {
|
|
|
3500
3644
|
const [viewerCapReached, setViewerCapReached] = useState13(false);
|
|
3501
3645
|
const [viewerId, setViewerId] = useState13(null);
|
|
3502
3646
|
const [nonce, setNonce] = useState13(0);
|
|
3503
|
-
const epochRef =
|
|
3504
|
-
const viewerIdRef =
|
|
3647
|
+
const epochRef = useRef6(0);
|
|
3648
|
+
const viewerIdRef = useRef6(null);
|
|
3505
3649
|
const renegotiate = useCallback15(() => {
|
|
3506
3650
|
setNonce((n) => n + 1);
|
|
3507
3651
|
}, []);
|
|
@@ -3700,7 +3844,7 @@ import {
|
|
|
3700
3844
|
desktopSocketUrl,
|
|
3701
3845
|
nextDesktopState
|
|
3702
3846
|
} from "@opengeni/sdk";
|
|
3703
|
-
import { useEffect as useEffect9, useRef as
|
|
3847
|
+
import { useEffect as useEffect9, useRef as useRef8, useState as useState15 } from "react";
|
|
3704
3848
|
|
|
3705
3849
|
// src/lib/relay-wire.ts
|
|
3706
3850
|
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
@@ -3773,7 +3917,7 @@ function decodeStreamFrame(bytes) {
|
|
|
3773
3917
|
}
|
|
3774
3918
|
|
|
3775
3919
|
// src/hooks/use-relay-frame-stream.ts
|
|
3776
|
-
import { useEffect as useEffect8, useRef as
|
|
3920
|
+
import { useEffect as useEffect8, useRef as useRef7, useState as useState14 } from "react";
|
|
3777
3921
|
var TAG_OPEN = 1;
|
|
3778
3922
|
var TAG_OPENACK = 2;
|
|
3779
3923
|
var TAG_FRAME = 3;
|
|
@@ -3791,7 +3935,7 @@ function useRelayFrameStream(options) {
|
|
|
3791
3935
|
const [state, setState] = useState14("idle");
|
|
3792
3936
|
const [error, setError] = useState14(null);
|
|
3793
3937
|
const [nonce, setNonce] = useState14(0);
|
|
3794
|
-
const stateRef =
|
|
3938
|
+
const stateRef = useRef7("idle");
|
|
3795
3939
|
const setBoth = (next) => {
|
|
3796
3940
|
stateRef.current = next;
|
|
3797
3941
|
setState(next);
|
|
@@ -3800,7 +3944,7 @@ function useRelayFrameStream(options) {
|
|
|
3800
3944
|
const transport = capability?.transport ?? null;
|
|
3801
3945
|
const url = capability?.url ?? null;
|
|
3802
3946
|
const token = capability?.token ?? null;
|
|
3803
|
-
const factoryRef =
|
|
3947
|
+
const factoryRef = useRef7(webSocketFactory);
|
|
3804
3948
|
factoryRef.current = webSocketFactory;
|
|
3805
3949
|
useEffect8(() => {
|
|
3806
3950
|
if (typeof window === "undefined") return;
|
|
@@ -3994,7 +4138,7 @@ function useDesktopStream(options) {
|
|
|
3994
4138
|
const [state, setState] = useState15("idle");
|
|
3995
4139
|
const [error, setError] = useState15(null);
|
|
3996
4140
|
const [nonce, setNonce] = useState15(0);
|
|
3997
|
-
const stateRef =
|
|
4141
|
+
const stateRef = useRef8("idle");
|
|
3998
4142
|
const setBoth = (next) => {
|
|
3999
4143
|
stateRef.current = next;
|
|
4000
4144
|
setState(next);
|
|
@@ -4004,11 +4148,11 @@ function useDesktopStream(options) {
|
|
|
4004
4148
|
const token = capability?.token ?? null;
|
|
4005
4149
|
const transport = capability?.transport ?? null;
|
|
4006
4150
|
const mode = capability?.mode ?? "read-only";
|
|
4007
|
-
const rfbRef =
|
|
4008
|
-
const interactiveRef =
|
|
4009
|
-
const scaleViewportRef =
|
|
4010
|
-
const modeRef =
|
|
4011
|
-
const rfbFactoryRef =
|
|
4151
|
+
const rfbRef = useRef8(null);
|
|
4152
|
+
const interactiveRef = useRef8(interactive);
|
|
4153
|
+
const scaleViewportRef = useRef8(scaleViewport);
|
|
4154
|
+
const modeRef = useRef8(mode);
|
|
4155
|
+
const rfbFactoryRef = useRef8(rfbFactory);
|
|
4012
4156
|
interactiveRef.current = interactive;
|
|
4013
4157
|
scaleViewportRef.current = scaleViewport;
|
|
4014
4158
|
modeRef.current = mode;
|
|
@@ -4101,7 +4245,7 @@ import {
|
|
|
4101
4245
|
ttydResizeFrame,
|
|
4102
4246
|
TtydServerCommand
|
|
4103
4247
|
} from "@opengeni/sdk";
|
|
4104
|
-
import { useEffect as useEffect10, useMemo as useMemo3, useRef as
|
|
4248
|
+
import { useEffect as useEffect10, useMemo as useMemo3, useRef as useRef9, useState as useState16 } from "react";
|
|
4105
4249
|
function decodeFrame(data) {
|
|
4106
4250
|
if (typeof data === "string") {
|
|
4107
4251
|
return { command: data.charAt(0), payload: data.slice(1) };
|
|
@@ -4114,13 +4258,13 @@ function decodeFrame(data) {
|
|
|
4114
4258
|
function useTerminalStream(options) {
|
|
4115
4259
|
const { capability, onOutput, onTitle, initialCols, initialRows } = options;
|
|
4116
4260
|
const [status, setStatus] = useState16("closed");
|
|
4117
|
-
const wsRef =
|
|
4118
|
-
const sizeRef =
|
|
4261
|
+
const wsRef = useRef9(null);
|
|
4262
|
+
const sizeRef = useRef9({
|
|
4119
4263
|
cols: initialCols ?? 80,
|
|
4120
4264
|
rows: initialRows ?? 24
|
|
4121
4265
|
});
|
|
4122
|
-
const onOutputRef =
|
|
4123
|
-
const onTitleRef =
|
|
4266
|
+
const onOutputRef = useRef9(onOutput);
|
|
4267
|
+
const onTitleRef = useRef9(onTitle);
|
|
4124
4268
|
onOutputRef.current = onOutput;
|
|
4125
4269
|
onTitleRef.current = onTitle;
|
|
4126
4270
|
const transport = capability?.transport ?? null;
|
|
@@ -4223,7 +4367,7 @@ function useTerminalStream(options) {
|
|
|
4223
4367
|
|
|
4224
4368
|
// src/hooks/use-sandbox-terminal.ts
|
|
4225
4369
|
import { OpenGeniApiError as OpenGeniApiError3 } from "@opengeni/sdk";
|
|
4226
|
-
import { useCallback as useCallback16, useEffect as useEffect11, useMemo as useMemo4, useRef as
|
|
4370
|
+
import { useCallback as useCallback16, useEffect as useEffect11, useMemo as useMemo4, useRef as useRef10, useState as useState17 } from "react";
|
|
4227
4371
|
function useSandboxTerminal(sessionId, options) {
|
|
4228
4372
|
const { client, workspaceId } = useOpenGeni(options);
|
|
4229
4373
|
const includeAgentFirehose = options.includeAgentFirehose ?? true;
|
|
@@ -4233,7 +4377,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4233
4377
|
const [openedPtyId, setOpenedPtyId] = useState17(null);
|
|
4234
4378
|
const [openError, setOpenError] = useState17(null);
|
|
4235
4379
|
const [reopenNonce, setReopenNonce] = useState17(0);
|
|
4236
|
-
const openInFlight =
|
|
4380
|
+
const openInFlight = useRef10(false);
|
|
4237
4381
|
const boxWarm = liveness === void 0 || liveness === "warm" || liveness === "draining";
|
|
4238
4382
|
useEffect11(() => {
|
|
4239
4383
|
if (!interactive || !sessionId || ptyFilter || !boxWarm) return;
|
|
@@ -4339,7 +4483,7 @@ function useSandboxTerminal(sessionId, options) {
|
|
|
4339
4483
|
}
|
|
4340
4484
|
|
|
4341
4485
|
// src/hooks/use-sandbox-files.ts
|
|
4342
|
-
import { useCallback as useCallback17, useEffect as useEffect12, useRef as
|
|
4486
|
+
import { useCallback as useCallback17, useEffect as useEffect12, useRef as useRef11, useState as useState18 } from "react";
|
|
4343
4487
|
function parentOf(path) {
|
|
4344
4488
|
const i = path.lastIndexOf("/");
|
|
4345
4489
|
return i <= 0 ? "" : path.slice(0, i);
|
|
@@ -4459,12 +4603,12 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4459
4603
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
4460
4604
|
const rootPath = options.rootPath ?? "";
|
|
4461
4605
|
const [tree, setTree] = useState18([]);
|
|
4462
|
-
const treeRef =
|
|
4606
|
+
const treeRef = useRef11([]);
|
|
4463
4607
|
const [loading, setLoading] = useState18(false);
|
|
4464
4608
|
const [expandingPaths, setExpandingPaths] = useState18(/* @__PURE__ */ new Set());
|
|
4465
4609
|
const [error, setError] = useState18(null);
|
|
4466
|
-
const statusRef =
|
|
4467
|
-
const ownRevisionsRef =
|
|
4610
|
+
const statusRef = useRef11(/* @__PURE__ */ new Map());
|
|
4611
|
+
const ownRevisionsRef = useRef11(/* @__PURE__ */ new Set());
|
|
4468
4612
|
const onMutationError = options.onMutationError;
|
|
4469
4613
|
treeRef.current = tree;
|
|
4470
4614
|
const applyStatus = useCallback17((nodes) => {
|
|
@@ -4679,10 +4823,10 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4679
4823
|
}
|
|
4680
4824
|
}, [client, workspaceId, sessionId, rootPath, applyStatus]);
|
|
4681
4825
|
const events = options.events;
|
|
4682
|
-
const lastSeqRef =
|
|
4683
|
-
const pendingParentsRef =
|
|
4684
|
-
const pendingGitRef =
|
|
4685
|
-
const debounceRef =
|
|
4826
|
+
const lastSeqRef = useRef11(0);
|
|
4827
|
+
const pendingParentsRef = useRef11(/* @__PURE__ */ new Set());
|
|
4828
|
+
const pendingGitRef = useRef11(false);
|
|
4829
|
+
const debounceRef = useRef11(null);
|
|
4686
4830
|
useEffect12(() => {
|
|
4687
4831
|
if (!enabled || !events) return;
|
|
4688
4832
|
let sawNew = false;
|
|
@@ -4726,7 +4870,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4726
4870
|
},
|
|
4727
4871
|
[]
|
|
4728
4872
|
);
|
|
4729
|
-
const wasLiveRef =
|
|
4873
|
+
const wasLiveRef = useRef11(false);
|
|
4730
4874
|
const liveness = options.liveness;
|
|
4731
4875
|
useEffect12(() => {
|
|
4732
4876
|
const live = liveness === "warm" || liveness === "draining";
|
|
@@ -4754,7 +4898,7 @@ function useSandboxFiles(sessionId, options = {}) {
|
|
|
4754
4898
|
}
|
|
4755
4899
|
|
|
4756
4900
|
// src/hooks/use-sandbox-git.ts
|
|
4757
|
-
import { useCallback as useCallback18, useEffect as useEffect13, useRef as
|
|
4901
|
+
import { useCallback as useCallback18, useEffect as useEffect13, useRef as useRef12, useState as useState19 } from "react";
|
|
4758
4902
|
function useSandboxGit(sessionId, options = {}) {
|
|
4759
4903
|
const { client, workspaceId } = useOpenGeni(options);
|
|
4760
4904
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
@@ -4799,7 +4943,7 @@ function useSandboxGit(sessionId, options = {}) {
|
|
|
4799
4943
|
void refresh();
|
|
4800
4944
|
}, [enabled, refresh]);
|
|
4801
4945
|
const events = options.events;
|
|
4802
|
-
const lastChangeRef =
|
|
4946
|
+
const lastChangeRef = useRef12(0);
|
|
4803
4947
|
useEffect13(() => {
|
|
4804
4948
|
if (!enabled || !events) return;
|
|
4805
4949
|
let latest = lastChangeRef.current;
|
|
@@ -5048,14 +5192,14 @@ function clearErrorMessage(cause) {
|
|
|
5048
5192
|
}
|
|
5049
5193
|
|
|
5050
5194
|
// src/hooks/use-slash-commands.ts
|
|
5051
|
-
import { useCallback as useCallback19, useMemo as useMemo5, useRef as
|
|
5195
|
+
import { useCallback as useCallback19, useMemo as useMemo5, useRef as useRef13, useState as useState20 } from "react";
|
|
5052
5196
|
function useSlashCommands(options) {
|
|
5053
5197
|
const { commands, context, handlers, value, setValue } = options;
|
|
5054
5198
|
const [highlight, setHighlight] = useState20(0);
|
|
5055
5199
|
const [dismissedValue, setDismissedValue] = useState20(null);
|
|
5056
5200
|
const dismissed = dismissedValue !== null && dismissedValue === value;
|
|
5057
|
-
const navigatedRef =
|
|
5058
|
-
const navTokenRef =
|
|
5201
|
+
const navigatedRef = useRef13(false);
|
|
5202
|
+
const navTokenRef = useRef13(value);
|
|
5059
5203
|
if (navTokenRef.current !== value) {
|
|
5060
5204
|
navTokenRef.current = value;
|
|
5061
5205
|
navigatedRef.current = false;
|
|
@@ -5182,7 +5326,7 @@ function useSlashCommands(options) {
|
|
|
5182
5326
|
},
|
|
5183
5327
|
[items, runResolved]
|
|
5184
5328
|
);
|
|
5185
|
-
const runningRef =
|
|
5329
|
+
const runningRef = useRef13(false);
|
|
5186
5330
|
const onKeyDown = useCallback19(
|
|
5187
5331
|
(event) => {
|
|
5188
5332
|
if (!open) {
|
|
@@ -5323,9 +5467,9 @@ function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintTex
|
|
|
5323
5467
|
}
|
|
5324
5468
|
|
|
5325
5469
|
// src/components/chat-composer.tsx
|
|
5326
|
-
import { ArrowUpIcon, FileIcon, ImageIcon as ImageIcon2, LoaderCircleIcon, PaperclipIcon, SquareIcon, XIcon as XIcon2 } from "lucide-react";
|
|
5470
|
+
import { ArrowUpIcon, FileIcon, ImageIcon as ImageIcon2, LoaderCircleIcon, PaperclipIcon, RotateCwIcon, SquareIcon, XIcon as XIcon2 } from "lucide-react";
|
|
5327
5471
|
import { AnimatePresence as AnimatePresence3, motion as motion3 } from "motion/react";
|
|
5328
|
-
import { useCallback as useCallback20, useEffect as useEffect14, useId as useId2, useMemo as useMemo7, useRef as
|
|
5472
|
+
import { useCallback as useCallback20, useEffect as useEffect14, useId as useId2, useMemo as useMemo7, useRef as useRef14, useState as useState21 } from "react";
|
|
5329
5473
|
|
|
5330
5474
|
// src/components/model-picker.tsx
|
|
5331
5475
|
import { ChevronDownIcon } from "lucide-react";
|
|
@@ -5402,8 +5546,8 @@ function ChatComposer({
|
|
|
5402
5546
|
commandContext,
|
|
5403
5547
|
onClearView
|
|
5404
5548
|
}) {
|
|
5405
|
-
const textareaRef =
|
|
5406
|
-
const fileInputRef =
|
|
5549
|
+
const textareaRef = useRef14(null);
|
|
5550
|
+
const fileInputRef = useRef14(null);
|
|
5407
5551
|
const active = status != null && ACTIVE_STATUSES.has(status);
|
|
5408
5552
|
const blockedByUpload = attachments?.uploading === true;
|
|
5409
5553
|
const hasReadyAttachment = (attachments?.readyResources.length ?? 0) > 0;
|
|
@@ -5545,217 +5689,258 @@ function ChatComposer({
|
|
|
5545
5689
|
[commands, commandContext]
|
|
5546
5690
|
);
|
|
5547
5691
|
const activeNotice = notice ?? (composer.error ? { tone: "error", message: composer.error.message || "Sending failed \u2014 your draft is still here. Try again." } : null);
|
|
5548
|
-
return
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
palette.
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
"div",
|
|
5582
|
-
{
|
|
5583
|
-
"aria-hidden": true,
|
|
5584
|
-
className: cn(
|
|
5585
|
-
"pointer-events-none absolute inset-0 z-10 flex items-center justify-center",
|
|
5586
|
-
"rounded-og-lg bg-og-surface-1/85 text-sm font-medium text-og-accent backdrop-blur-[1px]"
|
|
5587
|
-
),
|
|
5588
|
-
children: /* @__PURE__ */ jsxs10("span", { className: "inline-flex items-center gap-2", children: [
|
|
5589
|
-
/* @__PURE__ */ jsx12(PaperclipIcon, { className: "size-4" }),
|
|
5590
|
-
"Drop files to attach"
|
|
5591
|
-
] })
|
|
5592
|
-
}
|
|
5593
|
-
) : null,
|
|
5594
|
-
attachments && attachments.attachments.length > 0 ? /* @__PURE__ */ jsx12(AttachmentChips, { attachments: attachments.attachments, onRemove: attachments.remove }) : null,
|
|
5595
|
-
header,
|
|
5596
|
-
/* @__PURE__ */ jsx12(
|
|
5597
|
-
"textarea",
|
|
5598
|
-
{
|
|
5599
|
-
ref: textareaRef,
|
|
5600
|
-
rows: 1,
|
|
5601
|
-
value: composer.value,
|
|
5602
|
-
onChange: (event) => composer.setValue(event.target.value),
|
|
5603
|
-
onKeyDown,
|
|
5604
|
-
onPaste: handlePaste,
|
|
5605
|
-
placeholder: placeholder ?? "Message the agent\u2026",
|
|
5606
|
-
disabled,
|
|
5607
|
-
autoFocus,
|
|
5608
|
-
"aria-label": "Message the agent",
|
|
5609
|
-
role: paletteEnabled && palette.open ? "combobox" : void 0,
|
|
5610
|
-
"aria-expanded": paletteEnabled ? palette.open : void 0,
|
|
5611
|
-
"aria-controls": paletteEnabled && palette.open ? listboxId : void 0,
|
|
5612
|
-
"aria-activedescendant": paletteEnabled && palette.open ? `${listboxId}-option-${palette.highlight}` : void 0,
|
|
5613
|
-
className: cn(
|
|
5614
|
-
"block w-full resize-none bg-transparent px-4 pt-3.5 pb-1 text-[15px] leading-6",
|
|
5615
|
-
// The wrapper owns the whole-composer focus affordance (focus-within
|
|
5616
|
-
// border + soft glow). Suppress any self-scoped focus outline on the
|
|
5617
|
-
// textarea itself: `focus:outline-none` alone only sets outline-style
|
|
5618
|
-
// on `:focus`, which a host app's zero-specificity
|
|
5619
|
-
// `:where(...):focus-visible { outline: ... }` base rule re-applies as
|
|
5620
|
-
// the full shorthand. `focus-visible:outline-none` matches the same
|
|
5621
|
-
// state at class specificity and wins, so no second highlight (the
|
|
5622
|
-
// top-half rectangle bounded to the textarea box) ever paints.
|
|
5623
|
-
"text-og-fg placeholder:text-og-fg-subtle focus:outline-none focus-visible:outline-none",
|
|
5624
|
-
"disabled:cursor-not-allowed disabled:opacity-60"
|
|
5625
|
-
)
|
|
5626
|
-
}
|
|
5692
|
+
return (
|
|
5693
|
+
// Respect the iOS home-indicator inset so the sticky composer never sits
|
|
5694
|
+
// under it (0 on non-notch devices and desktop, so it's inert there).
|
|
5695
|
+
/* @__PURE__ */ jsxs10("div", { className: cn("og-root", className), style: { paddingBottom: "env(safe-area-inset-bottom)" }, children: [
|
|
5696
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative", children: [
|
|
5697
|
+
paletteEnabled ? /* @__PURE__ */ jsx12(
|
|
5698
|
+
CommandPalette,
|
|
5699
|
+
{
|
|
5700
|
+
open: palette.open && confirmState === null,
|
|
5701
|
+
items: palette.items,
|
|
5702
|
+
highlight: palette.highlight,
|
|
5703
|
+
onHighlight: palette.setHighlight,
|
|
5704
|
+
onRun: (index) => {
|
|
5705
|
+
palette.setHighlight(index);
|
|
5706
|
+
void palette.runAt(index);
|
|
5707
|
+
},
|
|
5708
|
+
argHintText: palette.activeArgHint,
|
|
5709
|
+
listboxId
|
|
5710
|
+
}
|
|
5711
|
+
) : null,
|
|
5712
|
+
/* @__PURE__ */ jsxs10(
|
|
5713
|
+
"div",
|
|
5714
|
+
{
|
|
5715
|
+
onDragOver: attachments ? handleDragOver : void 0,
|
|
5716
|
+
onDragLeave: attachments ? handleDragLeave : void 0,
|
|
5717
|
+
onDrop: attachments ? handleDrop : void 0,
|
|
5718
|
+
className: cn(
|
|
5719
|
+
"relative rounded-og-lg border border-og-border bg-og-surface-1 shadow-og-sm",
|
|
5720
|
+
"transition-[border-color,box-shadow] duration-200",
|
|
5721
|
+
"focus-within:border-og-accent/60 focus-within:shadow-og-glow",
|
|
5722
|
+
// While files are dragged over, swap to a dashed accent border to
|
|
5723
|
+
// signal a live drop target (the overlay carries the label).
|
|
5724
|
+
dragging && "border-dashed border-og-accent"
|
|
5627
5725
|
),
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
attachments || models || controlsStart ? /* @__PURE__ */ jsxs10("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
5637
|
-
attachments ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
5638
|
-
/* @__PURE__ */ jsx12(
|
|
5639
|
-
"input",
|
|
5640
|
-
{
|
|
5641
|
-
ref: fileInputRef,
|
|
5642
|
-
type: "file",
|
|
5643
|
-
multiple: true,
|
|
5644
|
-
className: "hidden",
|
|
5645
|
-
onChange: handleFileChange
|
|
5646
|
-
}
|
|
5726
|
+
children: [
|
|
5727
|
+
dragging ? /* @__PURE__ */ jsx12(
|
|
5728
|
+
"div",
|
|
5729
|
+
{
|
|
5730
|
+
"aria-hidden": true,
|
|
5731
|
+
className: cn(
|
|
5732
|
+
"pointer-events-none absolute inset-0 z-10 flex items-center justify-center",
|
|
5733
|
+
"rounded-og-lg bg-og-surface-1/85 text-sm font-medium text-og-accent backdrop-blur-[1px]"
|
|
5647
5734
|
),
|
|
5735
|
+
children: /* @__PURE__ */ jsxs10("span", { className: "inline-flex items-center gap-2", children: [
|
|
5736
|
+
/* @__PURE__ */ jsx12(PaperclipIcon, { className: "size-4" }),
|
|
5737
|
+
"Drop files to attach"
|
|
5738
|
+
] })
|
|
5739
|
+
}
|
|
5740
|
+
) : null,
|
|
5741
|
+
attachments && attachments.attachments.length > 0 ? /* @__PURE__ */ jsx12(
|
|
5742
|
+
AttachmentChips,
|
|
5743
|
+
{
|
|
5744
|
+
attachments: attachments.attachments,
|
|
5745
|
+
onRemove: attachments.remove,
|
|
5746
|
+
onRetry: attachments.retry
|
|
5747
|
+
}
|
|
5748
|
+
) : null,
|
|
5749
|
+
header,
|
|
5750
|
+
/* @__PURE__ */ jsx12(
|
|
5751
|
+
"textarea",
|
|
5752
|
+
{
|
|
5753
|
+
ref: textareaRef,
|
|
5754
|
+
rows: 1,
|
|
5755
|
+
value: composer.value,
|
|
5756
|
+
onChange: (event) => composer.setValue(event.target.value),
|
|
5757
|
+
onKeyDown,
|
|
5758
|
+
onPaste: handlePaste,
|
|
5759
|
+
placeholder: placeholder ?? "Message the agent\u2026",
|
|
5760
|
+
disabled,
|
|
5761
|
+
autoFocus,
|
|
5762
|
+
"aria-label": "Message the agent",
|
|
5763
|
+
role: paletteEnabled && palette.open ? "combobox" : void 0,
|
|
5764
|
+
"aria-expanded": paletteEnabled ? palette.open : void 0,
|
|
5765
|
+
"aria-controls": paletteEnabled && palette.open ? listboxId : void 0,
|
|
5766
|
+
"aria-activedescendant": paletteEnabled && palette.open ? `${listboxId}-option-${palette.highlight}` : void 0,
|
|
5767
|
+
className: cn(
|
|
5768
|
+
// Font size steps up to 16px below `md` so iOS never zooms the
|
|
5769
|
+
// viewport on focus; desktop keeps the 15px og-md rhythm.
|
|
5770
|
+
"block w-full resize-none bg-transparent px-4 pt-3.5 pb-1 text-base leading-6 md:text-og-md",
|
|
5771
|
+
// The wrapper owns the whole-composer focus affordance (focus-within
|
|
5772
|
+
// border + soft glow). Suppress any self-scoped focus outline on the
|
|
5773
|
+
// textarea itself: `focus:outline-none` alone only sets outline-style
|
|
5774
|
+
// on `:focus`, which a host app's zero-specificity
|
|
5775
|
+
// `:where(...):focus-visible { outline: ... }` base rule re-applies as
|
|
5776
|
+
// the full shorthand. `focus-visible:outline-none` matches the same
|
|
5777
|
+
// state at class specificity and wins, so no second highlight (the
|
|
5778
|
+
// top-half rectangle bounded to the textarea box) ever paints.
|
|
5779
|
+
"text-og-fg placeholder:text-og-fg-subtle focus:outline-none focus-visible:outline-none",
|
|
5780
|
+
"disabled:cursor-not-allowed disabled:opacity-60"
|
|
5781
|
+
)
|
|
5782
|
+
}
|
|
5783
|
+
),
|
|
5784
|
+
confirmState && pendingDangerCommand ? /* @__PURE__ */ jsx12(
|
|
5785
|
+
ConfirmBar,
|
|
5786
|
+
{
|
|
5787
|
+
command: pendingDangerCommand,
|
|
5788
|
+
onCancel: () => confirmState.resolve(false),
|
|
5789
|
+
onConfirm: () => confirmState.resolve(true),
|
|
5790
|
+
returnFocusRef: textareaRef
|
|
5791
|
+
}
|
|
5792
|
+
) : /* @__PURE__ */ jsxs10("div", { className: "flex items-end gap-2 px-2.5 pb-2.5 pt-1", children: [
|
|
5793
|
+
attachments || models || controlsStart ? (
|
|
5794
|
+
// The control group wraps onto extra rows when it can't fit
|
|
5795
|
+
// (narrow viewports) instead of clipping under the rounded
|
|
5796
|
+
// corner; send/stop stays anchored bottom-right (shrink-0).
|
|
5797
|
+
/* @__PURE__ */ jsxs10("span", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-1.5", children: [
|
|
5798
|
+
attachments ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
5799
|
+
/* @__PURE__ */ jsx12(
|
|
5800
|
+
"input",
|
|
5801
|
+
{
|
|
5802
|
+
ref: fileInputRef,
|
|
5803
|
+
type: "file",
|
|
5804
|
+
multiple: true,
|
|
5805
|
+
className: "hidden",
|
|
5806
|
+
onChange: handleFileChange
|
|
5807
|
+
}
|
|
5808
|
+
),
|
|
5809
|
+
/* @__PURE__ */ jsx12(
|
|
5810
|
+
"button",
|
|
5811
|
+
{
|
|
5812
|
+
type: "button",
|
|
5813
|
+
disabled: disabled === true,
|
|
5814
|
+
onClick: () => fileInputRef.current?.click(),
|
|
5815
|
+
"aria-label": "Attach files",
|
|
5816
|
+
title: "Attach files",
|
|
5817
|
+
className: cn(
|
|
5818
|
+
"inline-flex size-8 items-center justify-center rounded-og-md",
|
|
5819
|
+
"text-og-fg-muted transition-colors duration-150 hover:bg-og-surface-2 hover:text-og-fg",
|
|
5820
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
5821
|
+
),
|
|
5822
|
+
children: /* @__PURE__ */ jsx12(PaperclipIcon, { className: "size-4" })
|
|
5823
|
+
}
|
|
5824
|
+
)
|
|
5825
|
+
] }) : null,
|
|
5826
|
+
models ? /* @__PURE__ */ jsx12(
|
|
5827
|
+
ModelPicker,
|
|
5828
|
+
{
|
|
5829
|
+
models,
|
|
5830
|
+
value: selectedModel,
|
|
5831
|
+
onChange: (modelId) => onSelectModel?.(modelId),
|
|
5832
|
+
disabled: disabled === true
|
|
5833
|
+
}
|
|
5834
|
+
) : null,
|
|
5835
|
+
controlsStart
|
|
5836
|
+
] })
|
|
5837
|
+
) : /* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1 px-1.5 text-og-xs text-og-fg-subtle max-sm:hidden", children: hint ?? "Enter to send \xB7 Shift+Enter for a new line \xB7 / for commands" }),
|
|
5838
|
+
/* @__PURE__ */ jsxs10("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
5839
|
+
/* @__PURE__ */ jsx12(AnimatePresence3, { initial: false, children: active ? /* @__PURE__ */ jsx12(
|
|
5840
|
+
motion3.button,
|
|
5841
|
+
{
|
|
5842
|
+
type: "button",
|
|
5843
|
+
initial: { opacity: 0, scale: 0.8 },
|
|
5844
|
+
animate: { opacity: 1, scale: 1 },
|
|
5845
|
+
exit: { opacity: 0, scale: 0.8 },
|
|
5846
|
+
transition: { duration: 0.15, ease: "easeOut" },
|
|
5847
|
+
onClick: () => void composer.interrupt(),
|
|
5848
|
+
disabled: composer.interrupting,
|
|
5849
|
+
"aria-label": "Stop the current turn",
|
|
5850
|
+
title: "Stop the current turn",
|
|
5851
|
+
className: cn(
|
|
5852
|
+
"inline-flex size-8 items-center justify-center rounded-og-md border border-og-border pointer-coarse:size-11",
|
|
5853
|
+
"bg-og-surface-2 text-og-fg-muted transition-colors duration-150",
|
|
5854
|
+
"hover:border-og-status-failed/50 hover:text-og-status-failed",
|
|
5855
|
+
"disabled:opacity-50"
|
|
5856
|
+
),
|
|
5857
|
+
children: composer.interrupting ? /* @__PURE__ */ jsx12(LoaderCircleIcon, { className: "size-3.5 animate-og-spin" }) : /* @__PURE__ */ jsx12(SquareIcon, { className: "size-3 fill-current" })
|
|
5858
|
+
},
|
|
5859
|
+
"stop"
|
|
5860
|
+
) : null }),
|
|
5648
5861
|
/* @__PURE__ */ jsx12(
|
|
5649
5862
|
"button",
|
|
5650
5863
|
{
|
|
5651
5864
|
type: "button",
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5865
|
+
onClick: () => {
|
|
5866
|
+
if (blockedByUpload) {
|
|
5867
|
+
return;
|
|
5868
|
+
}
|
|
5869
|
+
void composer.send();
|
|
5870
|
+
},
|
|
5871
|
+
disabled: !canSend || disabled === true || commandDraftBlocked,
|
|
5872
|
+
"aria-label": "Send message",
|
|
5656
5873
|
className: cn(
|
|
5657
|
-
"inline-flex size-8 items-center justify-center rounded-og-md",
|
|
5658
|
-
"
|
|
5659
|
-
"
|
|
5874
|
+
"inline-flex size-8 items-center justify-center rounded-og-md pointer-coarse:size-11",
|
|
5875
|
+
"bg-og-accent text-og-accent-fg shadow-og-sm",
|
|
5876
|
+
"transition-[background-color,transform,opacity] duration-150 ease-og-spring",
|
|
5877
|
+
"hover:bg-og-accent-strong active:scale-95",
|
|
5878
|
+
"disabled:cursor-not-allowed disabled:bg-og-surface-3 disabled:text-og-fg-subtle disabled:shadow-none"
|
|
5660
5879
|
),
|
|
5661
|
-
children: /* @__PURE__ */ jsx12(
|
|
5880
|
+
children: composer.sending ? /* @__PURE__ */ jsx12(LoaderCircleIcon, { className: "size-4 animate-og-spin" }) : /* @__PURE__ */ jsx12(ArrowUpIcon, { className: "size-4" })
|
|
5662
5881
|
}
|
|
5663
5882
|
)
|
|
5664
|
-
] })
|
|
5665
|
-
models ? /* @__PURE__ */ jsx12(
|
|
5666
|
-
ModelPicker,
|
|
5667
|
-
{
|
|
5668
|
-
models,
|
|
5669
|
-
value: selectedModel,
|
|
5670
|
-
onChange: (modelId) => onSelectModel?.(modelId),
|
|
5671
|
-
disabled: disabled === true
|
|
5672
|
-
}
|
|
5673
|
-
) : null,
|
|
5674
|
-
controlsStart
|
|
5675
|
-
] }) : /* @__PURE__ */ jsx12("span", { className: "px-1.5 text-[11px] text-og-fg-subtle max-sm:hidden", children: hint ?? "Enter to send \xB7 Shift+Enter for a new line \xB7 / for commands" }),
|
|
5676
|
-
/* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-1.5", children: [
|
|
5677
|
-
/* @__PURE__ */ jsx12(AnimatePresence3, { initial: false, children: active ? /* @__PURE__ */ jsx12(
|
|
5678
|
-
motion3.button,
|
|
5679
|
-
{
|
|
5680
|
-
type: "button",
|
|
5681
|
-
initial: { opacity: 0, scale: 0.8 },
|
|
5682
|
-
animate: { opacity: 1, scale: 1 },
|
|
5683
|
-
exit: { opacity: 0, scale: 0.8 },
|
|
5684
|
-
transition: { duration: 0.15, ease: "easeOut" },
|
|
5685
|
-
onClick: () => void composer.interrupt(),
|
|
5686
|
-
disabled: composer.interrupting,
|
|
5687
|
-
"aria-label": "Stop the current turn",
|
|
5688
|
-
title: "Stop the current turn",
|
|
5689
|
-
className: cn(
|
|
5690
|
-
"inline-flex size-8 items-center justify-center rounded-og-md border border-og-border",
|
|
5691
|
-
"bg-og-surface-2 text-og-fg-muted transition-colors duration-150",
|
|
5692
|
-
"hover:border-og-status-failed/50 hover:text-og-status-failed",
|
|
5693
|
-
"disabled:opacity-50"
|
|
5694
|
-
),
|
|
5695
|
-
children: composer.interrupting ? /* @__PURE__ */ jsx12(LoaderCircleIcon, { className: "size-3.5 animate-og-spin" }) : /* @__PURE__ */ jsx12(SquareIcon, { className: "size-3 fill-current" })
|
|
5696
|
-
},
|
|
5697
|
-
"stop"
|
|
5698
|
-
) : null }),
|
|
5699
|
-
/* @__PURE__ */ jsx12(
|
|
5700
|
-
"button",
|
|
5701
|
-
{
|
|
5702
|
-
type: "button",
|
|
5703
|
-
onClick: () => {
|
|
5704
|
-
if (blockedByUpload) {
|
|
5705
|
-
return;
|
|
5706
|
-
}
|
|
5707
|
-
void composer.send();
|
|
5708
|
-
},
|
|
5709
|
-
disabled: !canSend || disabled === true || commandDraftBlocked,
|
|
5710
|
-
"aria-label": "Send message",
|
|
5711
|
-
className: cn(
|
|
5712
|
-
"inline-flex size-8 items-center justify-center rounded-og-md",
|
|
5713
|
-
"bg-og-accent text-og-accent-fg shadow-og-sm",
|
|
5714
|
-
"transition-[background-color,transform,opacity] duration-150 ease-og-spring",
|
|
5715
|
-
"hover:bg-og-accent-strong active:scale-95",
|
|
5716
|
-
"disabled:cursor-not-allowed disabled:bg-og-surface-3 disabled:text-og-fg-subtle disabled:shadow-none"
|
|
5717
|
-
),
|
|
5718
|
-
children: composer.sending ? /* @__PURE__ */ jsx12(LoaderCircleIcon, { className: "size-4 animate-og-spin" }) : /* @__PURE__ */ jsx12(ArrowUpIcon, { className: "size-4" })
|
|
5719
|
-
}
|
|
5720
|
-
)
|
|
5883
|
+
] })
|
|
5721
5884
|
] })
|
|
5722
|
-
]
|
|
5723
|
-
]
|
|
5724
|
-
}
|
|
5725
|
-
)
|
|
5726
|
-
] }),
|
|
5727
|
-
/* @__PURE__ */ jsx12(AnimatePresence3, { children: helpOpen ? /* @__PURE__ */ jsx12(HelpPanel, { commands: helpCommands, onClose: () => setHelpOpen(false) }) : null }),
|
|
5728
|
-
/* @__PURE__ */ jsx12(AnimatePresence3, { children: activeNotice ? /* @__PURE__ */ jsx12(
|
|
5729
|
-
motion3.p,
|
|
5730
|
-
{
|
|
5731
|
-
initial: { opacity: 0, height: 0 },
|
|
5732
|
-
animate: { opacity: 1, height: "auto" },
|
|
5733
|
-
exit: { opacity: 0, height: 0 },
|
|
5734
|
-
className: cn(
|
|
5735
|
-
"overflow-hidden px-1 pt-1.5 text-xs",
|
|
5736
|
-
activeNotice.tone === "ok" ? "text-og-fg-muted" : "text-og-status-failed"
|
|
5737
|
-
),
|
|
5738
|
-
role: activeNotice.tone === "error" ? "alert" : "status",
|
|
5739
|
-
onAnimationComplete: () => {
|
|
5740
|
-
if (activeNotice.tone === "ok") {
|
|
5741
|
-
window.setTimeout(() => setNotice((current) => current === activeNotice ? null : current), 2400);
|
|
5885
|
+
]
|
|
5742
5886
|
}
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
}
|
|
5746
|
-
|
|
5747
|
-
|
|
5887
|
+
)
|
|
5888
|
+
] }),
|
|
5889
|
+
/* @__PURE__ */ jsx12(AnimatePresence3, { children: helpOpen ? /* @__PURE__ */ jsx12(HelpPanel, { commands: helpCommands, onClose: () => setHelpOpen(false) }) : null }),
|
|
5890
|
+
/* @__PURE__ */ jsx12(AnimatePresence3, { children: activeNotice ? /* @__PURE__ */ jsx12(
|
|
5891
|
+
motion3.p,
|
|
5892
|
+
{
|
|
5893
|
+
initial: { opacity: 0, height: 0 },
|
|
5894
|
+
animate: { opacity: 1, height: "auto" },
|
|
5895
|
+
exit: { opacity: 0, height: 0 },
|
|
5896
|
+
className: cn(
|
|
5897
|
+
"overflow-hidden px-1 pt-1.5 text-xs",
|
|
5898
|
+
activeNotice.tone === "ok" ? "text-og-fg-muted" : "text-og-status-failed"
|
|
5899
|
+
),
|
|
5900
|
+
role: activeNotice.tone === "error" ? "alert" : "status",
|
|
5901
|
+
onAnimationComplete: () => {
|
|
5902
|
+
if (activeNotice.tone === "ok") {
|
|
5903
|
+
window.setTimeout(() => setNotice((current) => current === activeNotice ? null : current), 2400);
|
|
5904
|
+
}
|
|
5905
|
+
},
|
|
5906
|
+
children: activeNotice.message
|
|
5907
|
+
}
|
|
5908
|
+
) : null })
|
|
5909
|
+
] })
|
|
5910
|
+
);
|
|
5748
5911
|
}
|
|
5749
|
-
function ConfirmBar({
|
|
5912
|
+
function ConfirmBar({
|
|
5913
|
+
command,
|
|
5914
|
+
onCancel,
|
|
5915
|
+
onConfirm,
|
|
5916
|
+
returnFocusRef
|
|
5917
|
+
}) {
|
|
5918
|
+
const confirmRef = useRef14(null);
|
|
5919
|
+
const descriptionId = useId2();
|
|
5920
|
+
useEffect14(() => {
|
|
5921
|
+
const returnTo = returnFocusRef?.current ?? null;
|
|
5922
|
+
confirmRef.current?.focus();
|
|
5923
|
+
return () => {
|
|
5924
|
+
returnTo?.focus();
|
|
5925
|
+
};
|
|
5926
|
+
}, [returnFocusRef]);
|
|
5750
5927
|
return /* @__PURE__ */ jsxs10(
|
|
5751
5928
|
"div",
|
|
5752
5929
|
{
|
|
5753
5930
|
role: "alertdialog",
|
|
5754
5931
|
"aria-label": `Confirm /${command.name}`,
|
|
5932
|
+
"aria-describedby": descriptionId,
|
|
5755
5933
|
"data-testid": "danger-confirm",
|
|
5756
|
-
|
|
5934
|
+
onKeyDown: (event) => {
|
|
5935
|
+
if (event.key === "Escape") {
|
|
5936
|
+
event.preventDefault();
|
|
5937
|
+
event.stopPropagation();
|
|
5938
|
+
onCancel();
|
|
5939
|
+
}
|
|
5940
|
+
},
|
|
5941
|
+
className: "flex items-end justify-between gap-2 px-2.5 pb-2.5 pt-1",
|
|
5757
5942
|
children: [
|
|
5758
|
-
/* @__PURE__ */ jsxs10("span", { className: "px-1.5 text-
|
|
5943
|
+
/* @__PURE__ */ jsxs10("span", { id: descriptionId, className: "min-w-0 flex-1 px-1.5 text-og-sm text-og-status-failed", children: [
|
|
5759
5944
|
"Run ",
|
|
5760
5945
|
/* @__PURE__ */ jsxs10("span", { className: "font-mono", children: [
|
|
5761
5946
|
"/",
|
|
@@ -5764,24 +5949,27 @@ function ConfirmBar({ command, onCancel, onConfirm }) {
|
|
|
5764
5949
|
"? ",
|
|
5765
5950
|
command.description
|
|
5766
5951
|
] }),
|
|
5767
|
-
/* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-1.5", children: [
|
|
5952
|
+
/* @__PURE__ */ jsxs10("span", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
5768
5953
|
/* @__PURE__ */ jsx12(
|
|
5769
5954
|
"button",
|
|
5770
5955
|
{
|
|
5771
5956
|
type: "button",
|
|
5772
5957
|
onClick: onCancel,
|
|
5773
|
-
className: "rounded-og-md border border-og-border bg-og-surface-2 px-2.5 py-1 text-
|
|
5958
|
+
className: "rounded-og-md border border-og-border bg-og-surface-2 px-2.5 py-1 text-og-sm text-og-fg-muted hover:bg-og-surface-3 pointer-coarse:min-h-10",
|
|
5774
5959
|
children: "Cancel"
|
|
5775
5960
|
}
|
|
5776
5961
|
),
|
|
5777
|
-
/* @__PURE__ */
|
|
5962
|
+
/* @__PURE__ */ jsxs10(
|
|
5778
5963
|
"button",
|
|
5779
5964
|
{
|
|
5965
|
+
ref: confirmRef,
|
|
5780
5966
|
type: "button",
|
|
5781
|
-
autoFocus: true,
|
|
5782
5967
|
onClick: onConfirm,
|
|
5783
|
-
className: "rounded-og-md border border-og-status-failed/50 bg-og-status-failed/15 px-2.5 py-1 text-
|
|
5784
|
-
children:
|
|
5968
|
+
className: "rounded-og-md border border-og-status-failed/50 bg-og-status-failed/15 px-2.5 py-1 text-og-sm text-og-status-failed hover:bg-og-status-failed/25 pointer-coarse:min-h-10",
|
|
5969
|
+
children: [
|
|
5970
|
+
"Run /",
|
|
5971
|
+
command.name
|
|
5972
|
+
]
|
|
5785
5973
|
}
|
|
5786
5974
|
)
|
|
5787
5975
|
] })
|
|
@@ -5789,44 +5977,57 @@ function ConfirmBar({ command, onCancel, onConfirm }) {
|
|
|
5789
5977
|
}
|
|
5790
5978
|
);
|
|
5791
5979
|
}
|
|
5792
|
-
function AttachmentChips({ attachments, onRemove }) {
|
|
5793
|
-
return /* @__PURE__ */ jsx12("div", { className: "flex flex-wrap gap-2 border-b border-og-border px-3 py-2", children: attachments.map((attachment) =>
|
|
5794
|
-
"
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5980
|
+
function AttachmentChips({ attachments, onRemove, onRetry }) {
|
|
5981
|
+
return /* @__PURE__ */ jsx12("div", { className: "flex flex-wrap gap-2 border-b border-og-border px-3 py-2", children: attachments.map((attachment) => {
|
|
5982
|
+
const failed = attachment.status === "failed";
|
|
5983
|
+
const statusText = attachment.status === "uploading" ? "Uploading" : failed ? attachment.error || "Upload failed" : formatBytes(attachment.sizeBytes);
|
|
5984
|
+
return /* @__PURE__ */ jsxs10(
|
|
5985
|
+
"div",
|
|
5986
|
+
{
|
|
5987
|
+
className: cn(
|
|
5988
|
+
"flex min-w-0 max-w-[240px] items-center gap-2 rounded-og-md border px-2 py-1.5 text-og-sm",
|
|
5989
|
+
failed ? "border-og-status-failed/40 bg-og-status-failed/10" : "border-og-border bg-og-surface-2"
|
|
5990
|
+
),
|
|
5991
|
+
children: [
|
|
5992
|
+
attachment.previewUrl ? /* @__PURE__ */ jsx12("img", { src: attachment.previewUrl, alt: "", className: "size-8 shrink-0 rounded object-cover" }) : attachment.contentType.startsWith("image/") ? /* @__PURE__ */ jsx12(ImageIcon2, { className: "size-4 shrink-0 text-og-fg-muted" }) : /* @__PURE__ */ jsx12(FileIcon, { className: "size-4 shrink-0 text-og-fg-muted" }),
|
|
5993
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
|
|
5994
|
+
/* @__PURE__ */ jsx12("div", { className: "truncate font-medium text-og-fg", children: attachment.name }),
|
|
5995
|
+
/* @__PURE__ */ jsx12(
|
|
5996
|
+
"div",
|
|
5997
|
+
{
|
|
5998
|
+
className: cn("truncate text-og-xs", failed ? "text-og-status-failed" : "text-og-fg-subtle"),
|
|
5999
|
+
title: failed ? statusText : void 0,
|
|
6000
|
+
children: statusText
|
|
6001
|
+
}
|
|
6002
|
+
)
|
|
6003
|
+
] }),
|
|
6004
|
+
attachment.status === "uploading" ? /* @__PURE__ */ jsx12(LoaderCircleIcon, { className: "size-3.5 shrink-0 animate-og-spin" }) : null,
|
|
6005
|
+
failed && onRetry ? /* @__PURE__ */ jsx12(
|
|
6006
|
+
"button",
|
|
6007
|
+
{
|
|
6008
|
+
type: "button",
|
|
6009
|
+
onClick: () => onRetry(attachment.id),
|
|
6010
|
+
className: "shrink-0 rounded-og-xs p-1 text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg pointer-coarse:size-8",
|
|
6011
|
+
"aria-label": `Retry ${attachment.name}`,
|
|
6012
|
+
title: "Retry upload",
|
|
6013
|
+
children: /* @__PURE__ */ jsx12(RotateCwIcon, { className: "size-3.5" })
|
|
6014
|
+
}
|
|
6015
|
+
) : null,
|
|
5804
6016
|
/* @__PURE__ */ jsx12(
|
|
5805
|
-
"
|
|
6017
|
+
"button",
|
|
5806
6018
|
{
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
children:
|
|
6019
|
+
type: "button",
|
|
6020
|
+
onClick: () => onRemove(attachment.id),
|
|
6021
|
+
className: "shrink-0 rounded-og-xs p-1 text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg pointer-coarse:size-8",
|
|
6022
|
+
"aria-label": `Remove ${attachment.name}`,
|
|
6023
|
+
children: /* @__PURE__ */ jsx12(XIcon2, { className: "size-3.5" })
|
|
5812
6024
|
}
|
|
5813
6025
|
)
|
|
5814
|
-
]
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
type: "button",
|
|
5820
|
-
onClick: () => onRemove(attachment.id),
|
|
5821
|
-
className: "shrink-0 rounded-og-xs p-1 text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg",
|
|
5822
|
-
"aria-label": `Remove ${attachment.name}`,
|
|
5823
|
-
children: /* @__PURE__ */ jsx12(XIcon2, { className: "size-3.5" })
|
|
5824
|
-
}
|
|
5825
|
-
)
|
|
5826
|
-
]
|
|
5827
|
-
},
|
|
5828
|
-
attachment.id
|
|
5829
|
-
)) });
|
|
6026
|
+
]
|
|
6027
|
+
},
|
|
6028
|
+
attachment.id
|
|
6029
|
+
);
|
|
6030
|
+
}) });
|
|
5830
6031
|
}
|
|
5831
6032
|
function HelpPanel({ commands, onClose }) {
|
|
5832
6033
|
return /* @__PURE__ */ jsxs10(
|
|
@@ -5838,19 +6039,19 @@ function HelpPanel({ commands, onClose }) {
|
|
|
5838
6039
|
className: "mt-2 overflow-hidden rounded-og-lg border border-og-border bg-og-surface-2",
|
|
5839
6040
|
children: [
|
|
5840
6041
|
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between border-b border-og-border px-3 py-1.5", children: [
|
|
5841
|
-
/* @__PURE__ */ jsx12("span", { className: "text-
|
|
5842
|
-
/* @__PURE__ */ jsx12("button", { type: "button", onClick: onClose, className: "text-
|
|
6042
|
+
/* @__PURE__ */ jsx12("span", { className: "text-og-sm font-medium text-og-fg", children: "Commands" }),
|
|
6043
|
+
/* @__PURE__ */ jsx12("button", { type: "button", onClick: onClose, className: "text-og-xs text-og-fg-subtle hover:text-og-fg", children: "Close" })
|
|
5843
6044
|
] }),
|
|
5844
6045
|
/* @__PURE__ */ jsx12("ul", { className: "py-1", children: commands.map((command) => {
|
|
5845
6046
|
const hint = argHint(command.args);
|
|
5846
6047
|
return /* @__PURE__ */ jsxs10("li", { className: "flex items-baseline gap-2 px-3 py-1", children: [
|
|
5847
|
-
/* @__PURE__ */ jsxs10("span", { className: "font-mono text-
|
|
6048
|
+
/* @__PURE__ */ jsxs10("span", { className: "font-mono text-og-sm text-og-accent", children: [
|
|
5848
6049
|
"/",
|
|
5849
6050
|
command.name,
|
|
5850
6051
|
hint ? /* @__PURE__ */ jsx12("span", { className: "ml-1 text-og-fg-subtle", children: hint }) : null
|
|
5851
6052
|
] }),
|
|
5852
|
-
/* @__PURE__ */ jsx12("span", { className: "text-
|
|
5853
|
-
command.danger ? /* @__PURE__ */ jsx12("span", { className: "ml-auto rounded-og-xs bg-og-status-failed/15 px-1 text-
|
|
6053
|
+
/* @__PURE__ */ jsx12("span", { className: "text-og-sm text-og-fg-muted", children: command.description }),
|
|
6054
|
+
command.danger ? /* @__PURE__ */ jsx12("span", { className: "ml-auto rounded-og-xs bg-og-status-failed/15 px-1 text-og-xs uppercase tracking-wide text-og-status-failed", children: "danger" }) : null
|
|
5854
6055
|
] }, command.name);
|
|
5855
6056
|
}) })
|
|
5856
6057
|
]
|
|
@@ -5870,7 +6071,7 @@ import {
|
|
|
5870
6071
|
TriangleAlertIcon as TriangleAlertIcon2
|
|
5871
6072
|
} from "lucide-react";
|
|
5872
6073
|
import { AnimatePresence as AnimatePresence4, motion as motion4 } from "motion/react";
|
|
5873
|
-
import { useEffect as useEffect15, useMemo as useMemo8, useRef as
|
|
6074
|
+
import { useCallback as useCallback21, useEffect as useEffect15, useMemo as useMemo8, useRef as useRef15, useState as useState22 } from "react";
|
|
5874
6075
|
|
|
5875
6076
|
// src/components/markdown.tsx
|
|
5876
6077
|
import { memo } from "react";
|
|
@@ -5880,8 +6081,8 @@ import { jsx as jsx13 } from "react/jsx-runtime";
|
|
|
5880
6081
|
var components = {
|
|
5881
6082
|
h1: ({ children, ...props }) => /* @__PURE__ */ jsx13("h1", { className: "mt-5 mb-2.5 text-xl font-semibold tracking-tight text-og-fg first:mt-0", ...props, children }),
|
|
5882
6083
|
h2: ({ children, ...props }) => /* @__PURE__ */ jsx13("h2", { className: "mt-5 mb-2 text-lg font-semibold tracking-tight text-og-fg first:mt-0", ...props, children }),
|
|
5883
|
-
h3: ({ children, ...props }) => /* @__PURE__ */ jsx13("h3", { className: "mt-4 mb-1.5 text-
|
|
5884
|
-
h4: ({ children, ...props }) => /* @__PURE__ */ jsx13("h4", { className: "mt-4 mb-1.5 text-sm font-semibold uppercase tracking-[0.04em] text-og-fg-muted first:mt-0", ...props, children }),
|
|
6084
|
+
h3: ({ children, ...props }) => /* @__PURE__ */ jsx13("h3", { className: "mt-4 mb-1.5 text-og-md font-semibold tracking-tight text-og-fg first:mt-0", ...props, children }),
|
|
6085
|
+
h4: ({ children, ...props }) => /* @__PURE__ */ jsx13("h4", { className: "mt-4 mb-1.5 text-og-sm font-semibold uppercase tracking-[0.04em] text-og-fg-muted first:mt-0", ...props, children }),
|
|
5885
6086
|
p: ({ children, ...props }) => /* @__PURE__ */ jsx13("p", { className: "my-2.5 leading-7 first:mt-0 last:mb-0", ...props, children }),
|
|
5886
6087
|
strong: ({ children, ...props }) => /* @__PURE__ */ jsx13("strong", { className: "font-semibold text-og-fg", ...props, children }),
|
|
5887
6088
|
em: ({ children, ...props }) => /* @__PURE__ */ jsx13("em", { className: "italic", ...props, children }),
|
|
@@ -5907,7 +6108,7 @@ var components = {
|
|
|
5907
6108
|
...props,
|
|
5908
6109
|
type: "checkbox",
|
|
5909
6110
|
disabled: true,
|
|
5910
|
-
className: "mr-2 size-3.5 translate-y-[2px] cursor-default
|
|
6111
|
+
className: "mr-2 size-3.5 translate-y-[2px] cursor-default accent-og-accent align-baseline"
|
|
5911
6112
|
}
|
|
5912
6113
|
) : /* @__PURE__ */ jsx13("input", { type, ...props }),
|
|
5913
6114
|
blockquote: ({ children, ...props }) => /* @__PURE__ */ jsx13(
|
|
@@ -5925,7 +6126,7 @@ var components = {
|
|
|
5925
6126
|
code: ({ children, className: _className, ...props }) => /* @__PURE__ */ jsx13(
|
|
5926
6127
|
"code",
|
|
5927
6128
|
{
|
|
5928
|
-
className: "rounded-og-xs border border-og-border bg-og-surface-1 px-1 py-0.5 font-og-mono text-
|
|
6129
|
+
className: "rounded-og-xs border border-og-border bg-og-surface-1 px-1 py-0.5 font-og-mono text-og-sm text-og-fg",
|
|
5929
6130
|
...props,
|
|
5930
6131
|
children
|
|
5931
6132
|
}
|
|
@@ -5935,12 +6136,12 @@ var components = {
|
|
|
5935
6136
|
pre: ({ children, ...props }) => /* @__PURE__ */ jsx13(
|
|
5936
6137
|
"pre",
|
|
5937
6138
|
{
|
|
5938
|
-
className: "my-3 max-h-96 overflow-auto rounded-og-md border border-og-border bg-og-bg/60 p-3 font-og-mono text-
|
|
6139
|
+
className: "my-3 max-h-96 overflow-auto rounded-og-md border border-og-border bg-og-bg/60 p-3 font-og-mono text-og-sm text-og-fg-muted [&>code]:border-0 [&>code]:bg-transparent [&>code]:p-0 [&>code]:text-inherit first:mt-0 last:mb-0",
|
|
5939
6140
|
...props,
|
|
5940
6141
|
children
|
|
5941
6142
|
}
|
|
5942
6143
|
),
|
|
5943
|
-
table: ({ children, ...props }) => /* @__PURE__ */ jsx13("div", { className: "my-3 max-w-full overflow-x-auto rounded-og-md border border-og-border first:mt-0 last:mb-0", children: /* @__PURE__ */ jsx13("table", { className: "w-full border-collapse text-
|
|
6144
|
+
table: ({ children, ...props }) => /* @__PURE__ */ jsx13("div", { className: "my-3 max-w-full overflow-x-auto rounded-og-md border border-og-border first:mt-0 last:mb-0", children: /* @__PURE__ */ jsx13("table", { className: "w-full border-collapse text-og-base", ...props, children }) }),
|
|
5944
6145
|
thead: ({ children, ...props }) => /* @__PURE__ */ jsx13("thead", { className: "bg-og-surface-1", ...props, children }),
|
|
5945
6146
|
th: ({ children, ...props }) => /* @__PURE__ */ jsx13("th", { className: "border-b border-og-border px-3 py-1.5 text-left font-medium text-og-fg", ...props, children }),
|
|
5946
6147
|
td: ({ children, ...props }) => /* @__PURE__ */ jsx13("td", { className: "border-b border-og-border px-3 py-1.5 align-top text-og-fg-muted [tr:last-child>&]:border-b-0", ...props, children }),
|
|
@@ -5977,7 +6178,7 @@ var SESSION_STATUS_META = {
|
|
|
5977
6178
|
pulse: false
|
|
5978
6179
|
},
|
|
5979
6180
|
requires_action: {
|
|
5980
|
-
label: "
|
|
6181
|
+
label: "Waiting on you",
|
|
5981
6182
|
dotClassName: "bg-og-status-waiting",
|
|
5982
6183
|
badgeClassName: "text-og-status-waiting border-og-status-waiting/35 bg-og-status-waiting/10",
|
|
5983
6184
|
pulse: true
|
|
@@ -6003,7 +6204,7 @@ function SessionStatus({ status, label, size = "md", className }) {
|
|
|
6003
6204
|
"data-status": status,
|
|
6004
6205
|
className: cn(
|
|
6005
6206
|
"og-root inline-flex shrink-0 items-center rounded-full border font-medium",
|
|
6006
|
-
size === "sm" ? "gap-1 px-1.5 py-px text-
|
|
6207
|
+
size === "sm" ? "gap-1 px-1.5 py-px text-og-xs" : "gap-1.5 px-2 py-0.5 text-xs",
|
|
6007
6208
|
meta.badgeClassName,
|
|
6008
6209
|
className
|
|
6009
6210
|
),
|
|
@@ -6034,23 +6235,74 @@ function MessageTimeline({
|
|
|
6034
6235
|
}) {
|
|
6035
6236
|
const resolvedItems = useMemo8(() => items ?? buildTimeline(events ?? []), [items, events]);
|
|
6036
6237
|
const groups = useMemo8(() => groupTimeline(resolvedItems), [resolvedItems]);
|
|
6037
|
-
const scrollRef =
|
|
6238
|
+
const scrollRef = useRef15(null);
|
|
6038
6239
|
const [pinned, setPinned] = useState22(true);
|
|
6240
|
+
const pinnedRef = useRef15(true);
|
|
6241
|
+
const anchorRef = useRef15(null);
|
|
6039
6242
|
const lastItem = resolvedItems[resolvedItems.length - 1];
|
|
6040
6243
|
const streaming = lastItem !== void 0 && (lastItem.kind === "agent-message" || lastItem.kind === "reasoning") && lastItem.streaming;
|
|
6041
6244
|
const working = status === "running" && !streaming;
|
|
6245
|
+
const captureAnchor = useCallback21(() => {
|
|
6246
|
+
const node = scrollRef.current;
|
|
6247
|
+
const inner = node?.firstElementChild;
|
|
6248
|
+
if (!node || !inner) {
|
|
6249
|
+
anchorRef.current = null;
|
|
6250
|
+
return;
|
|
6251
|
+
}
|
|
6252
|
+
const containerTop = node.getBoundingClientRect().top;
|
|
6253
|
+
for (const child of Array.from(inner.children)) {
|
|
6254
|
+
const rect = child.getBoundingClientRect();
|
|
6255
|
+
if (rect.bottom > containerTop + 1) {
|
|
6256
|
+
anchorRef.current = { el: child, top: rect.top - containerTop };
|
|
6257
|
+
return;
|
|
6258
|
+
}
|
|
6259
|
+
}
|
|
6260
|
+
anchorRef.current = null;
|
|
6261
|
+
}, []);
|
|
6042
6262
|
useEffect15(() => {
|
|
6043
6263
|
const node = scrollRef.current;
|
|
6044
6264
|
if (node && autoFollow && pinned) {
|
|
6045
6265
|
node.scrollTop = node.scrollHeight;
|
|
6046
6266
|
}
|
|
6047
6267
|
}, [resolvedItems, working, autoFollow, pinned]);
|
|
6268
|
+
useEffect15(() => {
|
|
6269
|
+
const node = scrollRef.current;
|
|
6270
|
+
const inner = node?.firstElementChild;
|
|
6271
|
+
if (!node || !inner || typeof ResizeObserver === "undefined") {
|
|
6272
|
+
return;
|
|
6273
|
+
}
|
|
6274
|
+
const observer = new ResizeObserver(() => {
|
|
6275
|
+
const current = scrollRef.current;
|
|
6276
|
+
if (!current) {
|
|
6277
|
+
return;
|
|
6278
|
+
}
|
|
6279
|
+
if (autoFollow && pinnedRef.current) {
|
|
6280
|
+
current.scrollTop = current.scrollHeight;
|
|
6281
|
+
} else {
|
|
6282
|
+
const anchor = anchorRef.current;
|
|
6283
|
+
if (anchor && anchor.el.isConnected) {
|
|
6284
|
+
const containerTop = current.getBoundingClientRect().top;
|
|
6285
|
+
const now = anchor.el.getBoundingClientRect().top - containerTop;
|
|
6286
|
+
const diff = now - anchor.top;
|
|
6287
|
+
if (diff !== 0) {
|
|
6288
|
+
current.scrollTop += diff;
|
|
6289
|
+
}
|
|
6290
|
+
}
|
|
6291
|
+
}
|
|
6292
|
+
captureAnchor();
|
|
6293
|
+
});
|
|
6294
|
+
observer.observe(inner);
|
|
6295
|
+
return () => observer.disconnect();
|
|
6296
|
+
}, [autoFollow, captureAnchor]);
|
|
6048
6297
|
const onScroll = () => {
|
|
6049
6298
|
const node = scrollRef.current;
|
|
6050
6299
|
if (!node) {
|
|
6051
6300
|
return;
|
|
6052
6301
|
}
|
|
6053
|
-
|
|
6302
|
+
const nextPinned = node.scrollHeight - node.scrollTop - node.clientHeight < 48;
|
|
6303
|
+
pinnedRef.current = nextPinned;
|
|
6304
|
+
setPinned(nextPinned);
|
|
6305
|
+
captureAnchor();
|
|
6054
6306
|
};
|
|
6055
6307
|
return /* @__PURE__ */ jsx15(LightboxProvider, { children: /* @__PURE__ */ jsxs12("div", { className: cn("og-root relative flex min-h-0 flex-col", className), children: [
|
|
6056
6308
|
/* @__PURE__ */ jsx15("div", { ref: scrollRef, onScroll, className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 sm:px-6", children: /* @__PURE__ */ jsxs12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: [
|
|
@@ -6080,6 +6332,7 @@ function MessageTimeline({
|
|
|
6080
6332
|
if (node) {
|
|
6081
6333
|
node.scrollTo({ top: node.scrollHeight, behavior: "smooth" });
|
|
6082
6334
|
}
|
|
6335
|
+
pinnedRef.current = true;
|
|
6083
6336
|
setPinned(true);
|
|
6084
6337
|
},
|
|
6085
6338
|
className: cn(
|
|
@@ -6302,11 +6555,11 @@ function FleetTile({ session, title, subtitle, onOpen, className }) {
|
|
|
6302
6555
|
}
|
|
6303
6556
|
),
|
|
6304
6557
|
/* @__PURE__ */ jsxs13("span", { className: "flex w-full items-start justify-between gap-3", children: [
|
|
6305
|
-
/* @__PURE__ */ jsx16("span", { className: "line-clamp-2 min-w-0 text-
|
|
6558
|
+
/* @__PURE__ */ jsx16("span", { className: "line-clamp-2 min-w-0 text-og-base font-medium leading-snug text-og-fg", children: title ?? sessionDisplayTitle(session) }),
|
|
6306
6559
|
/* @__PURE__ */ jsx16(SessionStatus, { status: session.status, size: "sm", className: "mt-px" })
|
|
6307
6560
|
] }),
|
|
6308
|
-
subtitle ? /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-
|
|
6309
|
-
/* @__PURE__ */ jsxs13("span", { className: "mt-auto flex w-full items-center gap-2 text-
|
|
6561
|
+
subtitle ? /* @__PURE__ */ jsx16("span", { className: "line-clamp-1 text-og-sm text-og-fg-muted", children: subtitle }) : null,
|
|
6562
|
+
/* @__PURE__ */ jsxs13("span", { className: "mt-auto flex w-full items-center gap-2 text-og-xs text-og-fg-subtle", children: [
|
|
6310
6563
|
/* @__PURE__ */ jsx16("span", { className: "font-og-mono", children: session.id.slice(0, 8) }),
|
|
6311
6564
|
/* @__PURE__ */ jsx16("span", { "aria-hidden": true, children: "\xB7" }),
|
|
6312
6565
|
/* @__PURE__ */ jsx16("span", { className: "truncate", children: session.model }),
|
|
@@ -6318,7 +6571,7 @@ function FleetTile({ session, title, subtitle, onOpen, className }) {
|
|
|
6318
6571
|
}
|
|
6319
6572
|
|
|
6320
6573
|
// src/components/sandbox-terminal.tsx
|
|
6321
|
-
import { useEffect as useEffect16, useRef as
|
|
6574
|
+
import { useEffect as useEffect16, useRef as useRef16, useState as useState23 } from "react";
|
|
6322
6575
|
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
6323
6576
|
function SandboxTerminal({
|
|
6324
6577
|
result,
|
|
@@ -6333,13 +6586,13 @@ function SandboxTerminal({
|
|
|
6333
6586
|
onActivate,
|
|
6334
6587
|
className
|
|
6335
6588
|
}) {
|
|
6336
|
-
const containerRef =
|
|
6337
|
-
const termRef =
|
|
6338
|
-
const fitRef =
|
|
6339
|
-
const writtenRef =
|
|
6589
|
+
const containerRef = useRef16(null);
|
|
6590
|
+
const termRef = useRef16(null);
|
|
6591
|
+
const fitRef = useRef16(null);
|
|
6592
|
+
const writtenRef = useRef16(/* @__PURE__ */ new Set());
|
|
6340
6593
|
const [ready, setReady] = useState23(false);
|
|
6341
6594
|
const ptyWs = terminalCapability?.transport === "pty-ws" && Boolean(terminalCapability?.url);
|
|
6342
|
-
const ptyOutputQueueRef =
|
|
6595
|
+
const ptyOutputQueueRef = useRef16([]);
|
|
6343
6596
|
const ptyStream = useTerminalStream({
|
|
6344
6597
|
capability: ptyWs ? {
|
|
6345
6598
|
transport: terminalCapability.transport,
|
|
@@ -6387,7 +6640,7 @@ function SandboxTerminal({
|
|
|
6387
6640
|
convertEol: true,
|
|
6388
6641
|
disableStdin: !interactive,
|
|
6389
6642
|
cursorBlink: interactive,
|
|
6390
|
-
fontFamily: fontFamily ?? "var(--og-font-mono
|
|
6643
|
+
fontFamily: fontFamily ?? "var(--og-font-mono)",
|
|
6391
6644
|
fontSize: fontSize ?? 13,
|
|
6392
6645
|
lineHeight: 1.25,
|
|
6393
6646
|
// A little breathing room from the panel edge so output isn't flush to
|
|
@@ -6434,7 +6687,7 @@ function SandboxTerminal({
|
|
|
6434
6687
|
if (!ready || !term || !theme) return;
|
|
6435
6688
|
term.options.theme = theme;
|
|
6436
6689
|
}, [ready, theme]);
|
|
6437
|
-
const enteredPtyRef =
|
|
6690
|
+
const enteredPtyRef = useRef16(false);
|
|
6438
6691
|
useEffect16(() => {
|
|
6439
6692
|
const term = termRef.current;
|
|
6440
6693
|
if (!ready || !term) return;
|
|
@@ -6490,24 +6743,24 @@ function SandboxTerminal({
|
|
|
6490
6743
|
};
|
|
6491
6744
|
}, [ready]);
|
|
6492
6745
|
return /* @__PURE__ */ jsxs14("div", { className: cn("relative flex h-full w-full flex-col overflow-hidden", className), children: [
|
|
6493
|
-
showHeader && /* @__PURE__ */ jsxs14("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-
|
|
6746
|
+
showHeader && /* @__PURE__ */ jsxs14("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-og-border px-2 py-1 text-og-xs text-og-fg-subtle", children: [
|
|
6494
6747
|
/* @__PURE__ */ jsxs14("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
6495
6748
|
/* @__PURE__ */ jsx17(
|
|
6496
6749
|
"span",
|
|
6497
6750
|
{
|
|
6498
6751
|
className: cn(
|
|
6499
6752
|
"size-1.5 shrink-0 rounded-full",
|
|
6500
|
-
result.running ? "bg-
|
|
6753
|
+
result.running ? "bg-og-status-running" : "bg-og-fg-subtle"
|
|
6501
6754
|
)
|
|
6502
6755
|
}
|
|
6503
6756
|
),
|
|
6504
|
-
/* @__PURE__ */ jsxs14("span", { className: "truncate font-
|
|
6757
|
+
/* @__PURE__ */ jsxs14("span", { className: "truncate font-og-mono", children: [
|
|
6505
6758
|
"pty: ",
|
|
6506
6759
|
shell ?? "shell"
|
|
6507
6760
|
] })
|
|
6508
6761
|
] }),
|
|
6509
6762
|
/* @__PURE__ */ jsxs14("span", { className: "flex shrink-0 items-center gap-2", children: [
|
|
6510
|
-
!interactive && /* @__PURE__ */ jsx17("span", { className: "rounded-
|
|
6763
|
+
!interactive && /* @__PURE__ */ jsx17("span", { className: "rounded-og-sm bg-og-surface-2 px-1.5 py-0.5 text-og-xs uppercase tracking-wide", children: "read-only" }),
|
|
6511
6764
|
/* @__PURE__ */ jsx17(
|
|
6512
6765
|
"button",
|
|
6513
6766
|
{
|
|
@@ -6516,7 +6769,7 @@ function SandboxTerminal({
|
|
|
6516
6769
|
termRef.current?.clear();
|
|
6517
6770
|
writtenRef.current = /* @__PURE__ */ new Set();
|
|
6518
6771
|
},
|
|
6519
|
-
className: "rounded-
|
|
6772
|
+
className: "rounded-og-sm px-1.5 py-0.5 text-og-xs hover:text-og-fg pointer-coarse:min-h-10",
|
|
6520
6773
|
children: "Clear"
|
|
6521
6774
|
}
|
|
6522
6775
|
)
|
|
@@ -6525,7 +6778,7 @@ function SandboxTerminal({
|
|
|
6525
6778
|
/* @__PURE__ */ jsxs14(
|
|
6526
6779
|
"div",
|
|
6527
6780
|
{
|
|
6528
|
-
className: "relative min-h-0 flex-1 bg-
|
|
6781
|
+
className: "relative min-h-0 flex-1 bg-og-bg px-2 py-1.5",
|
|
6529
6782
|
onPointerDownCapture: onActivate,
|
|
6530
6783
|
onFocusCapture: onActivate,
|
|
6531
6784
|
children: [
|
|
@@ -6542,7 +6795,7 @@ var XTERM_BASE_CSS = `
|
|
|
6542
6795
|
.xterm.focus,.xterm:focus{outline:none}
|
|
6543
6796
|
.xterm .xterm-helpers{position:absolute;top:0;z-index:5}
|
|
6544
6797
|
.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}
|
|
6545
|
-
.xterm .composition-view{background
|
|
6798
|
+
.xterm .composition-view{background:var(--og-color-bg);color:var(--og-color-fg);display:none;position:absolute;white-space:nowrap;z-index:1}
|
|
6546
6799
|
.xterm .composition-view.active{display:block}
|
|
6547
6800
|
.xterm .xterm-viewport{background-color:transparent;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}
|
|
6548
6801
|
.xterm .xterm-screen{position:relative}
|
|
@@ -6578,7 +6831,7 @@ function ensureXtermBaseCss() {
|
|
|
6578
6831
|
document.head.appendChild(style);
|
|
6579
6832
|
}
|
|
6580
6833
|
function TerminalPlaceholder() {
|
|
6581
|
-
return /* @__PURE__ */ jsx17("div", { className: "absolute inset-0 flex items-center justify-center text-
|
|
6834
|
+
return /* @__PURE__ */ jsx17("div", { className: "absolute inset-0 flex items-center justify-center text-og-sm text-og-fg-subtle", children: "Loading terminal\u2026" });
|
|
6582
6835
|
}
|
|
6583
6836
|
|
|
6584
6837
|
// src/components/file-browser.tsx
|
|
@@ -6594,19 +6847,19 @@ import {
|
|
|
6594
6847
|
Trash2Icon
|
|
6595
6848
|
} from "lucide-react";
|
|
6596
6849
|
import {
|
|
6597
|
-
useCallback as
|
|
6850
|
+
useCallback as useCallback22,
|
|
6598
6851
|
useEffect as useEffect17,
|
|
6599
6852
|
useMemo as useMemo9,
|
|
6600
|
-
useRef as
|
|
6853
|
+
useRef as useRef17,
|
|
6601
6854
|
useState as useState24
|
|
6602
6855
|
} from "react";
|
|
6603
6856
|
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
6604
6857
|
var STATUS_TINT = {
|
|
6605
|
-
added: "text-
|
|
6606
|
-
modified: "text-
|
|
6607
|
-
deleted: "text-
|
|
6608
|
-
renamed: "text-
|
|
6609
|
-
untracked: "text-
|
|
6858
|
+
added: "text-og-status-idle",
|
|
6859
|
+
modified: "text-og-status-running",
|
|
6860
|
+
deleted: "text-og-status-failed line-through",
|
|
6861
|
+
renamed: "text-og-accent",
|
|
6862
|
+
untracked: "text-og-fg-subtle"
|
|
6610
6863
|
};
|
|
6611
6864
|
function parentOf2(path) {
|
|
6612
6865
|
const i = path.lastIndexOf("/");
|
|
@@ -6644,9 +6897,9 @@ function FileBrowser({
|
|
|
6644
6897
|
const [dragOver, setDragOver] = useState24(null);
|
|
6645
6898
|
const [menu, setMenu] = useState24(null);
|
|
6646
6899
|
const [busy, setBusy] = useState24(false);
|
|
6647
|
-
const containerRef =
|
|
6900
|
+
const containerRef = useRef17(null);
|
|
6648
6901
|
const cursor = active ?? selectedPath ?? null;
|
|
6649
|
-
const expand =
|
|
6902
|
+
const expand = useCallback22(
|
|
6650
6903
|
async (path) => {
|
|
6651
6904
|
const node = findNode(result.tree, path);
|
|
6652
6905
|
if (node && node.kind === "dir" && node.children === void 0) {
|
|
@@ -6664,14 +6917,14 @@ function FileBrowser({
|
|
|
6664
6917
|
},
|
|
6665
6918
|
[result]
|
|
6666
6919
|
);
|
|
6667
|
-
const open =
|
|
6920
|
+
const open = useCallback22(
|
|
6668
6921
|
(path) => {
|
|
6669
6922
|
setExpanded((prev) => new Set(prev).add(path));
|
|
6670
6923
|
void expand(path);
|
|
6671
6924
|
},
|
|
6672
6925
|
[expand]
|
|
6673
6926
|
);
|
|
6674
|
-
const toggle =
|
|
6927
|
+
const toggle = useCallback22(
|
|
6675
6928
|
async (node) => {
|
|
6676
6929
|
if (node.kind !== "dir") return;
|
|
6677
6930
|
const isOpen = expanded.has(node.path);
|
|
@@ -6699,7 +6952,7 @@ function FileBrowser({
|
|
|
6699
6952
|
return rows;
|
|
6700
6953
|
}, [result.tree, expanded]);
|
|
6701
6954
|
const supportsMutation = editable;
|
|
6702
|
-
const runDelete =
|
|
6955
|
+
const runDelete = useCallback22(
|
|
6703
6956
|
async (node) => {
|
|
6704
6957
|
if (!supportsMutation) return;
|
|
6705
6958
|
const recursive = node.kind === "dir";
|
|
@@ -6718,7 +6971,7 @@ function FileBrowser({
|
|
|
6718
6971
|
},
|
|
6719
6972
|
[supportsMutation, confirmDelete, result]
|
|
6720
6973
|
);
|
|
6721
|
-
const commitCreate =
|
|
6974
|
+
const commitCreate = useCallback22(
|
|
6722
6975
|
async (name) => {
|
|
6723
6976
|
const draft = draftCreate;
|
|
6724
6977
|
setDraftCreate(null);
|
|
@@ -6743,7 +6996,7 @@ function FileBrowser({
|
|
|
6743
6996
|
},
|
|
6744
6997
|
[draftCreate, supportsMutation, result, open, onSelectFile]
|
|
6745
6998
|
);
|
|
6746
|
-
const commitRename =
|
|
6999
|
+
const commitRename = useCallback22(
|
|
6747
7000
|
async (name) => {
|
|
6748
7001
|
const draft = draftRename;
|
|
6749
7002
|
setDraftRename(null);
|
|
@@ -6766,7 +7019,7 @@ function FileBrowser({
|
|
|
6766
7019
|
},
|
|
6767
7020
|
[draftRename, supportsMutation, result, selectedPath, active, onSelectFile]
|
|
6768
7021
|
);
|
|
6769
|
-
const startCreate =
|
|
7022
|
+
const startCreate = useCallback22(
|
|
6770
7023
|
(kind) => {
|
|
6771
7024
|
if (!supportsMutation) return;
|
|
6772
7025
|
const anchor = cursor ? findNode(result.tree, cursor) : void 0;
|
|
@@ -6778,7 +7031,7 @@ function FileBrowser({
|
|
|
6778
7031
|
},
|
|
6779
7032
|
[supportsMutation, cursor, result.tree, open]
|
|
6780
7033
|
);
|
|
6781
|
-
const startRename =
|
|
7034
|
+
const startRename = useCallback22(
|
|
6782
7035
|
(node) => {
|
|
6783
7036
|
if (!supportsMutation) return;
|
|
6784
7037
|
setDraftCreate(null);
|
|
@@ -6787,7 +7040,7 @@ function FileBrowser({
|
|
|
6787
7040
|
},
|
|
6788
7041
|
[supportsMutation]
|
|
6789
7042
|
);
|
|
6790
|
-
const onDropOnto =
|
|
7043
|
+
const onDropOnto = useCallback22(
|
|
6791
7044
|
async (targetDir, sourcePath) => {
|
|
6792
7045
|
setDragOver(null);
|
|
6793
7046
|
if (!supportsMutation || !sourcePath) return;
|
|
@@ -6811,7 +7064,7 @@ function FileBrowser({
|
|
|
6811
7064
|
},
|
|
6812
7065
|
[supportsMutation, result, selectedPath, active, onSelectFile]
|
|
6813
7066
|
);
|
|
6814
|
-
const onKeyDown =
|
|
7067
|
+
const onKeyDown = useCallback22(
|
|
6815
7068
|
(e) => {
|
|
6816
7069
|
if (draftCreate || draftRename) return;
|
|
6817
7070
|
if (flatRows.length === 0) return;
|
|
@@ -6888,10 +7141,9 @@ function FileBrowser({
|
|
|
6888
7141
|
window.removeEventListener("resize", close);
|
|
6889
7142
|
};
|
|
6890
7143
|
}, [menu]);
|
|
6891
|
-
|
|
6892
|
-
return /* @__PURE__ */ jsx18("div", { className: cn("p-3 text-xs text-[color:var(--og-color-fg-subtle,var(--color-fg-subtle,#888))]", className), children: fallback ?? `Files unavailable: ${result.error.message}` });
|
|
6893
|
-
}
|
|
7144
|
+
const showErrorEmpty = result.error && result.tree.length === 0 && !draftCreate;
|
|
6894
7145
|
const showEmpty = !result.loading && result.tree.length === 0 && !draftCreate;
|
|
7146
|
+
const showToolbar = supportsMutation || Boolean(result.error) || result.loading;
|
|
6895
7147
|
const renderRow = (node, depth) => {
|
|
6896
7148
|
const isOpen = expanded.has(node.path);
|
|
6897
7149
|
if (renderNode) {
|
|
@@ -6959,11 +7211,11 @@ function FileBrowser({
|
|
|
6959
7211
|
setMenu({ node, x: e.clientX, y: e.clientY });
|
|
6960
7212
|
},
|
|
6961
7213
|
className: cn(
|
|
6962
|
-
"group flex w-full items-center gap-1 truncate rounded px-1 py-0.5 text-left text-
|
|
6963
|
-
"hover:bg-
|
|
6964
|
-
isSelected && "bg-
|
|
6965
|
-
isCursor && "outline outline-1 -outline-offset-1 outline-
|
|
6966
|
-
isDropTarget && "ring-1 ring-inset ring-
|
|
7214
|
+
"group flex w-full items-center gap-1 truncate rounded-og-sm px-1 py-0.5 text-left text-og-sm pointer-coarse:min-h-10",
|
|
7215
|
+
"hover:bg-og-surface-2",
|
|
7216
|
+
isSelected && "bg-og-surface-2",
|
|
7217
|
+
isCursor && "outline outline-1 -outline-offset-1 outline-og-accent",
|
|
7218
|
+
isDropTarget && "bg-og-accent-soft ring-1 ring-inset ring-og-accent",
|
|
6967
7219
|
node.status ? STATUS_TINT[node.status] : void 0
|
|
6968
7220
|
),
|
|
6969
7221
|
style: { paddingLeft: `${depth * 12 + 4}px` },
|
|
@@ -6971,7 +7223,7 @@ function FileBrowser({
|
|
|
6971
7223
|
isDir ? isLoading ? /* @__PURE__ */ jsx18(
|
|
6972
7224
|
Loader2Icon,
|
|
6973
7225
|
{
|
|
6974
|
-
className: "size-3 shrink-0 animate-spin text-
|
|
7226
|
+
className: "size-3 shrink-0 animate-spin text-og-fg-subtle",
|
|
6975
7227
|
"aria-label": "Loading"
|
|
6976
7228
|
}
|
|
6977
7229
|
) : /* @__PURE__ */ jsx18(ChevronRightIcon3, { className: cn("size-3 shrink-0 transition-transform", isOpen && "rotate-90") }) : /* @__PURE__ */ jsx18("span", { className: "inline-block w-3 shrink-0" }),
|
|
@@ -6990,7 +7242,7 @@ function FileBrowser({
|
|
|
6990
7242
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
6991
7243
|
setMenu({ node, x: rect.right, y: rect.bottom });
|
|
6992
7244
|
},
|
|
6993
|
-
className: "ml-auto hidden shrink-0 px-1 text-
|
|
7245
|
+
className: "ml-auto hidden shrink-0 px-1 text-og-fg-subtle hover:text-og-fg group-hover:inline",
|
|
6994
7246
|
children: "\u22EF"
|
|
6995
7247
|
}
|
|
6996
7248
|
)
|
|
@@ -7017,7 +7269,7 @@ function FileBrowser({
|
|
|
7017
7269
|
children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx18(
|
|
7018
7270
|
"div",
|
|
7019
7271
|
{
|
|
7020
|
-
className: "h-2.5 animate-pulse rounded bg-
|
|
7272
|
+
className: "h-2.5 animate-pulse rounded-og-sm bg-og-surface-2",
|
|
7021
7273
|
style: { width: `${70 - i * 12}%` }
|
|
7022
7274
|
},
|
|
7023
7275
|
i
|
|
@@ -7031,33 +7283,35 @@ function FileBrowser({
|
|
|
7031
7283
|
);
|
|
7032
7284
|
};
|
|
7033
7285
|
return /* @__PURE__ */ jsxs15("div", { className: cn("flex min-w-0 flex-col", className), children: [
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7286
|
+
showToolbar && /* @__PURE__ */ jsxs15("div", { className: "flex shrink-0 flex-wrap items-center gap-0.5 border-b border-og-border px-1 py-1", children: [
|
|
7287
|
+
supportsMutation ? /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
7288
|
+
/* @__PURE__ */ jsx18(ToolbarButton, { label: "New file", onClick: () => startCreate("file"), disabled: busy, children: /* @__PURE__ */ jsx18(FilePlusIcon, { className: "size-3.5" }) }),
|
|
7289
|
+
/* @__PURE__ */ jsx18(ToolbarButton, { label: "New folder", onClick: () => startCreate("dir"), disabled: busy, children: /* @__PURE__ */ jsx18(FolderPlusIcon, { className: "size-3.5" }) }),
|
|
7290
|
+
/* @__PURE__ */ jsx18(
|
|
7291
|
+
ToolbarButton,
|
|
7292
|
+
{
|
|
7293
|
+
label: "Rename",
|
|
7294
|
+
onClick: () => {
|
|
7295
|
+
const node = cursor ? findNode(result.tree, cursor) : void 0;
|
|
7296
|
+
if (node) startRename(node);
|
|
7297
|
+
},
|
|
7298
|
+
disabled: busy || !cursor,
|
|
7299
|
+
children: /* @__PURE__ */ jsx18(PencilIcon, { className: "size-3.5" })
|
|
7300
|
+
}
|
|
7301
|
+
),
|
|
7302
|
+
/* @__PURE__ */ jsx18(
|
|
7303
|
+
ToolbarButton,
|
|
7304
|
+
{
|
|
7305
|
+
label: "Delete",
|
|
7306
|
+
onClick: () => {
|
|
7307
|
+
const node = cursor ? findNode(result.tree, cursor) : void 0;
|
|
7308
|
+
if (node) void runDelete(node);
|
|
7309
|
+
},
|
|
7310
|
+
disabled: busy || !cursor,
|
|
7311
|
+
children: /* @__PURE__ */ jsx18(Trash2Icon, { className: "size-3.5" })
|
|
7312
|
+
}
|
|
7313
|
+
)
|
|
7314
|
+
] }) : null,
|
|
7061
7315
|
/* @__PURE__ */ jsx18("span", { className: "ml-auto" }),
|
|
7062
7316
|
/* @__PURE__ */ jsx18(ToolbarButton, { label: "Refresh", onClick: () => void result.refresh(), disabled: busy || result.loading, children: /* @__PURE__ */ jsx18(RefreshCwIcon, { className: cn("size-3.5", result.loading && "animate-spin") }) })
|
|
7063
7317
|
] }),
|
|
@@ -7081,7 +7335,7 @@ function FileBrowser({
|
|
|
7081
7335
|
} : void 0,
|
|
7082
7336
|
className: cn(
|
|
7083
7337
|
"min-w-0 flex-1 overflow-auto p-1 outline-none",
|
|
7084
|
-
dragOver === "" && "ring-1 ring-inset ring-
|
|
7338
|
+
dragOver === "" && "ring-1 ring-inset ring-og-accent"
|
|
7085
7339
|
),
|
|
7086
7340
|
"data-opengeni-file-tree": true,
|
|
7087
7341
|
children: [
|
|
@@ -7095,7 +7349,22 @@ function FileBrowser({
|
|
|
7095
7349
|
onCancel: () => setDraftCreate(null)
|
|
7096
7350
|
}
|
|
7097
7351
|
),
|
|
7098
|
-
|
|
7352
|
+
showErrorEmpty ? /* @__PURE__ */ jsxs15("div", { className: "flex flex-col items-start gap-2 p-2 text-og-sm text-og-fg-subtle", children: [
|
|
7353
|
+
/* @__PURE__ */ jsx18("div", { children: fallback ?? `Could not load files: ${result.error?.message ?? "refresh the file list to try again"}` }),
|
|
7354
|
+
/* @__PURE__ */ jsxs15(
|
|
7355
|
+
"button",
|
|
7356
|
+
{
|
|
7357
|
+
type: "button",
|
|
7358
|
+
onClick: () => void result.refresh(),
|
|
7359
|
+
disabled: result.loading,
|
|
7360
|
+
className: "inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2 py-1 text-og-xs 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-10",
|
|
7361
|
+
children: [
|
|
7362
|
+
/* @__PURE__ */ jsx18(RefreshCwIcon, { className: cn("size-3.5", result.loading && "animate-spin"), "aria-hidden": true }),
|
|
7363
|
+
"Retry"
|
|
7364
|
+
]
|
|
7365
|
+
}
|
|
7366
|
+
)
|
|
7367
|
+
] }) : showEmpty ? /* @__PURE__ */ jsx18("div", { className: "p-2 text-og-sm text-og-fg-subtle", children: emptyState ?? "This directory is empty" }) : result.tree.map((node) => renderRow(node, 0))
|
|
7099
7368
|
]
|
|
7100
7369
|
}
|
|
7101
7370
|
),
|
|
@@ -7128,8 +7397,8 @@ function ToolbarButton({
|
|
|
7128
7397
|
onClick,
|
|
7129
7398
|
disabled,
|
|
7130
7399
|
className: cn(
|
|
7131
|
-
"inline-flex items-center justify-center rounded p-1 text-
|
|
7132
|
-
"hover:bg-
|
|
7400
|
+
"inline-flex items-center justify-center rounded-og-sm p-1 text-og-fg-muted pointer-coarse:min-h-10 pointer-coarse:min-w-10",
|
|
7401
|
+
"hover:bg-og-surface-2 hover:text-og-fg",
|
|
7133
7402
|
"disabled:cursor-not-allowed disabled:opacity-40"
|
|
7134
7403
|
),
|
|
7135
7404
|
children
|
|
@@ -7144,8 +7413,8 @@ function InlineInput({
|
|
|
7144
7413
|
onCancel
|
|
7145
7414
|
}) {
|
|
7146
7415
|
const [value, setValue] = useState24(initialValue);
|
|
7147
|
-
const ref =
|
|
7148
|
-
const doneRef =
|
|
7416
|
+
const ref = useRef17(null);
|
|
7417
|
+
const doneRef = useRef17(false);
|
|
7149
7418
|
useEffect17(() => {
|
|
7150
7419
|
const el = ref.current;
|
|
7151
7420
|
if (!el) return;
|
|
@@ -7184,8 +7453,8 @@ function InlineInput({
|
|
|
7184
7453
|
e.stopPropagation();
|
|
7185
7454
|
},
|
|
7186
7455
|
className: cn(
|
|
7187
|
-
"min-w-0 flex-1 rounded border bg-
|
|
7188
|
-
"border-
|
|
7456
|
+
"min-w-0 flex-1 rounded-og-sm border bg-og-bg px-1 py-0 text-og-sm",
|
|
7457
|
+
"border-og-accent text-og-fg",
|
|
7189
7458
|
"outline-none"
|
|
7190
7459
|
)
|
|
7191
7460
|
}
|
|
@@ -7215,9 +7484,9 @@ function ContextMenu({
|
|
|
7215
7484
|
onClick();
|
|
7216
7485
|
},
|
|
7217
7486
|
className: cn(
|
|
7218
|
-
"flex w-full items-center gap-2 px-2.5 py-1 text-left text-
|
|
7219
|
-
"hover:bg-
|
|
7220
|
-
danger ? "text-
|
|
7487
|
+
"flex w-full items-center gap-2 px-2.5 py-1 text-left text-og-sm pointer-coarse:min-h-10",
|
|
7488
|
+
"hover:bg-og-surface-2",
|
|
7489
|
+
danger ? "text-og-status-failed" : "text-og-fg"
|
|
7221
7490
|
),
|
|
7222
7491
|
children: [
|
|
7223
7492
|
icon,
|
|
@@ -7233,14 +7502,14 @@ function ContextMenu({
|
|
|
7233
7502
|
style: { left, top },
|
|
7234
7503
|
className: cn(
|
|
7235
7504
|
"fixed z-50 min-w-[160px] overflow-hidden rounded-md border py-1 shadow-lg",
|
|
7236
|
-
"border-
|
|
7237
|
-
"bg-
|
|
7505
|
+
"border-og-border",
|
|
7506
|
+
"bg-og-surface-1"
|
|
7238
7507
|
),
|
|
7239
7508
|
children: [
|
|
7240
7509
|
isDir && /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
7241
7510
|
item("New file", /* @__PURE__ */ jsx18(FilePlusIcon, { className: "size-3.5" }), onNewFile),
|
|
7242
7511
|
item("New folder", /* @__PURE__ */ jsx18(FolderPlusIcon, { className: "size-3.5" }), onNewFolder),
|
|
7243
|
-
/* @__PURE__ */ jsx18("div", { className: "my-1 h-px bg-
|
|
7512
|
+
/* @__PURE__ */ jsx18("div", { className: "my-1 h-px bg-og-border" })
|
|
7244
7513
|
] }),
|
|
7245
7514
|
item("Rename", /* @__PURE__ */ jsx18(PencilIcon, { className: "size-3.5" }), onRename),
|
|
7246
7515
|
item("Delete", /* @__PURE__ */ jsx18(Trash2Icon, { className: "size-3.5" }), onDelete, true)
|
|
@@ -7293,12 +7562,12 @@ function PierreFile({
|
|
|
7293
7562
|
themeType: themeType ?? "dark"
|
|
7294
7563
|
};
|
|
7295
7564
|
const pierreVars = {
|
|
7296
|
-
"--diffs-dark-bg": "var(--og-color-bg
|
|
7297
|
-
"--diffs-light-bg": "var(--og-color-bg
|
|
7298
|
-
"--diffs-bg-buffer-override": "var(--og-color-surface-1
|
|
7299
|
-
"--diffs-bg-separator-override": "var(--og-color-surface-1
|
|
7300
|
-
"--diffs-font-size": "
|
|
7301
|
-
"--diffs-line-height": "
|
|
7565
|
+
"--diffs-dark-bg": "var(--og-color-bg)",
|
|
7566
|
+
"--diffs-light-bg": "var(--og-color-bg)",
|
|
7567
|
+
"--diffs-bg-buffer-override": "var(--og-color-surface-1)",
|
|
7568
|
+
"--diffs-bg-separator-override": "var(--og-color-surface-1)",
|
|
7569
|
+
"--diffs-font-size": "var(--og-code-font-size)",
|
|
7570
|
+
"--diffs-line-height": "var(--og-code-line-height)"
|
|
7302
7571
|
};
|
|
7303
7572
|
return /* @__PURE__ */ jsx19("div", { className: cn("min-w-0", className), "data-opengeni-pierre-file": true, style: pierreVars, children: /* @__PURE__ */ jsx19(Suspense2, { fallback: loading ?? /* @__PURE__ */ jsx19(FileSkeleton, {}), children: /* @__PURE__ */ jsx19(
|
|
7304
7573
|
LazyFile,
|
|
@@ -7313,14 +7582,14 @@ function PlainFile({ name, contents }) {
|
|
|
7313
7582
|
return /* @__PURE__ */ jsx19(
|
|
7314
7583
|
"pre",
|
|
7315
7584
|
{
|
|
7316
|
-
className: "overflow-auto whitespace-pre p-2 font-
|
|
7585
|
+
className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg",
|
|
7317
7586
|
"data-file": name,
|
|
7318
7587
|
children: contents
|
|
7319
7588
|
}
|
|
7320
7589
|
);
|
|
7321
7590
|
}
|
|
7322
7591
|
function FileSkeleton() {
|
|
7323
|
-
return /* @__PURE__ */ jsx19("div", { className: "p-3 text-
|
|
7592
|
+
return /* @__PURE__ */ jsx19("div", { className: "p-3 text-og-sm text-og-fg-subtle", children: "Loading file\u2026" });
|
|
7324
7593
|
}
|
|
7325
7594
|
|
|
7326
7595
|
// src/components/code-editor.tsx
|
|
@@ -7328,10 +7597,10 @@ import { Loader2Icon as Loader2Icon2, SaveIcon } from "lucide-react";
|
|
|
7328
7597
|
import {
|
|
7329
7598
|
lazy as lazy3,
|
|
7330
7599
|
Suspense as Suspense3,
|
|
7331
|
-
useCallback as
|
|
7600
|
+
useCallback as useCallback23,
|
|
7332
7601
|
useEffect as useEffect19,
|
|
7333
7602
|
useMemo as useMemo10,
|
|
7334
|
-
useRef as
|
|
7603
|
+
useRef as useRef18,
|
|
7335
7604
|
useState as useState26
|
|
7336
7605
|
} from "react";
|
|
7337
7606
|
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
@@ -7400,7 +7669,7 @@ function CodeEditor({
|
|
|
7400
7669
|
const [saveError, setSaveError] = useState26(null);
|
|
7401
7670
|
const [savedTick, setSavedTick] = useState26(false);
|
|
7402
7671
|
const dirty = value !== baseline;
|
|
7403
|
-
const lastSeed =
|
|
7672
|
+
const lastSeed = useRef18({ path, contents: initialContents });
|
|
7404
7673
|
useEffect19(() => {
|
|
7405
7674
|
const seedChanged = lastSeed.current.path !== path || lastSeed.current.contents !== initialContents;
|
|
7406
7675
|
if (!seedChanged) return;
|
|
@@ -7443,9 +7712,9 @@ function CodeEditor({
|
|
|
7443
7712
|
cancelled = true;
|
|
7444
7713
|
};
|
|
7445
7714
|
}, [langKey]);
|
|
7446
|
-
const saveRef =
|
|
7715
|
+
const saveRef = useRef18(() => {
|
|
7447
7716
|
});
|
|
7448
|
-
const save =
|
|
7717
|
+
const save = useCallback23(async () => {
|
|
7449
7718
|
if (readOnly) return;
|
|
7450
7719
|
const snapshot = value;
|
|
7451
7720
|
if (snapshot === baseline) return;
|
|
@@ -7498,18 +7767,18 @@ function CodeEditor({
|
|
|
7498
7767
|
"data-opengeni-code-editor": true,
|
|
7499
7768
|
style: editorVars,
|
|
7500
7769
|
children: [
|
|
7501
|
-
/* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-2 border-b border-
|
|
7770
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-2 border-b border-og-border bg-og-surface-1 px-2 py-1", children: [
|
|
7502
7771
|
/* @__PURE__ */ jsx20(
|
|
7503
7772
|
"span",
|
|
7504
7773
|
{
|
|
7505
7774
|
className: cn(
|
|
7506
7775
|
"size-1.5 shrink-0 rounded-full transition-colors",
|
|
7507
|
-
readOnly ? "bg-transparent" : dirty ? "bg-
|
|
7776
|
+
readOnly ? "bg-transparent" : dirty ? "bg-og-status-running" : "bg-og-status-idle"
|
|
7508
7777
|
),
|
|
7509
7778
|
title: readOnly ? "read-only" : dirty ? "unsaved changes" : "saved"
|
|
7510
7779
|
}
|
|
7511
7780
|
),
|
|
7512
|
-
/* @__PURE__ */ jsxs16("span", { className: "truncate font-
|
|
7781
|
+
/* @__PURE__ */ jsxs16("span", { className: "truncate font-og-mono text-og-xs text-og-fg-muted", children: [
|
|
7513
7782
|
fileName,
|
|
7514
7783
|
dirty && !readOnly ? " \u2022" : ""
|
|
7515
7784
|
] }),
|
|
@@ -7517,21 +7786,21 @@ function CodeEditor({
|
|
|
7517
7786
|
saveError && /* @__PURE__ */ jsx20(
|
|
7518
7787
|
"span",
|
|
7519
7788
|
{
|
|
7520
|
-
className: "max-w-[220px] truncate text-
|
|
7789
|
+
className: "max-w-[220px] truncate text-og-xs text-og-status-failed",
|
|
7521
7790
|
title: saveError.message,
|
|
7522
7791
|
children: saveError.message
|
|
7523
7792
|
}
|
|
7524
7793
|
),
|
|
7525
|
-
!saveError && savedTick && /* @__PURE__ */ jsx20("span", { className: "text-
|
|
7526
|
-
readOnly ? /* @__PURE__ */ jsx20("span", { className: "text-
|
|
7794
|
+
!saveError && savedTick && /* @__PURE__ */ jsx20("span", { className: "text-og-xs text-og-status-idle", children: "Saved" }),
|
|
7795
|
+
readOnly ? /* @__PURE__ */ jsx20("span", { className: "text-og-xs uppercase tracking-wide text-og-fg-subtle", children: "Read-only" }) : /* @__PURE__ */ jsxs16(
|
|
7527
7796
|
"button",
|
|
7528
7797
|
{
|
|
7529
7798
|
type: "button",
|
|
7530
7799
|
onClick: () => void save(),
|
|
7531
7800
|
disabled: saving || !dirty,
|
|
7532
7801
|
className: cn(
|
|
7533
|
-
"flex items-center gap-1 rounded-
|
|
7534
|
-
saving || !dirty ? "cursor-default text-
|
|
7802
|
+
"flex items-center gap-1 rounded-og-sm border border-og-border px-1.5 py-0.5 text-og-xs pointer-coarse:min-h-10",
|
|
7803
|
+
saving || !dirty ? "cursor-default text-og-fg-subtle opacity-60" : "text-og-fg hover:bg-og-accent-soft"
|
|
7535
7804
|
),
|
|
7536
7805
|
title: "Save (\u2318/Ctrl+S)",
|
|
7537
7806
|
children: [
|
|
@@ -7552,7 +7821,7 @@ function CodeEditor({
|
|
|
7552
7821
|
basicSetup: true,
|
|
7553
7822
|
extensions: cmExtensions,
|
|
7554
7823
|
height: "100%",
|
|
7555
|
-
className: "og-cm-editor min-h-full text-
|
|
7824
|
+
className: "og-cm-editor min-h-full text-og-sm",
|
|
7556
7825
|
onChange: readOnly ? void 0 : (next) => {
|
|
7557
7826
|
setValue(next);
|
|
7558
7827
|
setSavedTick(false);
|
|
@@ -7564,8 +7833,8 @@ function CodeEditor({
|
|
|
7564
7833
|
);
|
|
7565
7834
|
}
|
|
7566
7835
|
var editorVars = {
|
|
7567
|
-
"--og-cm-bg": "var(--og-color-bg
|
|
7568
|
-
fontFamily: "var(--og-font-mono
|
|
7836
|
+
"--og-cm-bg": "var(--og-color-bg)",
|
|
7837
|
+
fontFamily: "var(--og-font-mono)"
|
|
7569
7838
|
};
|
|
7570
7839
|
function PlainTextarea({
|
|
7571
7840
|
value,
|
|
@@ -7579,28 +7848,28 @@ function PlainTextarea({
|
|
|
7579
7848
|
readOnly,
|
|
7580
7849
|
spellCheck: false,
|
|
7581
7850
|
onChange: (e) => onChange(e.target.value),
|
|
7582
|
-
className: "h-full w-full resize-none bg-transparent p-2 font-
|
|
7851
|
+
className: "h-full w-full resize-none bg-transparent p-2 font-og-mono text-og-sm text-og-fg outline-none"
|
|
7583
7852
|
}
|
|
7584
7853
|
);
|
|
7585
7854
|
}
|
|
7586
7855
|
function EditorSkeleton() {
|
|
7587
|
-
return /* @__PURE__ */ jsx20("div", { className: "p-3 text-
|
|
7856
|
+
return /* @__PURE__ */ jsx20("div", { className: "p-3 text-og-sm text-og-fg-subtle", children: "Loading editor\u2026" });
|
|
7588
7857
|
}
|
|
7589
7858
|
|
|
7590
7859
|
// src/components/sandbox-files.tsx
|
|
7591
7860
|
import { FileIcon as FileIcon3 } from "lucide-react";
|
|
7592
|
-
import { useCallback as
|
|
7861
|
+
import { useCallback as useCallback24, useEffect as useEffect20, useMemo as useMemo11, useRef as useRef19, useState as useState27 } from "react";
|
|
7593
7862
|
import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
7594
7863
|
var STATUS_TINT2 = {
|
|
7595
|
-
added: "text-
|
|
7596
|
-
modified: "text-
|
|
7597
|
-
deleted: "text-
|
|
7598
|
-
renamed: "text-
|
|
7599
|
-
copied: "text-
|
|
7600
|
-
untracked: "text-
|
|
7601
|
-
ignored: "text-
|
|
7602
|
-
conflicted: "text-
|
|
7603
|
-
typechange: "text-
|
|
7864
|
+
added: "text-og-status-idle",
|
|
7865
|
+
modified: "text-og-status-running",
|
|
7866
|
+
deleted: "text-og-status-failed",
|
|
7867
|
+
renamed: "text-og-accent",
|
|
7868
|
+
copied: "text-og-accent",
|
|
7869
|
+
untracked: "text-og-fg-subtle",
|
|
7870
|
+
ignored: "text-og-fg-subtle",
|
|
7871
|
+
conflicted: "text-og-status-failed",
|
|
7872
|
+
typechange: "text-og-status-running"
|
|
7604
7873
|
};
|
|
7605
7874
|
var STATUS_LETTER = {
|
|
7606
7875
|
added: "A",
|
|
@@ -7627,7 +7896,7 @@ function SandboxFiles({
|
|
|
7627
7896
|
const [staged, setStaged] = useState27(false);
|
|
7628
7897
|
const [layout, setLayout] = useState27("unified");
|
|
7629
7898
|
const [editMode, setEditMode] = useState27(false);
|
|
7630
|
-
const rootRef =
|
|
7899
|
+
const rootRef = useRef19(null);
|
|
7631
7900
|
const [wide, setWide] = useState27(false);
|
|
7632
7901
|
useEffect20(() => {
|
|
7633
7902
|
const el = rootRef.current;
|
|
@@ -7647,7 +7916,7 @@ function SandboxFiles({
|
|
|
7647
7916
|
const selectedDiff = changed.find((f) => f.path === effectiveSelected) ?? null;
|
|
7648
7917
|
const viewPath = effectiveSelected && !selectedDiff ? effectiveSelected : null;
|
|
7649
7918
|
const fileView = useFileView(viewPath, files.readFile);
|
|
7650
|
-
const selectFile =
|
|
7919
|
+
const selectFile = useCallback24((path) => {
|
|
7651
7920
|
setSelected(path);
|
|
7652
7921
|
setEditMode(false);
|
|
7653
7922
|
}, []);
|
|
@@ -7664,11 +7933,11 @@ function SandboxFiles({
|
|
|
7664
7933
|
{
|
|
7665
7934
|
className: cn(
|
|
7666
7935
|
"min-h-0 overflow-auto",
|
|
7667
|
-
wide ? "w-[280px] shrink-0 border-r border-
|
|
7936
|
+
wide ? "w-[280px] shrink-0 border-r border-og-border" : "flex-1"
|
|
7668
7937
|
),
|
|
7669
7938
|
children: [
|
|
7670
|
-
changed.length > 0 && /* @__PURE__ */ jsxs17("div", { className: "border-b border-
|
|
7671
|
-
/* @__PURE__ */ jsxs17("div", { className: "px-2 py-1 text-
|
|
7939
|
+
changed.length > 0 && /* @__PURE__ */ jsxs17("div", { className: "border-b border-og-border", children: [
|
|
7940
|
+
/* @__PURE__ */ jsxs17("div", { className: "px-2 py-1 text-og-xs font-medium uppercase tracking-wide text-og-fg-subtle", children: [
|
|
7672
7941
|
"Changes \xB7 ",
|
|
7673
7942
|
changed.length
|
|
7674
7943
|
] }),
|
|
@@ -7678,15 +7947,15 @@ function SandboxFiles({
|
|
|
7678
7947
|
type: "button",
|
|
7679
7948
|
onClick: () => selectFile(file.path),
|
|
7680
7949
|
className: cn(
|
|
7681
|
-
"flex w-full items-center gap-1.5 truncate px-2 py-0.5 text-left text-
|
|
7682
|
-
file.path === effectiveSelected && "bg-
|
|
7950
|
+
"flex w-full items-center gap-1.5 truncate px-2 py-0.5 text-left text-og-sm hover:bg-og-surface-2 pointer-coarse:min-h-10",
|
|
7951
|
+
file.path === effectiveSelected && "bg-og-surface-2"
|
|
7683
7952
|
),
|
|
7684
7953
|
children: [
|
|
7685
7954
|
/* @__PURE__ */ jsx21(
|
|
7686
7955
|
"span",
|
|
7687
7956
|
{
|
|
7688
7957
|
className: cn(
|
|
7689
|
-
"w-3 shrink-0 text-center font-
|
|
7958
|
+
"w-3 shrink-0 text-center font-og-mono text-og-xs",
|
|
7690
7959
|
STATUS_TINT2[file.status]
|
|
7691
7960
|
),
|
|
7692
7961
|
children: STATUS_LETTER[file.status]
|
|
@@ -7694,12 +7963,12 @@ function SandboxFiles({
|
|
|
7694
7963
|
),
|
|
7695
7964
|
/* @__PURE__ */ jsx21(FileIcon3, { className: "size-3.5 shrink-0 opacity-70" }),
|
|
7696
7965
|
/* @__PURE__ */ jsx21("span", { className: "truncate", children: file.path }),
|
|
7697
|
-
/* @__PURE__ */ jsxs17("span", { className: "ml-auto flex shrink-0 items-center gap-1.5 pl-2 text-
|
|
7698
|
-
/* @__PURE__ */ jsxs17("span", { className: "text-
|
|
7966
|
+
/* @__PURE__ */ jsxs17("span", { className: "ml-auto flex shrink-0 items-center gap-1.5 pl-2 text-og-xs", children: [
|
|
7967
|
+
/* @__PURE__ */ jsxs17("span", { className: "text-og-status-idle", children: [
|
|
7699
7968
|
"+",
|
|
7700
7969
|
file.additions
|
|
7701
7970
|
] }),
|
|
7702
|
-
/* @__PURE__ */ jsxs17("span", { className: "text-
|
|
7971
|
+
/* @__PURE__ */ jsxs17("span", { className: "text-og-status-failed", children: [
|
|
7703
7972
|
"\u2212",
|
|
7704
7973
|
file.deletions
|
|
7705
7974
|
] })
|
|
@@ -7708,14 +7977,14 @@ function SandboxFiles({
|
|
|
7708
7977
|
}
|
|
7709
7978
|
) }, file.path)) })
|
|
7710
7979
|
] }),
|
|
7711
|
-
/* @__PURE__ */ jsx21("div", { className: "px-2 py-1 text-
|
|
7980
|
+
/* @__PURE__ */ jsx21("div", { className: "px-2 py-1 text-og-xs font-medium uppercase tracking-wide text-og-fg-subtle", children: "Files" }),
|
|
7712
7981
|
/* @__PURE__ */ jsx21(
|
|
7713
7982
|
FileBrowser,
|
|
7714
7983
|
{
|
|
7715
7984
|
result: files,
|
|
7716
7985
|
selectedPath: effectiveSelected ?? void 0,
|
|
7717
7986
|
onSelectFile: selectFile,
|
|
7718
|
-
emptyState: "
|
|
7987
|
+
emptyState: "This directory is empty",
|
|
7719
7988
|
className: "min-w-0"
|
|
7720
7989
|
}
|
|
7721
7990
|
)
|
|
@@ -7727,12 +7996,12 @@ function SandboxFiles({
|
|
|
7727
7996
|
{
|
|
7728
7997
|
className: cn(
|
|
7729
7998
|
"flex min-h-0 min-w-0 flex-col",
|
|
7730
|
-
wide ? "flex-1" : "flex-[1.4] border-t border-
|
|
7999
|
+
wide ? "flex-1" : "flex-[1.4] border-t border-og-border"
|
|
7731
8000
|
),
|
|
7732
8001
|
children: [
|
|
7733
|
-
/* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-
|
|
7734
|
-
/* @__PURE__ */ jsx21("span", { className: "truncate font-
|
|
7735
|
-
/* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
8002
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-og-border bg-og-surface-1 px-2 py-1", children: [
|
|
8003
|
+
/* @__PURE__ */ jsx21("span", { className: "min-w-0 truncate font-og-mono text-og-xs text-og-fg-muted", children: effectiveSelected ?? "No file selected" }),
|
|
8004
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 shrink-0 flex-wrap items-center justify-end gap-1", children: [
|
|
7736
8005
|
selectedDiff && stagedGit && /* @__PURE__ */ jsx21(
|
|
7737
8006
|
Segmented,
|
|
7738
8007
|
{
|
|
@@ -7809,7 +8078,7 @@ function SandboxFiles({
|
|
|
7809
8078
|
fileView.sizeBytes ?? 0,
|
|
7810
8079
|
" bytes)."
|
|
7811
8080
|
] }) : fileView.content !== null ? /* @__PURE__ */ jsxs17(Fragment6, { children: [
|
|
7812
|
-
fileView.truncated && /* @__PURE__ */ jsxs17("div", { className: "border-b border-
|
|
8081
|
+
fileView.truncated && /* @__PURE__ */ jsxs17("div", { className: "border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-xs text-og-status-running", children: [
|
|
7813
8082
|
"Large file \u2014 showing a truncated preview (",
|
|
7814
8083
|
fileView.sizeBytes ?? 0,
|
|
7815
8084
|
" bytes loaded). Editing is disabled to avoid corrupting the file."
|
|
@@ -7820,10 +8089,10 @@ function SandboxFiles({
|
|
|
7820
8089
|
path: viewPath,
|
|
7821
8090
|
contents: fileView.content,
|
|
7822
8091
|
themeType: resolvedTheme,
|
|
7823
|
-
fallback: /* @__PURE__ */ jsx21("pre", { className: "overflow-auto whitespace-pre p-2 font-
|
|
8092
|
+
fallback: /* @__PURE__ */ jsx21("pre", { className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg", children: fileView.content }),
|
|
7824
8093
|
className: "p-1"
|
|
7825
8094
|
}
|
|
7826
|
-
) : /* @__PURE__ */ jsx21("pre", { className: "overflow-auto whitespace-pre p-2 font-
|
|
8095
|
+
) : /* @__PURE__ */ jsx21("pre", { className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg", children: fileView.content })
|
|
7827
8096
|
] }) : /* @__PURE__ */ jsxs17(Notice, { children: [
|
|
7828
8097
|
"Loading ",
|
|
7829
8098
|
viewPath,
|
|
@@ -7842,19 +8111,19 @@ function SandboxFiles({
|
|
|
7842
8111
|
}
|
|
7843
8112
|
function GitHeader({ git, dirtyCount }) {
|
|
7844
8113
|
const dirty = dirtyCount > 0;
|
|
7845
|
-
return /* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-2 border-b border-
|
|
8114
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-2 border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-sm", children: [
|
|
7846
8115
|
/* @__PURE__ */ jsx21(
|
|
7847
8116
|
"span",
|
|
7848
8117
|
{
|
|
7849
8118
|
className: cn(
|
|
7850
8119
|
"size-2 shrink-0 rounded-full",
|
|
7851
|
-
dirty ? "bg-
|
|
8120
|
+
dirty ? "bg-og-status-running" : "bg-og-status-idle"
|
|
7852
8121
|
),
|
|
7853
8122
|
title: dirty ? `${dirtyCount} changed` : "clean"
|
|
7854
8123
|
}
|
|
7855
8124
|
),
|
|
7856
|
-
/* @__PURE__ */ jsx21("span", { className: "truncate font-
|
|
7857
|
-
(git.ahead > 0 || git.behind > 0) && /* @__PURE__ */ jsxs17("span", { className: "flex shrink-0 items-center gap-1.5 text-
|
|
8125
|
+
/* @__PURE__ */ jsx21("span", { className: "truncate font-og-mono text-og-fg", children: git.branch ?? (git.isRepo ? "(detached)" : "no repo") }),
|
|
8126
|
+
(git.ahead > 0 || git.behind > 0) && /* @__PURE__ */ jsxs17("span", { className: "flex shrink-0 items-center gap-1.5 text-og-xs text-og-fg-subtle", children: [
|
|
7858
8127
|
git.ahead > 0 && /* @__PURE__ */ jsxs17("span", { children: [
|
|
7859
8128
|
"\u2191",
|
|
7860
8129
|
git.ahead
|
|
@@ -7864,7 +8133,7 @@ function GitHeader({ git, dirtyCount }) {
|
|
|
7864
8133
|
git.behind
|
|
7865
8134
|
] })
|
|
7866
8135
|
] }),
|
|
7867
|
-
dirty && /* @__PURE__ */ jsxs17("span", { className: "ml-auto shrink-0 text-
|
|
8136
|
+
dirty && /* @__PURE__ */ jsxs17("span", { className: "ml-auto shrink-0 text-og-xs text-og-fg-subtle", children: [
|
|
7868
8137
|
dirtyCount,
|
|
7869
8138
|
" changed"
|
|
7870
8139
|
] })
|
|
@@ -7875,14 +8144,14 @@ function Segmented({
|
|
|
7875
8144
|
value,
|
|
7876
8145
|
onChange
|
|
7877
8146
|
}) {
|
|
7878
|
-
return /* @__PURE__ */ jsx21("div", { className: "flex items-center rounded-
|
|
8147
|
+
return /* @__PURE__ */ jsx21("div", { className: "flex flex-wrap items-center rounded-og-sm border border-og-border p-0.5", children: options.map((opt) => /* @__PURE__ */ jsx21(
|
|
7879
8148
|
"button",
|
|
7880
8149
|
{
|
|
7881
8150
|
type: "button",
|
|
7882
8151
|
onClick: () => onChange(opt.value),
|
|
7883
8152
|
className: cn(
|
|
7884
|
-
"rounded-
|
|
7885
|
-
opt.value === value ? "bg-
|
|
8153
|
+
"rounded-og-xs px-1.5 py-0.5 text-og-xs pointer-coarse:min-h-10",
|
|
8154
|
+
opt.value === value ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
7886
8155
|
),
|
|
7887
8156
|
children: opt.label
|
|
7888
8157
|
},
|
|
@@ -7950,7 +8219,7 @@ function Notice({ children, className }) {
|
|
|
7950
8219
|
"div",
|
|
7951
8220
|
{
|
|
7952
8221
|
className: cn(
|
|
7953
|
-
"flex h-full items-center justify-center p-4 text-center text-
|
|
8222
|
+
"flex h-full items-center justify-center p-4 text-center text-og-sm text-og-fg-subtle",
|
|
7954
8223
|
className
|
|
7955
8224
|
),
|
|
7956
8225
|
children
|
|
@@ -7960,8 +8229,9 @@ function Notice({ children, className }) {
|
|
|
7960
8229
|
|
|
7961
8230
|
// src/components/desktop-viewer.tsx
|
|
7962
8231
|
import { LoaderCircleIcon as LoaderCircleIcon2, MonitorIcon, MousePointerClickIcon, WifiOffIcon } from "lucide-react";
|
|
7963
|
-
import { useEffect as useEffect21, useRef as
|
|
8232
|
+
import { useEffect as useEffect21, useRef as useRef20, useState as useState28 } from "react";
|
|
7964
8233
|
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
8234
|
+
var DESKTOP_MEDIA_BACKGROUND = "#000";
|
|
7965
8235
|
function isHardUnavailable(reason) {
|
|
7966
8236
|
switch (reason) {
|
|
7967
8237
|
case "backend_unsupported":
|
|
@@ -7992,7 +8262,7 @@ function DesktopViewer({
|
|
|
7992
8262
|
connectTimeoutMs = 13e3,
|
|
7993
8263
|
className
|
|
7994
8264
|
}) {
|
|
7995
|
-
const containerRef =
|
|
8265
|
+
const containerRef = useRef20(null);
|
|
7996
8266
|
const [consented, setConsented] = useState28(false);
|
|
7997
8267
|
const [takeControl, setTakeControl] = useState28(interactive ?? false);
|
|
7998
8268
|
const externallyControlled = interactive !== void 0;
|
|
@@ -8034,9 +8304,9 @@ function DesktopViewer({
|
|
|
8034
8304
|
});
|
|
8035
8305
|
const connected = stream.state === "connected";
|
|
8036
8306
|
const hasLiveUrl = Boolean(connectCapability?.url);
|
|
8037
|
-
const streamStateRef =
|
|
8307
|
+
const streamStateRef = useRef20(stream.state);
|
|
8038
8308
|
streamStateRef.current = stream.state;
|
|
8039
|
-
const warmKeyRef =
|
|
8309
|
+
const warmKeyRef = useRef20(null);
|
|
8040
8310
|
useEffect21(() => {
|
|
8041
8311
|
if (!isWatching || !coldWarmable || needsAck || viewerCapReached) {
|
|
8042
8312
|
if (!coldWarmable) warmKeyRef.current = null;
|
|
@@ -8115,10 +8385,11 @@ function DesktopViewer({
|
|
|
8115
8385
|
"div",
|
|
8116
8386
|
{
|
|
8117
8387
|
className: cn(
|
|
8118
|
-
"relative h-full w-full overflow-hidden
|
|
8119
|
-
inControl && "ring-2 ring-inset ring-
|
|
8388
|
+
"relative h-full w-full overflow-hidden",
|
|
8389
|
+
inControl && "ring-2 ring-inset ring-og-accent",
|
|
8120
8390
|
className
|
|
8121
8391
|
),
|
|
8392
|
+
style: { backgroundColor: DESKTOP_MEDIA_BACKGROUND },
|
|
8122
8393
|
"data-opengeni-desktop": true,
|
|
8123
8394
|
"data-state": stream.state,
|
|
8124
8395
|
"data-ui-state": uiState,
|
|
@@ -8133,18 +8404,18 @@ function DesktopViewer({
|
|
|
8133
8404
|
"data-state": stream.state
|
|
8134
8405
|
}
|
|
8135
8406
|
),
|
|
8136
|
-
uiState === "connecting" && /* @__PURE__ */ jsxs18("div", { className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center gap-3 text-
|
|
8407
|
+
uiState === "connecting" && /* @__PURE__ */ jsxs18("div", { className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center gap-3 text-og-fg-subtle", children: [
|
|
8137
8408
|
/* @__PURE__ */ jsxs18("span", { className: "relative flex items-center justify-center", children: [
|
|
8138
8409
|
/* @__PURE__ */ jsx22(MonitorIcon, { className: "size-8 opacity-30", strokeWidth: 1.5 }),
|
|
8139
8410
|
/* @__PURE__ */ jsx22(
|
|
8140
8411
|
LoaderCircleIcon2,
|
|
8141
8412
|
{
|
|
8142
|
-
className: "absolute size-12 animate-og-spin text-
|
|
8413
|
+
className: "absolute size-12 animate-og-spin text-og-accent opacity-70",
|
|
8143
8414
|
strokeWidth: 1.25
|
|
8144
8415
|
}
|
|
8145
8416
|
)
|
|
8146
8417
|
] }),
|
|
8147
|
-
/* @__PURE__ */ jsx22("span", { className: "text-
|
|
8418
|
+
/* @__PURE__ */ jsx22("span", { className: "text-og-sm", children: "Connecting to the desktop\u2026" })
|
|
8148
8419
|
] }),
|
|
8149
8420
|
showToggle && !externallyControlled && inControl && /* @__PURE__ */ jsx22(
|
|
8150
8421
|
InControlBar,
|
|
@@ -8157,7 +8428,7 @@ function DesktopViewer({
|
|
|
8157
8428
|
TakeControlCallToAction,
|
|
8158
8429
|
{
|
|
8159
8430
|
disabled: !serverAllowsControl,
|
|
8160
|
-
disabledReason: !serverAllowsControl ? capability?.client === "frames" ? "View-only \u2014 live control isn't available for this machine yet." : "This deployment streams the desktop read-only" : void 0,
|
|
8431
|
+
disabledReason: !serverAllowsControl ? capability?.client === "frames" ? "View-only \u2014 live control isn't available for this machine yet." : "This deployment streams the desktop read-only." : void 0,
|
|
8161
8432
|
onTakeControl: () => setTakeControl(true)
|
|
8162
8433
|
}
|
|
8163
8434
|
),
|
|
@@ -8183,16 +8454,16 @@ function TakeControlCallToAction({
|
|
|
8183
8454
|
title: disabled ? disabledReason : "Take control of the desktop",
|
|
8184
8455
|
onClick: onTakeControl,
|
|
8185
8456
|
className: cn(
|
|
8186
|
-
"group pointer-events-auto flex items-center gap-3 rounded-
|
|
8187
|
-
"border-
|
|
8188
|
-
"bg-
|
|
8189
|
-
"shadow-
|
|
8457
|
+
"group pointer-events-auto flex items-center gap-3 rounded-og-lg border px-5 py-3",
|
|
8458
|
+
"border-og-border",
|
|
8459
|
+
"bg-og-bg/85 backdrop-blur-md",
|
|
8460
|
+
"shadow-og-lg",
|
|
8190
8461
|
"outline-none transition-all duration-150 ease-out",
|
|
8191
|
-
"focus-visible:ring-2 focus-visible:ring-
|
|
8462
|
+
"focus-visible:ring-2 focus-visible:ring-og-accent focus-visible:ring-offset-2 focus-visible:ring-offset-og-bg",
|
|
8192
8463
|
disabled ? "cursor-not-allowed opacity-60" : cn(
|
|
8193
8464
|
"cursor-pointer opacity-90 hover:-translate-y-0.5 hover:opacity-100",
|
|
8194
|
-
"hover:border-
|
|
8195
|
-
"hover:bg-
|
|
8465
|
+
"hover:border-og-accent",
|
|
8466
|
+
"hover:bg-og-accent/10"
|
|
8196
8467
|
)
|
|
8197
8468
|
),
|
|
8198
8469
|
children: [
|
|
@@ -8201,16 +8472,16 @@ function TakeControlCallToAction({
|
|
|
8201
8472
|
{
|
|
8202
8473
|
className: cn(
|
|
8203
8474
|
"flex size-9 shrink-0 items-center justify-center rounded-full transition-colors",
|
|
8204
|
-
"bg-
|
|
8205
|
-
"text-
|
|
8475
|
+
"bg-og-accent",
|
|
8476
|
+
"text-og-accent-fg",
|
|
8206
8477
|
disabled ? "" : "group-hover:scale-105"
|
|
8207
8478
|
),
|
|
8208
8479
|
children: /* @__PURE__ */ jsx22(MousePointerClickIcon, { className: "size-5", strokeWidth: 2 })
|
|
8209
8480
|
}
|
|
8210
8481
|
),
|
|
8211
8482
|
/* @__PURE__ */ jsxs18("span", { className: "flex flex-col items-start leading-tight", children: [
|
|
8212
|
-
/* @__PURE__ */ jsx22("span", { className: "text-
|
|
8213
|
-
/* @__PURE__ */ jsx22("span", { className: "text-
|
|
8483
|
+
/* @__PURE__ */ jsx22("span", { className: "text-og-base font-semibold text-og-fg", children: "Take control" }),
|
|
8484
|
+
/* @__PURE__ */ jsx22("span", { className: "text-og-xs text-og-fg-subtle", children: disabled && disabledReason ? disabledReason : "Drive the mouse & keyboard" })
|
|
8214
8485
|
] })
|
|
8215
8486
|
]
|
|
8216
8487
|
}
|
|
@@ -8219,13 +8490,13 @@ function TakeControlCallToAction({
|
|
|
8219
8490
|
}
|
|
8220
8491
|
function InControlBar({ shared, onRelease }) {
|
|
8221
8492
|
return /* @__PURE__ */ jsxs18("div", { className: "pointer-events-none absolute inset-x-0 top-0 flex items-center justify-between gap-2 p-2", children: [
|
|
8222
|
-
/* @__PURE__ */ jsxs18("span", { className: "pointer-events-auto inline-flex items-center gap-2 rounded-
|
|
8493
|
+
/* @__PURE__ */ jsxs18("span", { className: "pointer-events-auto inline-flex items-center gap-2 rounded-og-sm bg-og-accent px-2.5 py-1 text-og-xs font-medium text-og-accent-fg shadow-og-md", children: [
|
|
8223
8494
|
/* @__PURE__ */ jsx22("span", { className: "size-1.5 animate-pulse rounded-full bg-current", "aria-hidden": true }),
|
|
8224
8495
|
"You're in control",
|
|
8225
8496
|
/* @__PURE__ */ jsx22("span", { className: "opacity-75", children: "\xB7 click Return control (or Ctrl+Alt+Shift)" })
|
|
8226
8497
|
] }),
|
|
8227
8498
|
/* @__PURE__ */ jsxs18("div", { className: "pointer-events-auto flex items-center gap-1.5", children: [
|
|
8228
|
-
shared && /* @__PURE__ */ jsx22("span", { className: "rounded-
|
|
8499
|
+
shared && /* @__PURE__ */ jsx22("span", { className: "rounded-og-sm bg-og-status-failed/85 px-2 py-0.5 text-og-xs text-og-accent-fg", children: "Shared sandbox \u2014 others are watching" }),
|
|
8229
8500
|
/* @__PURE__ */ jsxs18(
|
|
8230
8501
|
"button",
|
|
8231
8502
|
{
|
|
@@ -8233,9 +8504,9 @@ function InControlBar({ shared, onRelease }) {
|
|
|
8233
8504
|
onClick: onRelease,
|
|
8234
8505
|
title: "Return control (or press Ctrl+Alt+Shift)",
|
|
8235
8506
|
className: cn(
|
|
8236
|
-
"inline-flex items-center gap-1.5 rounded-
|
|
8237
|
-
"border-
|
|
8238
|
-
"outline-none hover:bg-
|
|
8507
|
+
"inline-flex items-center gap-1.5 rounded-og-sm border px-2.5 py-1 text-og-xs font-semibold shadow-og-md transition-colors",
|
|
8508
|
+
"border-og-accent bg-og-bg/90 text-og-fg backdrop-blur-sm",
|
|
8509
|
+
"outline-none hover:bg-og-accent hover:text-og-accent-fg focus-visible:ring-2 focus-visible:ring-og-accent"
|
|
8239
8510
|
),
|
|
8240
8511
|
children: [
|
|
8241
8512
|
/* @__PURE__ */ jsx22(MonitorIcon, { className: "size-3.5", strokeWidth: 2, "aria-hidden": true }),
|
|
@@ -8255,7 +8526,7 @@ function unavailableCopy(reason) {
|
|
|
8255
8526
|
case "os_unsupported":
|
|
8256
8527
|
return "The sandbox OS does not support a desktop stream.";
|
|
8257
8528
|
case "not_provisioned":
|
|
8258
|
-
return "
|
|
8529
|
+
return "This sandbox doesn't have a desktop yet.";
|
|
8259
8530
|
case "disabled_by_policy":
|
|
8260
8531
|
return "Desktop streaming is disabled on this deployment.";
|
|
8261
8532
|
case "lease_cold":
|
|
@@ -8265,62 +8536,62 @@ function unavailableCopy(reason) {
|
|
|
8265
8536
|
}
|
|
8266
8537
|
}
|
|
8267
8538
|
function WarmingNotice({ onRetry }) {
|
|
8268
|
-
return /* @__PURE__ */ jsxs18("div", { className: "flex max-w-sm flex-col items-center gap-3 rounded-lg border border-
|
|
8539
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex max-w-sm flex-col items-center gap-3 rounded-og-lg border border-og-border bg-og-bg/90 p-5 text-center text-og-base text-og-fg backdrop-blur-sm", children: [
|
|
8269
8540
|
/* @__PURE__ */ jsx22(
|
|
8270
8541
|
LoaderCircleIcon2,
|
|
8271
8542
|
{
|
|
8272
|
-
className: "size-7 animate-og-spin text-
|
|
8543
|
+
className: "size-7 animate-og-spin text-og-accent",
|
|
8273
8544
|
strokeWidth: 1.5
|
|
8274
8545
|
}
|
|
8275
8546
|
),
|
|
8276
8547
|
/* @__PURE__ */ jsxs18("div", { className: "space-y-1", children: [
|
|
8277
8548
|
/* @__PURE__ */ jsx22("div", { className: "font-medium", children: "Warming the sandbox\u2026" }),
|
|
8278
|
-
/* @__PURE__ */ jsx22("p", { className: "text-
|
|
8549
|
+
/* @__PURE__ */ jsx22("p", { className: "text-og-sm text-og-fg-subtle", children: "Spinning up the desktop \u2014 this takes a few seconds." })
|
|
8279
8550
|
] }),
|
|
8280
8551
|
onRetry && /* @__PURE__ */ jsx22(
|
|
8281
8552
|
"button",
|
|
8282
8553
|
{
|
|
8283
8554
|
type: "button",
|
|
8284
8555
|
onClick: onRetry,
|
|
8285
|
-
className: "rounded border border-
|
|
8556
|
+
className: "rounded-og-sm border border-og-border px-3 py-1.5 text-og-sm text-og-fg-muted transition-colors hover:text-og-fg pointer-coarse:min-h-10",
|
|
8286
8557
|
children: "Taking too long? Retry"
|
|
8287
8558
|
}
|
|
8288
8559
|
)
|
|
8289
8560
|
] });
|
|
8290
8561
|
}
|
|
8291
8562
|
function DefaultConsentGate({ shared, onAccept }) {
|
|
8292
|
-
return /* @__PURE__ */ jsxs18("div", { className: "max-w-sm rounded-lg border border-
|
|
8563
|
+
return /* @__PURE__ */ jsxs18("div", { className: "max-w-sm rounded-og-lg border border-og-border bg-og-bg p-4 text-center text-og-base text-og-fg", children: [
|
|
8293
8564
|
/* @__PURE__ */ jsx22("div", { className: "mb-1 font-medium", children: "Watch the live desktop?" }),
|
|
8294
|
-
/* @__PURE__ */ jsxs18("p", { className: "mb-3 text-
|
|
8565
|
+
/* @__PURE__ */ jsxs18("p", { className: "mb-3 text-og-sm text-og-fg-subtle", children: [
|
|
8295
8566
|
"The desktop pixel stream is ",
|
|
8296
8567
|
/* @__PURE__ */ jsx22("strong", { children: "un-redacted" }),
|
|
8297
8568
|
" \u2014 it can show secrets the agent prints on screen.",
|
|
8298
|
-
shared ? " This
|
|
8569
|
+
shared ? " This sandbox is shared: you'll also see other sessions' agents on the same screen." : ""
|
|
8299
8570
|
] }),
|
|
8300
8571
|
/* @__PURE__ */ jsx22(
|
|
8301
8572
|
"button",
|
|
8302
8573
|
{
|
|
8303
8574
|
type: "button",
|
|
8304
8575
|
onClick: onAccept,
|
|
8305
|
-
className: "rounded bg-
|
|
8576
|
+
className: "rounded-og-sm bg-og-accent px-3 py-1.5 text-og-sm font-medium text-og-accent-fg pointer-coarse:min-h-10",
|
|
8306
8577
|
children: "I understand \u2014 show the desktop"
|
|
8307
8578
|
}
|
|
8308
8579
|
)
|
|
8309
8580
|
] });
|
|
8310
8581
|
}
|
|
8311
8582
|
function defaultNotice(title, body, onRetry) {
|
|
8312
|
-
return /* @__PURE__ */ jsxs18("div", { className: "max-w-sm rounded-lg border border-
|
|
8583
|
+
return /* @__PURE__ */ jsxs18("div", { className: "max-w-sm rounded-og-lg border border-og-border bg-og-bg p-4 text-center text-og-base text-og-fg", children: [
|
|
8313
8584
|
/* @__PURE__ */ jsxs18("div", { className: "mb-1 flex items-center justify-center gap-1.5 font-medium", children: [
|
|
8314
8585
|
onRetry && /* @__PURE__ */ jsx22(WifiOffIcon, { className: "size-4 opacity-70", strokeWidth: 1.75 }),
|
|
8315
8586
|
title
|
|
8316
8587
|
] }),
|
|
8317
|
-
/* @__PURE__ */ jsx22("p", { className: "text-
|
|
8588
|
+
/* @__PURE__ */ jsx22("p", { className: "text-og-sm text-og-fg-subtle", children: body }),
|
|
8318
8589
|
onRetry && /* @__PURE__ */ jsx22(
|
|
8319
8590
|
"button",
|
|
8320
8591
|
{
|
|
8321
8592
|
type: "button",
|
|
8322
8593
|
onClick: onRetry,
|
|
8323
|
-
className: "mt-3 rounded border border-
|
|
8594
|
+
className: "mt-3 rounded-og-sm border border-og-border px-3 py-1.5 text-og-sm transition-colors hover:border-og-accent pointer-coarse:min-h-10",
|
|
8324
8595
|
children: "Reconnect"
|
|
8325
8596
|
}
|
|
8326
8597
|
)
|
|
@@ -8328,12 +8599,13 @@ function defaultNotice(title, body, onRetry) {
|
|
|
8328
8599
|
}
|
|
8329
8600
|
|
|
8330
8601
|
// src/components/workspace-dock.tsx
|
|
8331
|
-
import { useCallback as
|
|
8602
|
+
import { useCallback as useCallback25, useEffect as useEffect22, useLayoutEffect, useState as useState29 } from "react";
|
|
8332
8603
|
import {
|
|
8333
8604
|
ChevronsLeftRightIcon,
|
|
8334
8605
|
Maximize2Icon,
|
|
8335
8606
|
Minimize2Icon,
|
|
8336
|
-
PanelRightCloseIcon
|
|
8607
|
+
PanelRightCloseIcon,
|
|
8608
|
+
XIcon as XIcon3
|
|
8337
8609
|
} from "lucide-react";
|
|
8338
8610
|
import {
|
|
8339
8611
|
Group,
|
|
@@ -8344,6 +8616,25 @@ import {
|
|
|
8344
8616
|
} from "react-resizable-panels";
|
|
8345
8617
|
import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
8346
8618
|
var useDockLayoutEffect = typeof window === "undefined" ? useEffect22 : useLayoutEffect;
|
|
8619
|
+
var DOCK_OVERLAY_BREAKPOINT = 1024;
|
|
8620
|
+
function useIsNarrow(maxWidth) {
|
|
8621
|
+
const [narrow, setNarrow] = useState29(false);
|
|
8622
|
+
useDockLayoutEffect(() => {
|
|
8623
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
8624
|
+
return;
|
|
8625
|
+
}
|
|
8626
|
+
const mql = window.matchMedia(`(max-width: ${maxWidth - 1}px)`);
|
|
8627
|
+
const update = () => setNarrow(mql.matches);
|
|
8628
|
+
update();
|
|
8629
|
+
if (typeof mql.addEventListener === "function") {
|
|
8630
|
+
mql.addEventListener("change", update);
|
|
8631
|
+
return () => mql.removeEventListener("change", update);
|
|
8632
|
+
}
|
|
8633
|
+
mql.addListener(update);
|
|
8634
|
+
return () => mql.removeListener(update);
|
|
8635
|
+
}, [maxWidth]);
|
|
8636
|
+
return narrow;
|
|
8637
|
+
}
|
|
8347
8638
|
function WorkspaceDock({
|
|
8348
8639
|
primary,
|
|
8349
8640
|
tabs,
|
|
@@ -8357,11 +8648,13 @@ function WorkspaceDock({
|
|
|
8357
8648
|
maxSize = 70,
|
|
8358
8649
|
className
|
|
8359
8650
|
}) {
|
|
8651
|
+
const narrow = useIsNarrow(DOCK_OVERLAY_BREAKPOINT);
|
|
8360
8652
|
const dockPanelRef = usePanelRef();
|
|
8361
8653
|
const [internalCollapsed, setInternalCollapsed] = useState29(false);
|
|
8362
8654
|
const [maximized, setMaximized] = useState29(false);
|
|
8363
8655
|
const [internalTab, setInternalTab] = useState29(tabs[0]?.id ?? "");
|
|
8364
8656
|
const collapsed = collapsedProp ?? internalCollapsed;
|
|
8657
|
+
const hostControlled = collapsedProp !== void 0;
|
|
8365
8658
|
const { defaultLayout, onLayoutChanged } = useDefaultLayout({
|
|
8366
8659
|
panelIds: ["primary", "dock"],
|
|
8367
8660
|
storage: typeof window !== "undefined" ? window.localStorage : void 0,
|
|
@@ -8370,14 +8663,14 @@ function WorkspaceDock({
|
|
|
8370
8663
|
const current = activeTab ?? internalTab;
|
|
8371
8664
|
const tabIds = tabs.map((tab) => tab.id).join("\0");
|
|
8372
8665
|
const firstTabId = tabs[0]?.id ?? "";
|
|
8373
|
-
const setTab =
|
|
8666
|
+
const setTab = useCallback25(
|
|
8374
8667
|
(id) => {
|
|
8375
8668
|
setInternalTab(id);
|
|
8376
8669
|
onActiveTabChange?.(id);
|
|
8377
8670
|
},
|
|
8378
8671
|
[onActiveTabChange]
|
|
8379
8672
|
);
|
|
8380
|
-
const setCollapsed =
|
|
8673
|
+
const setCollapsed = useCallback25(
|
|
8381
8674
|
(next) => {
|
|
8382
8675
|
setInternalCollapsed((previous) => previous === next ? previous : next);
|
|
8383
8676
|
onCollapsedChange?.(next);
|
|
@@ -8400,31 +8693,70 @@ function WorkspaceDock({
|
|
|
8400
8693
|
setTab(firstTabId);
|
|
8401
8694
|
}
|
|
8402
8695
|
}, [tabIds, firstTabId, current, setTab]);
|
|
8403
|
-
|
|
8404
|
-
if (!maximized) return;
|
|
8405
|
-
const onKey = (event) => {
|
|
8406
|
-
if (event.key === "Escape") setMaximized(false);
|
|
8407
|
-
};
|
|
8408
|
-
window.addEventListener("keydown", onKey);
|
|
8409
|
-
return () => window.removeEventListener("keydown", onKey);
|
|
8410
|
-
}, [maximized]);
|
|
8411
|
-
const collapse = useCallback24(() => {
|
|
8696
|
+
const collapse = useCallback25(() => {
|
|
8412
8697
|
dockPanelRef.current?.collapse();
|
|
8413
8698
|
setCollapsed(true);
|
|
8414
8699
|
}, [dockPanelRef, setCollapsed]);
|
|
8415
|
-
const expand =
|
|
8700
|
+
const expand = useCallback25(() => {
|
|
8416
8701
|
dockPanelRef.current?.expand();
|
|
8417
8702
|
setCollapsed(false);
|
|
8418
8703
|
}, [dockPanelRef, setCollapsed]);
|
|
8704
|
+
useEffect22(() => {
|
|
8705
|
+
const overlayOpen = maximized || narrow && !collapsed;
|
|
8706
|
+
if (!overlayOpen) return;
|
|
8707
|
+
const onKey = (event) => {
|
|
8708
|
+
if (event.key !== "Escape") return;
|
|
8709
|
+
if (maximized) setMaximized(false);
|
|
8710
|
+
else collapse();
|
|
8711
|
+
};
|
|
8712
|
+
window.addEventListener("keydown", onKey);
|
|
8713
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
8714
|
+
}, [maximized, narrow, collapsed, collapse]);
|
|
8715
|
+
if (narrow) {
|
|
8716
|
+
return /* @__PURE__ */ jsxs19("div", { className: cn("relative flex h-full min-h-0 w-full min-w-0", className), children: [
|
|
8717
|
+
/* @__PURE__ */ jsx23("div", { className: "min-h-0 min-w-0 flex-1", children: primary }),
|
|
8718
|
+
!collapsed && /* @__PURE__ */ jsx23(
|
|
8719
|
+
"div",
|
|
8720
|
+
{
|
|
8721
|
+
role: "dialog",
|
|
8722
|
+
"aria-modal": "true",
|
|
8723
|
+
"aria-label": "Workspace",
|
|
8724
|
+
className: "fixed inset-0 z-40 flex flex-col bg-og-bg",
|
|
8725
|
+
style: {
|
|
8726
|
+
paddingTop: "env(safe-area-inset-top)",
|
|
8727
|
+
paddingBottom: "env(safe-area-inset-bottom)"
|
|
8728
|
+
},
|
|
8729
|
+
children: /* @__PURE__ */ jsx23(
|
|
8730
|
+
DockChrome,
|
|
8731
|
+
{
|
|
8732
|
+
tabs,
|
|
8733
|
+
current,
|
|
8734
|
+
onTab: setTab,
|
|
8735
|
+
controls: /* @__PURE__ */ jsx23(ChromeButton, { onClick: collapse, title: "Close workspace", label: "Close workspace", children: /* @__PURE__ */ jsx23(XIcon3, { className: "size-4" }) })
|
|
8736
|
+
}
|
|
8737
|
+
)
|
|
8738
|
+
}
|
|
8739
|
+
)
|
|
8740
|
+
] });
|
|
8741
|
+
}
|
|
8419
8742
|
const dockChrome = /* @__PURE__ */ jsx23(
|
|
8420
8743
|
DockChrome,
|
|
8421
8744
|
{
|
|
8422
8745
|
tabs,
|
|
8423
8746
|
current,
|
|
8424
8747
|
onTab: setTab,
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8748
|
+
controls: /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
8749
|
+
/* @__PURE__ */ jsx23(
|
|
8750
|
+
ChromeButton,
|
|
8751
|
+
{
|
|
8752
|
+
onClick: () => setMaximized((m) => !m),
|
|
8753
|
+
title: maximized ? "Restore (Esc)" : "Maximize",
|
|
8754
|
+
label: maximized ? "Restore dock" : "Maximize dock",
|
|
8755
|
+
children: maximized ? /* @__PURE__ */ jsx23(Minimize2Icon, { className: "size-3.5" }) : /* @__PURE__ */ jsx23(Maximize2Icon, { className: "size-3.5" })
|
|
8756
|
+
}
|
|
8757
|
+
),
|
|
8758
|
+
hostControlled ? null : /* @__PURE__ */ jsx23(ChromeButton, { onClick: collapse, title: "Collapse", label: "Collapse dock", children: /* @__PURE__ */ jsx23(PanelRightCloseIcon, { className: "size-3.5" }) })
|
|
8759
|
+
] })
|
|
8428
8760
|
}
|
|
8429
8761
|
);
|
|
8430
8762
|
return /* @__PURE__ */ jsxs19("div", { className: cn("relative flex h-full min-h-0 w-full min-w-0", className), children: [
|
|
@@ -8437,7 +8769,7 @@ function WorkspaceDock({
|
|
|
8437
8769
|
onLayoutChanged,
|
|
8438
8770
|
children: [
|
|
8439
8771
|
/* @__PURE__ */ jsx23(Panel, { id: "primary", minSize: "30%", className: "min-h-0 min-w-0", children: primary }),
|
|
8440
|
-
!collapsed && /* @__PURE__ */ jsx23(Separator, { className: "group relative w-1.5 shrink-0 outline-none", children: /* @__PURE__ */ jsx23("span", { className: "absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-
|
|
8772
|
+
!collapsed && /* @__PURE__ */ jsx23(Separator, { className: "group relative w-1.5 shrink-0 outline-none", children: /* @__PURE__ */ jsx23("span", { className: "absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-og-border transition-colors group-hover:bg-og-accent group-data-[separator-state=dragging]:bg-og-accent" }) }),
|
|
8441
8773
|
/* @__PURE__ */ jsx23(
|
|
8442
8774
|
Panel,
|
|
8443
8775
|
{
|
|
@@ -8456,83 +8788,85 @@ function WorkspaceDock({
|
|
|
8456
8788
|
}
|
|
8457
8789
|
},
|
|
8458
8790
|
className: "min-h-0 min-w-0",
|
|
8459
|
-
children: !collapsed && !maximized && /* @__PURE__ */ jsx23("div", { className: "flex h-full min-h-0 min-w-0 flex-col border-l border-
|
|
8791
|
+
children: !collapsed && !maximized && /* @__PURE__ */ jsx23("div", { className: "flex h-full min-h-0 min-w-0 flex-col border-l border-og-border bg-og-bg", children: dockChrome })
|
|
8460
8792
|
}
|
|
8461
8793
|
)
|
|
8462
8794
|
]
|
|
8463
8795
|
}
|
|
8464
8796
|
),
|
|
8465
|
-
collapsed && !maximized && /* @__PURE__ */ jsx23(
|
|
8797
|
+
collapsed && !maximized && !hostControlled && /* @__PURE__ */ jsx23(
|
|
8466
8798
|
"button",
|
|
8467
8799
|
{
|
|
8468
8800
|
type: "button",
|
|
8469
8801
|
onClick: expand,
|
|
8470
8802
|
title: "Open workspace",
|
|
8471
|
-
className: "absolute inset-y-0 right-0 flex w-6 shrink-0 items-center justify-center border-l border-
|
|
8803
|
+
className: "absolute inset-y-0 right-0 flex w-6 shrink-0 items-center justify-center border-l border-og-border bg-og-surface-1 text-og-fg-subtle hover:text-og-fg",
|
|
8472
8804
|
children: /* @__PURE__ */ jsx23(ChevronsLeftRightIcon, { className: "size-3.5" })
|
|
8473
8805
|
}
|
|
8474
8806
|
),
|
|
8475
|
-
maximized && /* @__PURE__ */ jsx23("div", { className: "fixed inset-0 z-40 flex flex-col bg-
|
|
8807
|
+
maximized && /* @__PURE__ */ jsx23("div", { className: "fixed inset-0 z-40 flex flex-col bg-og-bg", children: dockChrome })
|
|
8476
8808
|
] });
|
|
8477
8809
|
}
|
|
8810
|
+
function ChromeButton({
|
|
8811
|
+
onClick,
|
|
8812
|
+
title,
|
|
8813
|
+
label,
|
|
8814
|
+
children
|
|
8815
|
+
}) {
|
|
8816
|
+
return /* @__PURE__ */ jsx23(
|
|
8817
|
+
"button",
|
|
8818
|
+
{
|
|
8819
|
+
type: "button",
|
|
8820
|
+
onClick,
|
|
8821
|
+
title,
|
|
8822
|
+
"aria-label": label,
|
|
8823
|
+
className: "inline-flex items-center justify-center rounded-og-sm p-1 transition-colors hover:bg-og-surface-2 hover:text-og-fg pointer-coarse:size-10",
|
|
8824
|
+
children
|
|
8825
|
+
}
|
|
8826
|
+
);
|
|
8827
|
+
}
|
|
8478
8828
|
function DockChrome({
|
|
8479
8829
|
tabs,
|
|
8480
8830
|
current,
|
|
8481
8831
|
onTab,
|
|
8482
|
-
|
|
8483
|
-
onToggleMaximize,
|
|
8484
|
-
onCollapse
|
|
8832
|
+
controls
|
|
8485
8833
|
}) {
|
|
8486
8834
|
const active = tabs.find((t) => t.id === current) ?? tabs[0];
|
|
8487
8835
|
return /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
8488
|
-
/* @__PURE__ */ jsxs19("div", { className: "flex shrink-0 items-center
|
|
8489
|
-
/* @__PURE__ */ jsx23(
|
|
8490
|
-
"
|
|
8836
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex shrink-0 items-center gap-2 border-b border-og-border px-1.5 py-1", children: [
|
|
8837
|
+
/* @__PURE__ */ jsx23(
|
|
8838
|
+
"div",
|
|
8491
8839
|
{
|
|
8492
|
-
|
|
8493
|
-
role: "
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
children: maximized ? /* @__PURE__ */ jsx23(Minimize2Icon, { className: "size-3.5" }) : /* @__PURE__ */ jsx23(Maximize2Icon, { className: "size-3.5" })
|
|
8516
|
-
}
|
|
8517
|
-
),
|
|
8518
|
-
/* @__PURE__ */ jsx23(
|
|
8519
|
-
"button",
|
|
8520
|
-
{
|
|
8521
|
-
type: "button",
|
|
8522
|
-
onClick: onCollapse,
|
|
8523
|
-
title: maximized ? "Restore" : "Collapse",
|
|
8524
|
-
className: "rounded-[var(--og-radius-sm,4px)] p-1 hover:bg-[color:var(--og-color-surface-2,var(--color-surface-2,#222))] hover:text-[color:var(--og-color-fg,var(--color-fg,#e6e6e6))]",
|
|
8525
|
-
children: /* @__PURE__ */ jsx23(PanelRightCloseIcon, { className: "size-3.5" })
|
|
8526
|
-
}
|
|
8527
|
-
)
|
|
8528
|
-
] })
|
|
8840
|
+
className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
8841
|
+
role: "tablist",
|
|
8842
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs19(
|
|
8843
|
+
"button",
|
|
8844
|
+
{
|
|
8845
|
+
type: "button",
|
|
8846
|
+
role: "tab",
|
|
8847
|
+
"aria-selected": tab.id === current,
|
|
8848
|
+
onClick: () => onTab(tab.id),
|
|
8849
|
+
className: cn(
|
|
8850
|
+
"flex shrink-0 items-center gap-1 rounded-og-sm px-2 py-1 text-og-xs font-medium transition-colors pointer-coarse:min-h-10",
|
|
8851
|
+
tab.id === current ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
8852
|
+
),
|
|
8853
|
+
children: [
|
|
8854
|
+
/* @__PURE__ */ jsx23("span", { children: tab.label }),
|
|
8855
|
+
tab.badge
|
|
8856
|
+
]
|
|
8857
|
+
},
|
|
8858
|
+
tab.id
|
|
8859
|
+
))
|
|
8860
|
+
}
|
|
8861
|
+
),
|
|
8862
|
+
/* @__PURE__ */ jsx23("div", { className: "flex shrink-0 items-center gap-0.5 text-og-fg-subtle", children: controls })
|
|
8529
8863
|
] }),
|
|
8530
8864
|
/* @__PURE__ */ jsx23("div", { className: "min-h-0 min-w-0 flex-1 overflow-hidden", role: "tabpanel", children: active?.content })
|
|
8531
8865
|
] });
|
|
8532
8866
|
}
|
|
8533
8867
|
|
|
8534
8868
|
// src/hooks/use-codex-accounts.ts
|
|
8535
|
-
import { useCallback as
|
|
8869
|
+
import { useCallback as useCallback26, useState as useState30 } from "react";
|
|
8536
8870
|
function isCodexAccountEvent(event) {
|
|
8537
8871
|
return event.type === "codex.account.switched" || event.type === "turn.started";
|
|
8538
8872
|
}
|
|
@@ -8549,7 +8883,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8549
8883
|
const codexClient = options.codexClient ?? client;
|
|
8550
8884
|
const sessionId = options.sessionId;
|
|
8551
8885
|
const sharedEvents = options.events;
|
|
8552
|
-
const load =
|
|
8886
|
+
const load = useCallback26(async () => {
|
|
8553
8887
|
const accountsP = codexClient.listCodexAccounts(workspaceId);
|
|
8554
8888
|
const sessionP = sessionId && codexClient.getSession ? codexClient.getSession(workspaceId, sessionId).catch(() => null) : Promise.resolve(null);
|
|
8555
8889
|
const [acc, session] = await Promise.all([accountsP, sessionP]);
|
|
@@ -8573,7 +8907,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8573
8907
|
() => void state.refresh(),
|
|
8574
8908
|
{ enabled: options.enabled ?? true, ...sharedEvents !== void 0 ? { events: sharedEvents } : {} }
|
|
8575
8909
|
);
|
|
8576
|
-
const pin =
|
|
8910
|
+
const pin = useCallback26(
|
|
8577
8911
|
async (target) => {
|
|
8578
8912
|
if (!sessionId || !codexClient.pinSessionCodexAccount) {
|
|
8579
8913
|
return false;
|
|
@@ -8589,7 +8923,7 @@ function useCodexAccounts(options = {}) {
|
|
|
8589
8923
|
},
|
|
8590
8924
|
[codexClient, workspaceId, sessionId, mutation.run, state.refresh]
|
|
8591
8925
|
);
|
|
8592
|
-
const refreshUsage =
|
|
8926
|
+
const refreshUsage = useCallback26(
|
|
8593
8927
|
async () => {
|
|
8594
8928
|
if (!codexClient.refreshCodexUsage) {
|
|
8595
8929
|
return false;
|
|
@@ -8628,16 +8962,13 @@ function xtermThemeFromTokens(root) {
|
|
|
8628
8962
|
if (typeof window === "undefined" || typeof getComputedStyle === "undefined") return void 0;
|
|
8629
8963
|
const el = root ?? document.documentElement;
|
|
8630
8964
|
const style = getComputedStyle(el);
|
|
8631
|
-
const read = (
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
if (value) return value;
|
|
8635
|
-
}
|
|
8636
|
-
return void 0;
|
|
8965
|
+
const read = (name) => {
|
|
8966
|
+
const value = style.getPropertyValue(name).trim();
|
|
8967
|
+
return value || void 0;
|
|
8637
8968
|
};
|
|
8638
|
-
const bg = read(
|
|
8639
|
-
const fg = read(
|
|
8640
|
-
const accent = read(
|
|
8969
|
+
const bg = read("--og-color-bg");
|
|
8970
|
+
const fg = read("--og-color-fg");
|
|
8971
|
+
const accent = read("--og-color-accent");
|
|
8641
8972
|
const theme = {};
|
|
8642
8973
|
if (bg) theme.background = bg;
|
|
8643
8974
|
if (fg) theme.foreground = fg;
|
|
@@ -8663,6 +8994,7 @@ export {
|
|
|
8663
8994
|
DisclosureDefaultsProvider,
|
|
8664
8995
|
EnrollmentConsent,
|
|
8665
8996
|
EnrollmentDeviceFlow,
|
|
8997
|
+
FILE_ONLY_MESSAGE_TEXT,
|
|
8666
8998
|
FileBrowser,
|
|
8667
8999
|
FleetTile,
|
|
8668
9000
|
LightboxProvider,
|
|
@@ -8718,6 +9050,7 @@ export {
|
|
|
8718
9050
|
gitFileDiffToPatch,
|
|
8719
9051
|
groupTimeline,
|
|
8720
9052
|
hasPermission,
|
|
9053
|
+
humanizeFailureReason,
|
|
8721
9054
|
isApplyPatch,
|
|
8722
9055
|
isCodexAccountEvent,
|
|
8723
9056
|
isExecSessionLostBanner,
|