@opengeni/react 0.36.1 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -2
- package/dist/{chunk-J2RVJ6JX.js → chunk-4IJCL7YO.js} +13 -2
- package/dist/chunk-4IJCL7YO.js.map +1 -0
- package/dist/{chunk-7CJOAW3V.js → chunk-EB67J347.js} +1 -135
- package/dist/chunk-EB67J347.js.map +1 -0
- package/dist/chunk-EKZH6IDG.js +141 -0
- package/dist/chunk-EKZH6IDG.js.map +1 -0
- package/dist/{chunk-OKKMZDQF.js → chunk-JALF5FI3.js} +9 -7
- package/dist/{chunk-OKKMZDQF.js.map → chunk-JALF5FI3.js.map} +1 -1
- package/dist/{chunk-Z5FV355Z.js → chunk-KR2SK5GJ.js} +1382 -724
- package/dist/chunk-KR2SK5GJ.js.map +1 -0
- package/dist/{chunk-N4XEBE23.js → chunk-OMCFRWHL.js} +22 -13
- package/dist/{chunk-N4XEBE23.js.map → chunk-OMCFRWHL.js.map} +1 -1
- package/dist/{chunk-FT2TXNGZ.js → chunk-Q2NCKWTK.js} +183 -18
- package/dist/chunk-Q2NCKWTK.js.map +1 -0
- package/dist/{chunk-22RM4GMO.js → chunk-SJKT4TKW.js} +26 -2
- package/dist/chunk-SJKT4TKW.js.map +1 -0
- package/dist/{chunk-ALA3UGWB.js → chunk-SXIQK54Z.js} +8 -6
- package/dist/{chunk-ALA3UGWB.js.map → chunk-SXIQK54Z.js.map} +1 -1
- package/dist/chunk-WZT5G5OR.js +433 -0
- package/dist/chunk-WZT5G5OR.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/components/chat-composer.d.ts +7 -1
- package/dist/components/human-input-form.d.ts +16 -6
- package/dist/components/human-input-surface.d.ts +19 -0
- package/dist/components/machine-input-display.d.ts +12 -0
- package/dist/components/message-timeline.d.ts +6 -1
- package/dist/components/model-policy-picker.d.ts +78 -0
- package/dist/components/session-chrome.d.ts +2 -1
- package/dist/components/tip-follow.d.ts +30 -0
- package/dist/composer.d.ts +2 -0
- package/dist/composer.js +22 -5
- package/dist/hooks/use-composer.d.ts +10 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +2261 -2230
- package/dist/index.js.map +1 -1
- package/dist/machines.js +4 -3
- package/dist/model-policy.d.ts +12 -4
- package/dist/model-policy.js +5 -1
- package/dist/realtime/dropdown-menu.d.ts +16 -0
- package/dist/realtime/realtime-control.d.ts +126 -0
- package/dist/realtime.d.ts +11 -0
- package/dist/realtime.js +1023 -0
- package/dist/realtime.js.map +1 -0
- package/dist/session-context.d.ts +7 -1
- package/dist/session-ui.d.ts +2 -0
- package/dist/session-ui.js +6 -4
- package/dist/session.js +5 -4
- package/dist/timeline/compute-label.d.ts +2 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/types.d.ts +5 -0
- package/package.json +7 -2
- package/src/client.ts +13 -0
- package/src/components/chat-composer.tsx +19 -5
- package/src/components/composer-transcription-control.tsx +2 -2
- package/src/components/composer.tsx +14 -5
- package/src/components/human-input-form.tsx +506 -186
- package/src/components/human-input-surface.tsx +80 -0
- package/src/components/machine-input-display.ts +83 -0
- package/src/components/message-timeline.tsx +348 -308
- package/src/components/model-policy-picker.tsx +587 -0
- package/src/components/sandbox-files.tsx +1 -1
- package/src/components/session-chrome.tsx +141 -15
- package/src/components/tip-follow.ts +127 -6
- package/src/composer.ts +13 -0
- package/src/hooks/use-composer.ts +229 -29
- package/src/index.ts +19 -0
- package/src/model-policy.ts +51 -7
- package/src/realtime/dropdown-menu.tsx +123 -0
- package/src/realtime/realtime-control.tsx +1178 -0
- package/src/realtime.ts +27 -0
- package/src/session-context.ts +16 -0
- package/src/session-ui.ts +2 -0
- package/src/timeline/compute-label.tsx +18 -0
- package/src/timeline/index.ts +3 -0
- package/src/timeline/projection.ts +21 -1
- package/src/timeline/tool-renderers.tsx +232 -43
- package/src/timeline/types.ts +5 -0
- package/styles/index.css +61 -0
- package/styles/tokens.css +2 -0
- package/dist/chunk-22RM4GMO.js.map +0 -1
- package/dist/chunk-7CJOAW3V.js.map +0 -1
- package/dist/chunk-FT2TXNGZ.js.map +0 -1
- package/dist/chunk-J2RVJ6JX.js.map +0 -1
- package/dist/chunk-Z5FV355Z.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
healthPulses,
|
|
26
26
|
pointsFor,
|
|
27
27
|
useMachines
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-SXIQK54Z.js";
|
|
29
29
|
import {
|
|
30
30
|
SESSION_EVENT_BROWSER_MAX_BYTES,
|
|
31
31
|
SESSION_EVENT_BROWSER_MAX_COUNT,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
useSessionLineage,
|
|
53
53
|
useSessionMcpApprovalPolicy,
|
|
54
54
|
useTurnQueue
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-JALF5FI3.js";
|
|
56
56
|
import {
|
|
57
57
|
ActivityDisclosure,
|
|
58
58
|
ActivityRail,
|
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
CopyHoverFrame,
|
|
63
63
|
DisclosureDefaultsProvider,
|
|
64
64
|
HumanInputForm,
|
|
65
|
+
HumanInputSurface,
|
|
65
66
|
LightboxProvider,
|
|
66
67
|
Markdown,
|
|
67
68
|
MediaEmpty,
|
|
@@ -106,7 +107,8 @@ import {
|
|
|
106
107
|
useLightboxOptional,
|
|
107
108
|
useThemeType,
|
|
108
109
|
v4aToGitFileDiff
|
|
109
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-KR2SK5GJ.js";
|
|
111
|
+
import "./chunk-YDNWMKXO.js";
|
|
110
112
|
import {
|
|
111
113
|
buildTimeline,
|
|
112
114
|
creditExhaustedFromEvents,
|
|
@@ -114,7 +116,7 @@ import {
|
|
|
114
116
|
groupTimeline,
|
|
115
117
|
sessionStatusFromEvents,
|
|
116
118
|
toolDisplayName
|
|
117
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-4IJCL7YO.js";
|
|
118
120
|
import {
|
|
119
121
|
Actions,
|
|
120
122
|
AttachButton,
|
|
@@ -154,21 +156,32 @@ import {
|
|
|
154
156
|
useSlashCommands,
|
|
155
157
|
useTranscription,
|
|
156
158
|
useVoiceInput
|
|
157
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-OMCFRWHL.js";
|
|
158
160
|
import {
|
|
159
161
|
FILE_ONLY_MESSAGE_TEXT,
|
|
160
162
|
composeSendInput,
|
|
161
163
|
shouldSteerOnKey,
|
|
162
164
|
shouldSubmitOnKey,
|
|
163
165
|
useComposer
|
|
164
|
-
} from "./chunk-
|
|
166
|
+
} from "./chunk-Q2NCKWTK.js";
|
|
165
167
|
import {
|
|
166
168
|
useMutationRunner,
|
|
167
|
-
useOpenGeni,
|
|
168
|
-
useOpenGeniClient,
|
|
169
169
|
usePolledValue,
|
|
170
170
|
useSessionEventTrigger
|
|
171
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-EB67J347.js";
|
|
172
|
+
import {
|
|
173
|
+
BillingClassMark,
|
|
174
|
+
ModelPolicyPicker,
|
|
175
|
+
ModelPolicyPickerMenu,
|
|
176
|
+
PickerAnimatedPage,
|
|
177
|
+
PickerBackHeader,
|
|
178
|
+
PickerNavRow,
|
|
179
|
+
defaultModelPolicyPickerMessages
|
|
180
|
+
} from "./chunk-WZT5G5OR.js";
|
|
181
|
+
import {
|
|
182
|
+
useOpenGeni,
|
|
183
|
+
useOpenGeniClient
|
|
184
|
+
} from "./chunk-EKZH6IDG.js";
|
|
172
185
|
import {
|
|
173
186
|
advancedSourceSummary,
|
|
174
187
|
availabilityReasonLabel,
|
|
@@ -180,11 +193,13 @@ import {
|
|
|
180
193
|
findPickerRow,
|
|
181
194
|
groupPickerRowsByBillingClass,
|
|
182
195
|
labelLatencyMode,
|
|
196
|
+
labelReasoningEffort,
|
|
183
197
|
payerSummaryForModel,
|
|
198
|
+
projectClientModelRows,
|
|
184
199
|
projectPickerRows,
|
|
185
200
|
runnableLatencyModesForModel,
|
|
186
201
|
sortPickerRows
|
|
187
|
-
} from "./chunk-
|
|
202
|
+
} from "./chunk-SJKT4TKW.js";
|
|
188
203
|
import {
|
|
189
204
|
Tooltip,
|
|
190
205
|
TooltipContent,
|
|
@@ -192,9 +207,6 @@ import {
|
|
|
192
207
|
TooltipTrigger,
|
|
193
208
|
usePortalTokenStyle
|
|
194
209
|
} from "./chunk-ATSTR5P3.js";
|
|
195
|
-
import {
|
|
196
|
-
cn
|
|
197
|
-
} from "./chunk-TK7G6XLT.js";
|
|
198
210
|
import {
|
|
199
211
|
COMPOSER_PAYMENT_REQUIRED_MESSAGE,
|
|
200
212
|
CREDIT_EXHAUSTION_MESSAGE,
|
|
@@ -208,7 +220,9 @@ import {
|
|
|
208
220
|
truncate,
|
|
209
221
|
tryParseJson
|
|
210
222
|
} from "./chunk-LAKLF4PA.js";
|
|
211
|
-
import
|
|
223
|
+
import {
|
|
224
|
+
cn
|
|
225
|
+
} from "./chunk-TK7G6XLT.js";
|
|
212
226
|
|
|
213
227
|
// src/hooks/use-last-started-turn-policy.ts
|
|
214
228
|
import { useCallback, useEffect } from "react";
|
|
@@ -3324,7 +3338,10 @@ function ChatComposer({
|
|
|
3324
3338
|
disabled,
|
|
3325
3339
|
autoFocus,
|
|
3326
3340
|
hint,
|
|
3341
|
+
controlsLeading,
|
|
3327
3342
|
controlsStart,
|
|
3343
|
+
actionsStart,
|
|
3344
|
+
attachButtonClassName,
|
|
3328
3345
|
transcription,
|
|
3329
3346
|
header,
|
|
3330
3347
|
onPaste,
|
|
@@ -3354,7 +3371,10 @@ function ChatComposer({
|
|
|
3354
3371
|
onPaste,
|
|
3355
3372
|
messages
|
|
3356
3373
|
});
|
|
3357
|
-
const hasControls = Boolean(
|
|
3374
|
+
const hasControls = Boolean(
|
|
3375
|
+
attachments || models || controlsLeading || controlsStart || transcription
|
|
3376
|
+
);
|
|
3377
|
+
const stackActions = hasControls && Boolean(actionsStart);
|
|
3358
3378
|
return /* @__PURE__ */ jsxs2(Root, { controller, className, children: [
|
|
3359
3379
|
/* @__PURE__ */ jsxs2(Frame, { children: [
|
|
3360
3380
|
/* @__PURE__ */ jsx2(CommandPalette2, {}),
|
|
@@ -3364,14 +3384,16 @@ function ChatComposer({
|
|
|
3364
3384
|
/* @__PURE__ */ jsx2(Attachments, {}),
|
|
3365
3385
|
header,
|
|
3366
3386
|
/* @__PURE__ */ jsx2(Input, { placeholder, autoFocus }),
|
|
3367
|
-
controller.confirmState ? /* @__PURE__ */ jsx2(Confirmation, {}) : /* @__PURE__ */ jsxs2(Footer, { children: [
|
|
3368
|
-
hasControls ? /* @__PURE__ */ jsxs2(Controls, { children: [
|
|
3369
|
-
|
|
3387
|
+
controller.confirmState ? /* @__PURE__ */ jsx2(Confirmation, {}) : /* @__PURE__ */ jsxs2(Footer, { className: stackActions ? "flex-wrap" : void 0, children: [
|
|
3388
|
+
hasControls ? /* @__PURE__ */ jsxs2(Controls, { className: stackActions ? "w-full sm:w-auto" : void 0, children: [
|
|
3389
|
+
controlsLeading,
|
|
3390
|
+
/* @__PURE__ */ jsx2(AttachButton, { className: attachButtonClassName }),
|
|
3370
3391
|
transcription ? /* @__PURE__ */ jsx2(ComposerTranscriptionControl, { ...transcription }) : null,
|
|
3371
3392
|
models ? /* @__PURE__ */ jsx2(ModelPicker2, { models, value: selectedModel, onChange: onSelectModel }) : null,
|
|
3372
3393
|
controlsStart
|
|
3373
3394
|
] }) : /* @__PURE__ */ jsx2(Hint, { children: hint }),
|
|
3374
|
-
/* @__PURE__ */ jsxs2(Actions, { children: [
|
|
3395
|
+
/* @__PURE__ */ jsxs2(Actions, { className: stackActions ? "w-full justify-end sm:w-auto" : void 0, children: [
|
|
3396
|
+
actionsStart,
|
|
3375
3397
|
/* @__PURE__ */ jsx2(PauseButton, {}),
|
|
3376
3398
|
/* @__PURE__ */ jsx2(SendButton, {})
|
|
3377
3399
|
] })
|
|
@@ -5100,2414 +5122,2412 @@ function ContextMenu({
|
|
|
5100
5122
|
);
|
|
5101
5123
|
}
|
|
5102
5124
|
|
|
5103
|
-
// src/components/
|
|
5104
|
-
import {
|
|
5105
|
-
function DiffView({
|
|
5106
|
-
diff,
|
|
5107
|
-
fallback,
|
|
5108
|
-
layout = "unified",
|
|
5109
|
-
themeType,
|
|
5110
|
-
isRepo = true,
|
|
5111
|
-
emptyState,
|
|
5112
|
-
className
|
|
5113
|
-
}) {
|
|
5114
|
-
if (diff.length === 0) {
|
|
5115
|
-
return /* @__PURE__ */ jsx6("div", { className: cn("p-3 text-og-sm text-og-fg-subtle", className), children: emptyState ?? (isRepo ? "No changes" : "No repository mounted") });
|
|
5116
|
-
}
|
|
5117
|
-
return /* @__PURE__ */ jsx6(
|
|
5118
|
-
PierreDiff,
|
|
5119
|
-
{
|
|
5120
|
-
diff,
|
|
5121
|
-
layout,
|
|
5122
|
-
themeType,
|
|
5123
|
-
...fallback !== void 0 ? { fallback } : {},
|
|
5124
|
-
className
|
|
5125
|
-
}
|
|
5126
|
-
);
|
|
5127
|
-
}
|
|
5128
|
-
|
|
5129
|
-
// src/components/pierre-file.tsx
|
|
5125
|
+
// src/components/workbench-changes.tsx
|
|
5126
|
+
import { ArrowUpRightIcon, FileWarningIcon, HistoryIcon } from "lucide-react";
|
|
5130
5127
|
import {
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5128
|
+
useCallback as useCallback18,
|
|
5129
|
+
useEffect as useEffect17,
|
|
5130
|
+
useId as useId3,
|
|
5131
|
+
useLayoutEffect as useLayoutEffect2,
|
|
5132
|
+
useMemo as useMemo9,
|
|
5133
|
+
useRef as useRef15,
|
|
5134
|
+
useState as useState14
|
|
5135
5135
|
} from "react";
|
|
5136
|
-
import {
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5136
|
+
import { VList as VList2 } from "virtua";
|
|
5137
|
+
|
|
5138
|
+
// src/hooks/use-windowed-sections.ts
|
|
5139
|
+
import { useCallback as useCallback17, useEffect as useEffect16, useMemo as useMemo8, useRef as useRef14, useState as useState13 } from "react";
|
|
5140
|
+
function computeWindowRange(heights, scrollTop, viewport, overscan) {
|
|
5141
|
+
const n = heights.length;
|
|
5142
|
+
if (n === 0) return { start: 0, end: 0 };
|
|
5143
|
+
const top = Math.max(scrollTop, 0);
|
|
5144
|
+
const bottom = top + Math.max(viewport, 0);
|
|
5145
|
+
let firstVisible = -1;
|
|
5146
|
+
let lastVisible = -1;
|
|
5147
|
+
let acc = 0;
|
|
5148
|
+
let anchor = 0;
|
|
5149
|
+
for (let i = 0; i < n; i++) {
|
|
5150
|
+
const secTop = acc;
|
|
5151
|
+
const secBottom = secTop + Math.max(heights[i] ?? 0, 0);
|
|
5152
|
+
if (secTop <= top) anchor = i;
|
|
5153
|
+
if (secBottom > top && secTop < bottom) {
|
|
5154
|
+
if (firstVisible === -1) firstVisible = i;
|
|
5155
|
+
lastVisible = i;
|
|
5156
|
+
}
|
|
5157
|
+
acc = secBottom;
|
|
5158
|
+
}
|
|
5159
|
+
if (firstVisible === -1) {
|
|
5160
|
+
firstVisible = anchor;
|
|
5161
|
+
lastVisible = anchor;
|
|
5162
|
+
}
|
|
5163
|
+
return {
|
|
5164
|
+
start: Math.max(0, firstVisible - overscan),
|
|
5165
|
+
end: Math.min(n, lastVisible + 1 + overscan)
|
|
5166
|
+
};
|
|
5167
|
+
}
|
|
5168
|
+
function useWindowedSections(opts) {
|
|
5169
|
+
const { count, estimateHeight, overscan = 3 } = opts;
|
|
5170
|
+
const scrollRef = useRef14(null);
|
|
5171
|
+
const [heights, setHeights] = useState13(
|
|
5172
|
+
() => Array.from({ length: count }, (_, i) => estimateHeight(i))
|
|
5173
|
+
);
|
|
5152
5174
|
useEffect16(() => {
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5175
|
+
setHeights((prev) => {
|
|
5176
|
+
if (prev.length === count) return prev;
|
|
5177
|
+
return Array.from({ length: count }, (_, i) => prev[i] ?? estimateHeight(i));
|
|
5156
5178
|
});
|
|
5179
|
+
}, [count]);
|
|
5180
|
+
const heightsRef = useRef14(heights);
|
|
5181
|
+
heightsRef.current = heights;
|
|
5182
|
+
const [range, setRange] = useState13(() => ({
|
|
5183
|
+
start: 0,
|
|
5184
|
+
end: Math.min(count, overscan + 1)
|
|
5185
|
+
}));
|
|
5186
|
+
const recompute = useCallback17(() => {
|
|
5187
|
+
const el = scrollRef.current;
|
|
5188
|
+
if (!el) return;
|
|
5189
|
+
const next = computeWindowRange(heightsRef.current, el.scrollTop, el.clientHeight, overscan);
|
|
5190
|
+
setRange((prev) => prev.start === next.start && prev.end === next.end ? prev : next);
|
|
5191
|
+
}, [overscan]);
|
|
5192
|
+
useEffect16(() => {
|
|
5193
|
+
const el = scrollRef.current;
|
|
5194
|
+
if (!el) return;
|
|
5195
|
+
let raf = 0;
|
|
5196
|
+
const onScroll = () => {
|
|
5197
|
+
if (raf) return;
|
|
5198
|
+
raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame(() => {
|
|
5199
|
+
raf = 0;
|
|
5200
|
+
recompute();
|
|
5201
|
+
}) : (recompute(), 0);
|
|
5202
|
+
};
|
|
5203
|
+
el.addEventListener("scroll", onScroll, { passive: true });
|
|
5204
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => recompute()) : null;
|
|
5205
|
+
ro?.observe(el);
|
|
5206
|
+
recompute();
|
|
5157
5207
|
return () => {
|
|
5158
|
-
|
|
5208
|
+
el.removeEventListener("scroll", onScroll);
|
|
5209
|
+
ro?.disconnect();
|
|
5210
|
+
if (raf && typeof cancelAnimationFrame === "function") cancelAnimationFrame(raf);
|
|
5159
5211
|
};
|
|
5212
|
+
}, [recompute, count]);
|
|
5213
|
+
const measure = useCallback17((index, height) => {
|
|
5214
|
+
if (height <= 0) return;
|
|
5215
|
+
setHeights((prev) => {
|
|
5216
|
+
if (Math.abs((prev[index] ?? 0) - height) < 1) return prev;
|
|
5217
|
+
const next = prev.slice();
|
|
5218
|
+
next[index] = height;
|
|
5219
|
+
return next;
|
|
5220
|
+
});
|
|
5160
5221
|
}, []);
|
|
5161
|
-
const
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5222
|
+
const offsets = useMemo8(() => {
|
|
5223
|
+
const out = new Array(count + 1);
|
|
5224
|
+
out[0] = 0;
|
|
5225
|
+
for (let i = 0; i < count; i++) out[i + 1] = (out[i] ?? 0) + Math.max(heights[i] ?? 0, 0);
|
|
5226
|
+
return out;
|
|
5227
|
+
}, [heights, count]);
|
|
5228
|
+
useEffect16(() => {
|
|
5229
|
+
recompute();
|
|
5230
|
+
}, [offsets, recompute]);
|
|
5231
|
+
const scrollToIndex = useCallback17(
|
|
5232
|
+
(index) => {
|
|
5233
|
+
const el = scrollRef.current;
|
|
5234
|
+
if (!el) return;
|
|
5235
|
+
const clamped = Math.max(0, Math.min(count - 1, index));
|
|
5236
|
+
el.scrollTop = offsets[clamped] ?? 0;
|
|
5174
5237
|
},
|
|
5175
|
-
|
|
5176
|
-
};
|
|
5177
|
-
const pierreVars = {
|
|
5178
|
-
"--diffs-dark-bg": "var(--og-color-bg)",
|
|
5179
|
-
"--diffs-light-bg": "var(--og-color-bg)",
|
|
5180
|
-
"--diffs-bg-buffer-override": "var(--og-color-surface-1)",
|
|
5181
|
-
"--diffs-bg-separator-override": "var(--og-color-surface-1)",
|
|
5182
|
-
"--diffs-font-size": "var(--og-code-font-size)",
|
|
5183
|
-
"--diffs-line-height": "var(--og-code-line-height)"
|
|
5184
|
-
};
|
|
5185
|
-
return /* @__PURE__ */ jsx7("div", { className: cn("min-w-0", className), "data-opengeni-pierre-file": true, style: pierreVars, children: /* @__PURE__ */ jsx7(Suspense, { fallback: loading ?? /* @__PURE__ */ jsx7(FileSkeleton, {}), children: /* @__PURE__ */ jsx7(
|
|
5186
|
-
LazyFile,
|
|
5187
|
-
{
|
|
5188
|
-
file: { name, contents },
|
|
5189
|
-
options,
|
|
5190
|
-
...disableWorkerPool !== void 0 ? { disableWorkerPool } : {}
|
|
5191
|
-
}
|
|
5192
|
-
) }) });
|
|
5193
|
-
}
|
|
5194
|
-
function PlainFile({ name, contents }) {
|
|
5195
|
-
return /* @__PURE__ */ jsx7(
|
|
5196
|
-
"pre",
|
|
5197
|
-
{
|
|
5198
|
-
className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg",
|
|
5199
|
-
"data-file": name,
|
|
5200
|
-
children: contents
|
|
5201
|
-
}
|
|
5238
|
+
[offsets, count]
|
|
5202
5239
|
);
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5240
|
+
return {
|
|
5241
|
+
scrollRef,
|
|
5242
|
+
range,
|
|
5243
|
+
offsets,
|
|
5244
|
+
totalHeight: offsets[count] ?? 0,
|
|
5245
|
+
measure,
|
|
5246
|
+
scrollToIndex
|
|
5247
|
+
};
|
|
5206
5248
|
}
|
|
5207
5249
|
|
|
5208
|
-
// src/components/
|
|
5209
|
-
import {
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5250
|
+
// src/components/workbench-changes.tsx
|
|
5251
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
5252
|
+
var GROUP_THRESHOLD = 20;
|
|
5253
|
+
var OVERSCAN = 2;
|
|
5254
|
+
var HEADER_PX = 30;
|
|
5255
|
+
var LINE_PX = 18;
|
|
5256
|
+
var GUARD_BODY_PX = 52;
|
|
5257
|
+
var COMPACT_SURFACE_PX = 560;
|
|
5258
|
+
var useChangesLayoutEffect = typeof window === "undefined" ? useEffect17 : useLayoutEffect2;
|
|
5259
|
+
var STATUS_TINT2 = {
|
|
5260
|
+
added: "text-og-status-idle",
|
|
5261
|
+
modified: "text-og-status-running",
|
|
5262
|
+
deleted: "text-og-status-failed",
|
|
5263
|
+
renamed: "text-og-accent",
|
|
5264
|
+
copied: "text-og-accent",
|
|
5265
|
+
untracked: "text-og-fg-subtle",
|
|
5266
|
+
ignored: "text-og-fg-subtle",
|
|
5267
|
+
conflicted: "text-og-status-failed",
|
|
5268
|
+
typechange: "text-og-status-running"
|
|
5225
5269
|
};
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5270
|
+
var STATUS_LETTER = {
|
|
5271
|
+
added: "A",
|
|
5272
|
+
modified: "M",
|
|
5273
|
+
deleted: "D",
|
|
5274
|
+
renamed: "R",
|
|
5275
|
+
copied: "C",
|
|
5276
|
+
untracked: "U",
|
|
5277
|
+
ignored: "I",
|
|
5278
|
+
conflicted: "!",
|
|
5279
|
+
typechange: "T"
|
|
5280
|
+
};
|
|
5281
|
+
function compactFileLabel(file) {
|
|
5282
|
+
const slash = file.path.lastIndexOf("/");
|
|
5283
|
+
const basename = slash >= 0 ? file.path.slice(slash + 1) : file.path;
|
|
5284
|
+
const parent = slash >= 0 ? file.path.slice(0, slash + 1) : "";
|
|
5285
|
+
return `${STATUS_LETTER[file.status]} \xB7 ${basename}${parent ? ` \u2014 ${parent}` : ""}`;
|
|
5286
|
+
}
|
|
5287
|
+
function buildRail(files) {
|
|
5288
|
+
const roots = new Set(
|
|
5289
|
+
files.flatMap((file) => file.repoRoot === void 0 ? [] : [file.repoRoot])
|
|
5290
|
+
);
|
|
5291
|
+
const groupByRepo = roots.size > 1;
|
|
5292
|
+
if (!groupByRepo && files.length <= GROUP_THRESHOLD) {
|
|
5293
|
+
return {
|
|
5294
|
+
orderedFiles: files,
|
|
5295
|
+
rows: files.map((file, index) => ({ kind: "file", file, index })),
|
|
5296
|
+
grouped: false
|
|
5297
|
+
};
|
|
5298
|
+
}
|
|
5299
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5300
|
+
for (const file of files) {
|
|
5301
|
+
const slash = file.path.indexOf("/");
|
|
5302
|
+
const key = groupByRepo ? file.repoRoot || "(workspace)" : slash > 0 ? file.path.slice(0, slash) : "(root)";
|
|
5303
|
+
const bucket = groups.get(key);
|
|
5304
|
+
if (bucket) bucket.push(file);
|
|
5305
|
+
else groups.set(key, [file]);
|
|
5306
|
+
}
|
|
5307
|
+
const labels = [...groups.keys()].sort((a, b) => a.localeCompare(b));
|
|
5308
|
+
const orderedFiles = [];
|
|
5309
|
+
const rows = [];
|
|
5310
|
+
for (const label of labels) {
|
|
5311
|
+
const bucket = (groups.get(label) ?? []).slice().sort((a, b) => a.path.localeCompare(b.path));
|
|
5312
|
+
rows.push({ kind: "group", label, count: bucket.length });
|
|
5313
|
+
for (const file of bucket) {
|
|
5314
|
+
rows.push({ kind: "file", file, index: orderedFiles.length });
|
|
5315
|
+
orderedFiles.push(file);
|
|
5316
|
+
}
|
|
5259
5317
|
}
|
|
5318
|
+
return { orderedFiles, rows, grouped: true };
|
|
5260
5319
|
}
|
|
5261
|
-
function
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5320
|
+
function isGuarded(file) {
|
|
5321
|
+
return file.isBinary || file.truncated;
|
|
5322
|
+
}
|
|
5323
|
+
function estimateSectionHeight(file) {
|
|
5324
|
+
if (isGuarded(file)) return HEADER_PX + GUARD_BODY_PX;
|
|
5325
|
+
let lines = 0;
|
|
5326
|
+
for (const hunk of file.hunks) lines += hunk.lines.length + 1;
|
|
5327
|
+
return HEADER_PX + Math.max(lines, 1) * LINE_PX + 8;
|
|
5328
|
+
}
|
|
5329
|
+
function WorkbenchChanges({
|
|
5330
|
+
diff,
|
|
5331
|
+
source,
|
|
5332
|
+
capturedAt,
|
|
5333
|
+
captureRevision,
|
|
5334
|
+
themeType,
|
|
5335
|
+
onOpenFile,
|
|
5272
5336
|
className
|
|
5273
5337
|
}) {
|
|
5274
|
-
const
|
|
5275
|
-
const [
|
|
5276
|
-
const [
|
|
5277
|
-
const
|
|
5278
|
-
const [
|
|
5279
|
-
const [
|
|
5280
|
-
const
|
|
5281
|
-
const
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
const lastSeed = useRef14({ path, contents: initialContents });
|
|
5285
|
-
useEffect17(() => {
|
|
5286
|
-
const seedChanged = lastSeed.current.path !== path || lastSeed.current.contents !== initialContents;
|
|
5287
|
-
if (!seedChanged) return;
|
|
5288
|
-
lastSeed.current = { path, contents: initialContents };
|
|
5289
|
-
editIntentFiredRef.current = false;
|
|
5290
|
-
setValue(initialContents);
|
|
5291
|
-
setBaseline(initialContents);
|
|
5292
|
-
setSaveError(null);
|
|
5293
|
-
setSavedTick(false);
|
|
5294
|
-
}, [path, initialContents]);
|
|
5295
|
-
const noteEdit = useCallback17(
|
|
5296
|
-
(next) => {
|
|
5297
|
-
setValue(next);
|
|
5298
|
-
setSavedTick(false);
|
|
5299
|
-
if (!editIntentFiredRef.current && next !== baseline) {
|
|
5300
|
-
editIntentFiredRef.current = true;
|
|
5301
|
-
onEditIntent?.();
|
|
5302
|
-
}
|
|
5303
|
-
},
|
|
5304
|
-
[baseline, onEditIntent]
|
|
5338
|
+
const rootRef = useRef15(null);
|
|
5339
|
+
const [compact, setCompact] = useState14(false);
|
|
5340
|
+
const [coarsePointer, setCoarsePointer] = useState14(false);
|
|
5341
|
+
const resolvedTheme = useThemeType(themeType);
|
|
5342
|
+
const [layout, setLayout] = useState14("unified");
|
|
5343
|
+
const [activePath, setActivePath] = useState14(null);
|
|
5344
|
+
const pickerId = useId3();
|
|
5345
|
+
const unicodeFontPaths = useMemo9(
|
|
5346
|
+
() => diff.flatMap((file) => file.oldPath ? [file.path, file.oldPath] : [file.path]),
|
|
5347
|
+
[diff]
|
|
5305
5348
|
);
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
languageExtension = await LANGUAGE_LOADERS[langKey]?.() ?? null;
|
|
5316
|
-
} catch {
|
|
5317
|
-
languageExtension = null;
|
|
5318
|
-
}
|
|
5319
|
-
}
|
|
5320
|
-
if (cancelled) return;
|
|
5321
|
-
const saveKeymapExtension = (run) => cmMod.Prec.highest(
|
|
5322
|
-
cmMod.keymap.of([
|
|
5323
|
-
{
|
|
5324
|
-
key: "Mod-s",
|
|
5325
|
-
preventDefault: true,
|
|
5326
|
-
run: () => {
|
|
5327
|
-
run();
|
|
5328
|
-
return true;
|
|
5329
|
-
}
|
|
5330
|
-
}
|
|
5331
|
-
])
|
|
5332
|
-
);
|
|
5333
|
-
setBundle({
|
|
5334
|
-
Editor: cmMod.default,
|
|
5335
|
-
saveKeymapExtension,
|
|
5336
|
-
languageExtension
|
|
5337
|
-
});
|
|
5338
|
-
setFailed(false);
|
|
5339
|
-
} catch {
|
|
5340
|
-
if (!cancelled) setFailed(true);
|
|
5341
|
-
}
|
|
5342
|
-
})();
|
|
5343
|
-
return () => {
|
|
5344
|
-
cancelled = true;
|
|
5349
|
+
useUnicodeFallbackFonts(unicodeFontPaths);
|
|
5350
|
+
const { orderedFiles, rows, grouped } = useMemo9(() => buildRail(diff), [diff]);
|
|
5351
|
+
const selectedIndex = orderedFiles.findIndex((file) => file.path === activePath);
|
|
5352
|
+
const activeIndex = selectedIndex >= 0 ? selectedIndex : 0;
|
|
5353
|
+
useChangesLayoutEffect(() => {
|
|
5354
|
+
const root = rootRef.current;
|
|
5355
|
+
if (!root || typeof ResizeObserver === "undefined") return;
|
|
5356
|
+
const update = (width) => {
|
|
5357
|
+
if (width > 0) setCompact(width < COMPACT_SURFACE_PX);
|
|
5345
5358
|
};
|
|
5346
|
-
|
|
5347
|
-
|
|
5359
|
+
update(root.getBoundingClientRect().width);
|
|
5360
|
+
const observer = new ResizeObserver((entries) => {
|
|
5361
|
+
update(entries[0]?.contentRect.width ?? root.getBoundingClientRect().width);
|
|
5362
|
+
});
|
|
5363
|
+
observer.observe(root);
|
|
5364
|
+
return () => observer.disconnect();
|
|
5365
|
+
}, []);
|
|
5366
|
+
useChangesLayoutEffect(() => {
|
|
5367
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
5368
|
+
const query = window.matchMedia("(pointer: coarse)");
|
|
5369
|
+
const update = () => setCoarsePointer(query.matches);
|
|
5370
|
+
update();
|
|
5371
|
+
if (typeof query.addEventListener === "function") {
|
|
5372
|
+
query.addEventListener("change", update);
|
|
5373
|
+
return () => query.removeEventListener("change", update);
|
|
5374
|
+
}
|
|
5375
|
+
if (typeof query.addListener === "function") {
|
|
5376
|
+
query.addListener(update);
|
|
5377
|
+
return () => query.removeListener(update);
|
|
5378
|
+
}
|
|
5379
|
+
}, []);
|
|
5380
|
+
const additions = useMemo9(() => diff.reduce((sum, f) => sum + f.additions, 0), [diff]);
|
|
5381
|
+
const deletions = useMemo9(() => diff.reduce((sum, f) => sum + f.deletions, 0), [diff]);
|
|
5382
|
+
const estimateHeight = useCallback18(
|
|
5383
|
+
(index) => {
|
|
5384
|
+
const file = orderedFiles[index];
|
|
5385
|
+
return file ? estimateSectionHeight(file) : HEADER_PX + LINE_PX;
|
|
5386
|
+
},
|
|
5387
|
+
[orderedFiles]
|
|
5388
|
+
);
|
|
5389
|
+
const windowed = useWindowedSections({
|
|
5390
|
+
count: orderedFiles.length,
|
|
5391
|
+
estimateHeight,
|
|
5392
|
+
overscan: OVERSCAN
|
|
5348
5393
|
});
|
|
5349
|
-
const
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
setSavedTick(true);
|
|
5361
|
-
} catch (cause) {
|
|
5362
|
-
setSaveError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
5363
|
-
} finally {
|
|
5364
|
-
setSaving(false);
|
|
5394
|
+
const jumpTo = useCallback18(
|
|
5395
|
+
(index) => {
|
|
5396
|
+
setActivePath(orderedFiles[index]?.path ?? null);
|
|
5397
|
+
windowed.scrollToIndex(index);
|
|
5398
|
+
},
|
|
5399
|
+
[orderedFiles, windowed]
|
|
5400
|
+
);
|
|
5401
|
+
const onPaneScroll = useCallback18(() => {
|
|
5402
|
+
const el = windowed.scrollRef.current;
|
|
5403
|
+
if (!el) {
|
|
5404
|
+
return;
|
|
5365
5405
|
}
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
setSaveError(null);
|
|
5373
|
-
setSavedTick(false);
|
|
5374
|
-
try {
|
|
5375
|
-
await onOverwrite(snapshot);
|
|
5376
|
-
setBaseline(snapshot);
|
|
5377
|
-
lastSeed.current = { path, contents: snapshot };
|
|
5378
|
-
setSavedTick(true);
|
|
5379
|
-
} catch (cause) {
|
|
5380
|
-
setSaveError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
5381
|
-
} finally {
|
|
5382
|
-
setSaving(false);
|
|
5406
|
+
const top = el.scrollTop;
|
|
5407
|
+
const offsets = windowed.offsets;
|
|
5408
|
+
let idx = 0;
|
|
5409
|
+
for (let i = 0; i < orderedFiles.length; i++) {
|
|
5410
|
+
if ((offsets[i] ?? 0) <= top + 4) idx = i;
|
|
5411
|
+
else break;
|
|
5383
5412
|
}
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
};
|
|
5413
|
+
const nextPath = orderedFiles[idx]?.path ?? null;
|
|
5414
|
+
setActivePath((previous) => previous === nextPath ? previous : nextPath);
|
|
5415
|
+
}, [windowed, orderedFiles]);
|
|
5388
5416
|
useEffect17(() => {
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
const
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
"div",
|
|
5403
|
-
{
|
|
5404
|
-
className: cn("flex h-full min-h-0 flex-col", className),
|
|
5405
|
-
"data-opengeni-code-editor": true,
|
|
5406
|
-
style: editorVars,
|
|
5417
|
+
const el = windowed.scrollRef.current;
|
|
5418
|
+
if (!el) return;
|
|
5419
|
+
el.addEventListener("scroll", onPaneScroll, { passive: true });
|
|
5420
|
+
return () => el.removeEventListener("scroll", onPaneScroll);
|
|
5421
|
+
}, [windowed.scrollRef, onPaneScroll]);
|
|
5422
|
+
const sourceBadge = describeSource(source, capturedAt, captureRevision ?? null);
|
|
5423
|
+
const activeFile = orderedFiles[activeIndex] ?? orderedFiles[0];
|
|
5424
|
+
return /* @__PURE__ */ jsxs6(
|
|
5425
|
+
"div",
|
|
5426
|
+
{
|
|
5427
|
+
ref: rootRef,
|
|
5428
|
+
className: cn("flex h-full min-h-0 min-w-0 flex-col", className),
|
|
5429
|
+
"data-workbench-changes-layout": compact ? "compact" : "rail",
|
|
5407
5430
|
children: [
|
|
5408
|
-
/* @__PURE__ */ jsxs6(
|
|
5409
|
-
/* @__PURE__ */ jsx8(
|
|
5410
|
-
"span",
|
|
5411
|
-
{
|
|
5412
|
-
className: cn(
|
|
5413
|
-
"size-1.5 shrink-0 rounded-full transition-colors",
|
|
5414
|
-
readOnly ? "bg-transparent" : dirty ? "bg-og-status-running" : "bg-og-status-idle"
|
|
5415
|
-
),
|
|
5416
|
-
title: readOnly ? "read-only" : dirty ? "unsaved changes" : "saved"
|
|
5417
|
-
}
|
|
5418
|
-
),
|
|
5419
|
-
/* @__PURE__ */ jsxs6("span", { className: "truncate font-og-mono text-og-xs text-og-fg-muted", children: [
|
|
5420
|
-
fileName,
|
|
5421
|
-
dirty && !readOnly ? " \u2022" : ""
|
|
5422
|
-
] }),
|
|
5423
|
-
/* @__PURE__ */ jsxs6("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
|
|
5424
|
-
saveError && !saveConflict && /* @__PURE__ */ jsx8(
|
|
5425
|
-
"span",
|
|
5426
|
-
{
|
|
5427
|
-
className: "max-w-[220px] truncate text-og-xs text-og-status-failed",
|
|
5428
|
-
title: saveError.message,
|
|
5429
|
-
children: saveError.message
|
|
5430
|
-
}
|
|
5431
|
-
),
|
|
5432
|
-
!saveError && savedTick && /* @__PURE__ */ jsx8("span", { className: "text-og-xs text-og-status-idle", children: "Saved" }),
|
|
5433
|
-
readOnly ? /* @__PURE__ */ jsx8("span", { className: "text-og-xs uppercase tracking-wide text-og-fg-subtle", children: "Read-only" }) : !saveConflict ? /* @__PURE__ */ jsxs6(
|
|
5434
|
-
"button",
|
|
5435
|
-
{
|
|
5436
|
-
type: "button",
|
|
5437
|
-
onClick: () => void save(),
|
|
5438
|
-
disabled: saving || !dirty,
|
|
5439
|
-
className: cn(
|
|
5440
|
-
"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-11",
|
|
5441
|
-
saving || !dirty ? "cursor-default text-og-fg-subtle opacity-60" : "text-og-fg hover:bg-og-accent-soft"
|
|
5442
|
-
),
|
|
5443
|
-
title: "Save (\u2318/Ctrl+S)",
|
|
5444
|
-
children: [
|
|
5445
|
-
saving ? /* @__PURE__ */ jsx8(Loader2Icon, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx8(SaveIcon, { className: "size-3" }),
|
|
5446
|
-
"Save"
|
|
5447
|
-
]
|
|
5448
|
-
}
|
|
5449
|
-
) : null
|
|
5450
|
-
] })
|
|
5451
|
-
] }),
|
|
5452
|
-
saveConflict ? /* @__PURE__ */ jsxs6(
|
|
5431
|
+
/* @__PURE__ */ jsxs6(
|
|
5453
5432
|
"div",
|
|
5454
5433
|
{
|
|
5455
|
-
className:
|
|
5456
|
-
|
|
5434
|
+
className: cn(
|
|
5435
|
+
"flex shrink-0 items-center justify-between gap-2 border-b border-og-border px-3 py-1.5",
|
|
5436
|
+
compact && source === "capture" && "flex-col items-stretch gap-1.5 py-2"
|
|
5437
|
+
),
|
|
5457
5438
|
children: [
|
|
5458
|
-
/* @__PURE__ */ jsxs6(
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
"
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5439
|
+
/* @__PURE__ */ jsxs6(
|
|
5440
|
+
"span",
|
|
5441
|
+
{
|
|
5442
|
+
role: "status",
|
|
5443
|
+
"aria-atomic": "true",
|
|
5444
|
+
"aria-live": "polite",
|
|
5445
|
+
"data-contrast-audited": true,
|
|
5446
|
+
className: "min-w-0 text-og-xs text-og-fg-muted",
|
|
5447
|
+
children: [
|
|
5448
|
+
diff.length,
|
|
5449
|
+
" ",
|
|
5450
|
+
diff.length === 1 ? "file" : "files",
|
|
5451
|
+
" changed",
|
|
5452
|
+
/* @__PURE__ */ jsxs6("span", { "data-contrast-audited": true, className: "ml-2 text-og-status-idle", children: [
|
|
5453
|
+
"+",
|
|
5454
|
+
additions
|
|
5455
|
+
] }),
|
|
5456
|
+
/* @__PURE__ */ jsxs6("span", { "data-contrast-audited": true, className: "ml-1 text-og-status-failed", children: [
|
|
5457
|
+
"\u2212",
|
|
5458
|
+
deletions
|
|
5459
|
+
] })
|
|
5460
|
+
]
|
|
5461
|
+
}
|
|
5462
|
+
),
|
|
5463
|
+
/* @__PURE__ */ jsxs6(
|
|
5464
|
+
"div",
|
|
5465
|
+
{
|
|
5466
|
+
className: cn(
|
|
5467
|
+
"flex shrink-0 items-center gap-2",
|
|
5468
|
+
compact && source === "capture" && "self-start"
|
|
5469
|
+
),
|
|
5470
|
+
children: [
|
|
5471
|
+
compact ? null : /* @__PURE__ */ jsx6(LayoutToggle, { layout, onChange: setLayout }),
|
|
5472
|
+
/* @__PURE__ */ jsx6(SourceBadge, { source, capturedAt, label: sourceBadge })
|
|
5473
|
+
]
|
|
5474
|
+
}
|
|
5475
|
+
)
|
|
5487
5476
|
]
|
|
5488
5477
|
}
|
|
5489
|
-
)
|
|
5490
|
-
/* @__PURE__ */
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5478
|
+
),
|
|
5479
|
+
compact ? /* @__PURE__ */ jsxs6("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
5480
|
+
/* @__PURE__ */ jsxs6("div", { className: "shrink-0 border-b border-og-border bg-og-surface-1 p-2", children: [
|
|
5481
|
+
/* @__PURE__ */ jsx6("label", { className: "sr-only", htmlFor: pickerId, children: "Changed file" }),
|
|
5482
|
+
/* @__PURE__ */ jsx6(
|
|
5483
|
+
"select",
|
|
5484
|
+
{
|
|
5485
|
+
id: pickerId,
|
|
5486
|
+
"aria-label": "Changed file",
|
|
5487
|
+
value: activeIndex,
|
|
5488
|
+
onChange: (event) => {
|
|
5489
|
+
const index = Number(event.currentTarget.value);
|
|
5490
|
+
setActivePath(orderedFiles[index]?.path ?? null);
|
|
5491
|
+
},
|
|
5492
|
+
title: activeFile?.path,
|
|
5493
|
+
"data-compact-file-picker": true,
|
|
5494
|
+
className: "h-11 w-full rounded-og-md border border-og-border bg-og-bg px-3 font-og-mono text-og-sm text-og-fg outline-none transition-colors focus:border-og-accent focus:ring-2 focus:ring-og-accent-soft",
|
|
5495
|
+
children: orderedFiles.map((file, index) => /* @__PURE__ */ jsx6("option", { value: index, children: compactFileLabel(file) }, file.path))
|
|
5496
|
+
}
|
|
5497
|
+
)
|
|
5498
|
+
] }),
|
|
5499
|
+
/* @__PURE__ */ jsx6("div", { className: "min-h-0 min-w-0 flex-1 overflow-auto", "data-opengeni-changes-pane": true, children: activeFile ? /* @__PURE__ */ jsx6(
|
|
5500
|
+
DiffSection,
|
|
5501
|
+
{
|
|
5502
|
+
file: activeFile,
|
|
5503
|
+
layout: "unified",
|
|
5504
|
+
themeType: resolvedTheme,
|
|
5505
|
+
...onOpenFile ? { onOpenFile } : {}
|
|
5506
|
+
}
|
|
5507
|
+
) : null })
|
|
5508
|
+
] }) : /* @__PURE__ */ jsxs6("div", { className: "flex min-h-0 flex-1", children: [
|
|
5509
|
+
/* @__PURE__ */ jsx6("div", { className: "w-[clamp(12rem,28%,15rem)] shrink-0 border-r border-og-border bg-og-surface-1/35", children: /* @__PURE__ */ jsx6(
|
|
5510
|
+
VList2,
|
|
5511
|
+
{
|
|
5512
|
+
className: "h-full",
|
|
5513
|
+
itemSize: coarsePointer ? 44 : 28,
|
|
5514
|
+
ssrCount: Math.min(30, rows.length),
|
|
5515
|
+
children: rows.map(
|
|
5516
|
+
(row) => row.kind === "group" ? /* @__PURE__ */ jsxs6(
|
|
5517
|
+
"div",
|
|
5518
|
+
{
|
|
5519
|
+
"data-rail-group": true,
|
|
5520
|
+
className: "flex items-center gap-1.5 px-2 pb-0.5 pt-2 text-og-xs font-medium uppercase tracking-wide text-og-fg-subtle",
|
|
5521
|
+
children: [
|
|
5522
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate", children: row.label }),
|
|
5523
|
+
/* @__PURE__ */ jsx6("span", { className: "shrink-0", children: row.count })
|
|
5524
|
+
]
|
|
5525
|
+
},
|
|
5526
|
+
`g:${row.label}`
|
|
5527
|
+
) : /* @__PURE__ */ jsx6(
|
|
5528
|
+
RailFileRow,
|
|
5529
|
+
{
|
|
5530
|
+
file: row.file,
|
|
5531
|
+
grouped,
|
|
5532
|
+
active: row.index === activeIndex,
|
|
5533
|
+
onClick: () => jumpTo(row.index)
|
|
5534
|
+
},
|
|
5535
|
+
row.file.path
|
|
5536
|
+
)
|
|
5537
|
+
)
|
|
5538
|
+
}
|
|
5539
|
+
) }),
|
|
5540
|
+
/* @__PURE__ */ jsx6(
|
|
5541
|
+
"div",
|
|
5542
|
+
{
|
|
5543
|
+
ref: windowed.scrollRef,
|
|
5544
|
+
className: "min-h-0 min-w-0 flex-1 overflow-auto",
|
|
5545
|
+
"data-opengeni-changes-pane": true,
|
|
5546
|
+
children: /* @__PURE__ */ jsx6("div", { style: { position: "relative", height: windowed.totalHeight }, children: orderedFiles.map((file, index) => {
|
|
5547
|
+
if (index < windowed.range.start || index >= windowed.range.end) return null;
|
|
5548
|
+
return /* @__PURE__ */ jsx6(
|
|
5549
|
+
MeasuredSection,
|
|
5550
|
+
{
|
|
5551
|
+
index,
|
|
5552
|
+
top: windowed.offsets[index] ?? 0,
|
|
5553
|
+
onMeasure: windowed.measure,
|
|
5554
|
+
children: /* @__PURE__ */ jsx6(
|
|
5555
|
+
DiffSection,
|
|
5556
|
+
{
|
|
5557
|
+
file,
|
|
5558
|
+
layout,
|
|
5559
|
+
themeType: resolvedTheme,
|
|
5560
|
+
...onOpenFile ? { onOpenFile } : {}
|
|
5561
|
+
}
|
|
5562
|
+
)
|
|
5563
|
+
},
|
|
5564
|
+
file.path
|
|
5565
|
+
);
|
|
5566
|
+
}) })
|
|
5567
|
+
}
|
|
5568
|
+
)
|
|
5569
|
+
] })
|
|
5512
5570
|
]
|
|
5513
5571
|
}
|
|
5514
5572
|
);
|
|
5515
5573
|
}
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
function PlainTextarea({
|
|
5521
|
-
value,
|
|
5522
|
-
readOnly,
|
|
5523
|
-
onChange,
|
|
5524
|
-
onSave
|
|
5574
|
+
function SourceBadge({
|
|
5575
|
+
source,
|
|
5576
|
+
capturedAt,
|
|
5577
|
+
label
|
|
5525
5578
|
}) {
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
className: "h-full w-full resize-none bg-transparent p-2 font-og-mono text-og-sm text-og-fg outline-none"
|
|
5541
|
-
}
|
|
5542
|
-
);
|
|
5579
|
+
if (source === "capture" && capturedAt) {
|
|
5580
|
+
return /* @__PURE__ */ jsxs6(
|
|
5581
|
+
"span",
|
|
5582
|
+
{
|
|
5583
|
+
className: "inline-flex items-center gap-1 rounded-og-xs border border-og-border px-1.5 py-px text-og-xs text-og-fg-muted",
|
|
5584
|
+
title: new Date(capturedAt).toLocaleString(),
|
|
5585
|
+
children: [
|
|
5586
|
+
/* @__PURE__ */ jsx6(HistoryIcon, { className: "size-3 shrink-0 text-og-status-running", "aria-hidden": true }),
|
|
5587
|
+
label
|
|
5588
|
+
]
|
|
5589
|
+
}
|
|
5590
|
+
);
|
|
5591
|
+
}
|
|
5592
|
+
return /* @__PURE__ */ jsx6("span", { className: "rounded-og-xs bg-og-surface-2 px-1.5 py-px text-og-xs text-og-fg-subtle", children: label });
|
|
5543
5593
|
}
|
|
5544
|
-
function
|
|
5545
|
-
|
|
5594
|
+
function describeSource(source, capturedAt, revision) {
|
|
5595
|
+
if (source !== "capture" || !capturedAt) return "Live diff";
|
|
5596
|
+
const time = formatAsOf(capturedAt, Date.now());
|
|
5597
|
+
return revision !== null ? `as of turn ${revision} \xB7 ${time}` : `as of ${time}`;
|
|
5546
5598
|
}
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
function SandboxFiles({
|
|
5553
|
-
files,
|
|
5554
|
-
git,
|
|
5555
|
-
fileSystemAvailable = true,
|
|
5556
|
-
usePierre = true,
|
|
5557
|
-
editable = true,
|
|
5558
|
-
onEditIntent,
|
|
5559
|
-
requestedPath,
|
|
5560
|
-
requestedPathRequestId,
|
|
5561
|
-
requestedPathReady = true,
|
|
5562
|
-
workspaceResting = false,
|
|
5563
|
-
workspaceWaking = false,
|
|
5564
|
-
liveWorkspaceReady = true,
|
|
5565
|
-
onWakeWorkspace,
|
|
5566
|
-
themeType,
|
|
5567
|
-
className
|
|
5599
|
+
function RailFileRow({
|
|
5600
|
+
file,
|
|
5601
|
+
grouped,
|
|
5602
|
+
active,
|
|
5603
|
+
onClick
|
|
5568
5604
|
}) {
|
|
5569
|
-
const
|
|
5570
|
-
const
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5605
|
+
const repoPrefix = file.repoRoot ? `${file.repoRoot}/` : null;
|
|
5606
|
+
const shown = grouped ? file.repoRoot !== void 0 ? repoPrefix && file.path.startsWith(repoPrefix) ? file.path.slice(repoPrefix.length) : file.path : file.path.slice(file.path.indexOf("/") + 1) || file.path : file.path;
|
|
5607
|
+
return /* @__PURE__ */ jsxs6(
|
|
5608
|
+
"button",
|
|
5609
|
+
{
|
|
5610
|
+
type: "button",
|
|
5611
|
+
onClick,
|
|
5612
|
+
title: file.path,
|
|
5613
|
+
"data-rail-file": true,
|
|
5614
|
+
className: cn(
|
|
5615
|
+
"relative flex min-h-7 w-full items-center gap-1.5 truncate px-2 py-0.5 text-left text-og-sm transition-colors hover:bg-og-surface-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent pointer-coarse:min-h-11",
|
|
5616
|
+
grouped && "pl-3",
|
|
5617
|
+
active && "bg-og-accent-soft text-og-fg before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-r-full before:bg-og-accent"
|
|
5618
|
+
),
|
|
5619
|
+
children: [
|
|
5620
|
+
/* @__PURE__ */ jsx6(
|
|
5621
|
+
"span",
|
|
5622
|
+
{
|
|
5623
|
+
"data-contrast-audited": true,
|
|
5624
|
+
className: cn("w-3 shrink-0 text-center font-og-mono text-og-xs", STATUS_TINT2[file.status]),
|
|
5625
|
+
children: STATUS_LETTER[file.status]
|
|
5626
|
+
}
|
|
5627
|
+
),
|
|
5628
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 flex-1 truncate", children: shown }),
|
|
5629
|
+
/* @__PURE__ */ jsxs6("span", { className: "ml-auto flex shrink-0 items-center gap-1 pl-1 font-og-mono text-og-xs", children: [
|
|
5630
|
+
/* @__PURE__ */ jsxs6("span", { "data-contrast-audited": true, className: "text-og-status-idle", children: [
|
|
5631
|
+
"+",
|
|
5632
|
+
file.additions
|
|
5633
|
+
] }),
|
|
5634
|
+
/* @__PURE__ */ jsxs6("span", { "data-contrast-audited": true, className: "text-og-status-failed", children: [
|
|
5635
|
+
"\u2212",
|
|
5636
|
+
file.deletions
|
|
5637
|
+
] })
|
|
5638
|
+
] })
|
|
5639
|
+
]
|
|
5588
5640
|
}
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
const
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5641
|
+
);
|
|
5642
|
+
}
|
|
5643
|
+
function MeasuredSection({
|
|
5644
|
+
index,
|
|
5645
|
+
top,
|
|
5646
|
+
onMeasure,
|
|
5647
|
+
children
|
|
5648
|
+
}) {
|
|
5649
|
+
const ref = useRef15(null);
|
|
5650
|
+
useEffect17(() => {
|
|
5651
|
+
const el = ref.current;
|
|
5652
|
+
if (!el) return;
|
|
5653
|
+
const report = () => onMeasure(index, el.offsetHeight);
|
|
5654
|
+
report();
|
|
5655
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(report) : null;
|
|
5656
|
+
ro?.observe(el);
|
|
5657
|
+
return () => ro?.disconnect();
|
|
5658
|
+
}, [index, onMeasure]);
|
|
5659
|
+
return /* @__PURE__ */ jsx6(
|
|
5660
|
+
"div",
|
|
5661
|
+
{
|
|
5662
|
+
ref,
|
|
5663
|
+
"data-diff-section": true,
|
|
5664
|
+
"data-diff-index": index,
|
|
5665
|
+
style: { position: "absolute", top, left: 0, right: 0 },
|
|
5666
|
+
children
|
|
5613
5667
|
}
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
return /* @__PURE__ */
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
className,
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5668
|
+
);
|
|
5669
|
+
}
|
|
5670
|
+
function DiffSection({
|
|
5671
|
+
file,
|
|
5672
|
+
layout,
|
|
5673
|
+
themeType,
|
|
5674
|
+
onOpenFile
|
|
5675
|
+
}) {
|
|
5676
|
+
if (isGuarded(file)) {
|
|
5677
|
+
const renamed = file.oldPath && file.oldPath !== file.path;
|
|
5678
|
+
return /* @__PURE__ */ jsxs6("section", { className: "border-b border-og-border pb-1", children: [
|
|
5679
|
+
/* @__PURE__ */ jsxs6("header", { className: "flex items-center justify-between gap-2 bg-og-surface-1 px-3 py-1.5 text-og-sm", children: [
|
|
5680
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate font-og-mono text-og-xs", children: renamed ? `${file.oldPath} \u2192 ${file.path}` : file.path }),
|
|
5681
|
+
/* @__PURE__ */ jsxs6("span", { className: "flex shrink-0 items-center gap-2 font-og-mono text-og-xs", children: [
|
|
5682
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-og-status-idle", children: [
|
|
5683
|
+
"+",
|
|
5684
|
+
file.additions
|
|
5685
|
+
] }),
|
|
5686
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-og-status-failed", children: [
|
|
5687
|
+
"\u2212",
|
|
5688
|
+
file.deletions
|
|
5689
|
+
] })
|
|
5690
|
+
] })
|
|
5691
|
+
] }),
|
|
5692
|
+
/* @__PURE__ */ jsx6(GuardBody, { file, ...onOpenFile ? { onOpenFile } : {} })
|
|
5693
|
+
] });
|
|
5634
5694
|
}
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5695
|
+
return /* @__PURE__ */ jsx6("section", { "data-pierre-section": true, className: "border-b border-og-border pb-2", children: /* @__PURE__ */ jsx6(PierreDiff, { diff: [file], layout, themeType, className: "px-1" }) });
|
|
5696
|
+
}
|
|
5697
|
+
function GuardBody({
|
|
5698
|
+
file,
|
|
5699
|
+
onOpenFile
|
|
5700
|
+
}) {
|
|
5701
|
+
const reason = file.isBinary ? "Binary file" : "Diff too large to show here";
|
|
5702
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-2 px-3 py-3 text-og-sm text-og-fg-subtle", children: [
|
|
5703
|
+
/* @__PURE__ */ jsx6(FileWarningIcon, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
5704
|
+
/* @__PURE__ */ jsxs6("span", { className: "min-w-0 flex-1", children: [
|
|
5705
|
+
reason,
|
|
5706
|
+
"."
|
|
5707
|
+
] }),
|
|
5708
|
+
onOpenFile ? /* @__PURE__ */ jsxs6(
|
|
5709
|
+
"button",
|
|
5638
5710
|
{
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
className: "size-5 animate-spin motion-reduce:animate-none",
|
|
5643
|
-
"aria-hidden": true
|
|
5644
|
-
}
|
|
5645
|
-
) : /* @__PURE__ */ jsx9(FileCode2Icon, { className: "size-5", "aria-hidden": true }),
|
|
5646
|
-
title: workspaceWaking ? "Waking workspace" : "Workspace is resting",
|
|
5647
|
-
announce: "status",
|
|
5711
|
+
type: "button",
|
|
5712
|
+
onClick: () => onOpenFile(file.path),
|
|
5713
|
+
className: "inline-flex min-h-8 shrink-0 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:bg-og-surface-2 hover:text-og-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-11",
|
|
5648
5714
|
children: [
|
|
5649
|
-
|
|
5650
|
-
|
|
5715
|
+
"Open in Files",
|
|
5716
|
+
/* @__PURE__ */ jsx6(ArrowUpRightIcon, { className: "size-3.5", "aria-hidden": true })
|
|
5651
5717
|
]
|
|
5652
5718
|
}
|
|
5653
|
-
)
|
|
5654
|
-
}
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
result: files,
|
|
5669
|
-
selectedPath: selected ?? void 0,
|
|
5670
|
-
onSelectFile: selectFile,
|
|
5671
|
-
editable,
|
|
5672
|
-
emptyState: "This directory is empty",
|
|
5673
|
-
className: "min-w-0 flex-1"
|
|
5674
|
-
}
|
|
5675
|
-
)
|
|
5676
|
-
}
|
|
5719
|
+
) : null
|
|
5720
|
+
] });
|
|
5721
|
+
}
|
|
5722
|
+
function LayoutToggle({
|
|
5723
|
+
layout,
|
|
5724
|
+
onChange
|
|
5725
|
+
}) {
|
|
5726
|
+
return /* @__PURE__ */ jsx6("div", { className: "inline-flex items-center rounded-og-sm border border-og-border p-0.5", children: ["unified", "split"].map((value) => /* @__PURE__ */ jsx6(
|
|
5727
|
+
"button",
|
|
5728
|
+
{
|
|
5729
|
+
type: "button",
|
|
5730
|
+
onClick: () => onChange(value),
|
|
5731
|
+
className: cn(
|
|
5732
|
+
"min-h-7 rounded-og-xs px-1.5 py-0.5 text-og-xs capitalize focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-w-11 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
|
|
5733
|
+
layout === value ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
5677
5734
|
),
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
"flex min-h-0 min-w-0 flex-col",
|
|
5683
|
-
wide ? "flex-1" : "flex-[1.4] border-t border-og-border"
|
|
5684
|
-
),
|
|
5685
|
-
children: [
|
|
5686
|
-
/* @__PURE__ */ jsxs7("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: [
|
|
5687
|
-
/* @__PURE__ */ jsx9(
|
|
5688
|
-
"span",
|
|
5689
|
-
{
|
|
5690
|
-
"data-opengeni-selected-file": true,
|
|
5691
|
-
className: "min-w-0 truncate font-og-mono text-og-xs text-og-fg-muted",
|
|
5692
|
-
children: selected ?? "No file selected"
|
|
5693
|
-
}
|
|
5694
|
-
),
|
|
5695
|
-
canEdit && /* @__PURE__ */ jsx9(
|
|
5696
|
-
Segmented,
|
|
5697
|
-
{
|
|
5698
|
-
options: [
|
|
5699
|
-
{ value: "view", label: "View" },
|
|
5700
|
-
{ value: "edit", label: "Edit" }
|
|
5701
|
-
],
|
|
5702
|
-
value: editMode ? "edit" : "view",
|
|
5703
|
-
onChange: (v) => setEditMode(v === "edit")
|
|
5704
|
-
}
|
|
5705
|
-
)
|
|
5706
|
-
] }),
|
|
5707
|
-
/* @__PURE__ */ jsx9("div", { className: "min-h-0 flex-1 overflow-auto", children: viewPath ? showEditor && fileView.content !== null ? /* @__PURE__ */ jsx9(
|
|
5708
|
-
CodeEditor,
|
|
5709
|
-
{
|
|
5710
|
-
path: viewPath,
|
|
5711
|
-
initialContents: fileView.content,
|
|
5712
|
-
themeType: resolvedTheme,
|
|
5713
|
-
onSave: (contents) => files.writeFile(viewPath, contents, { expectedContent: fileView.content }),
|
|
5714
|
-
onOverwrite: (contents) => files.writeFile(viewPath, contents, { force: true }),
|
|
5715
|
-
onReload: () => setViewReloadRevision((revision) => revision + 1),
|
|
5716
|
-
...onEditIntent ? { onEditIntent } : {},
|
|
5717
|
-
className: "h-full"
|
|
5718
|
-
},
|
|
5719
|
-
viewPath
|
|
5720
|
-
) : waitingForSelectedFile ? /* @__PURE__ */ jsxs7(
|
|
5721
|
-
Notice,
|
|
5722
|
-
{
|
|
5723
|
-
icon: /* @__PURE__ */ jsx9(
|
|
5724
|
-
LoaderCircleIcon,
|
|
5725
|
-
{
|
|
5726
|
-
className: "size-5 animate-spin motion-reduce:animate-none",
|
|
5727
|
-
"aria-hidden": true
|
|
5728
|
-
}
|
|
5729
|
-
),
|
|
5730
|
-
title: "Waking workspace",
|
|
5731
|
-
announce: "status",
|
|
5732
|
-
children: [
|
|
5733
|
-
"Opening ",
|
|
5734
|
-
viewPath,
|
|
5735
|
-
" when the live file system is ready\u2026"
|
|
5736
|
-
]
|
|
5737
|
-
}
|
|
5738
|
-
) : captureFileUnavailable ? /* @__PURE__ */ jsxs7(Notice, { icon: /* @__PURE__ */ jsx9(FileCode2Icon, { className: "size-5", "aria-hidden": true }), title: "On machine", children: [
|
|
5739
|
-
/* @__PURE__ */ jsx9("p", { children: captureFileUnavailable.reason === "too-large" ? "This file is larger than the captured preview limit." : captureFileUnavailable.reason === "content-missing" ? "The captured copy is no longer available." : "This file was indexed, but it was not changed in the captured turn." }),
|
|
5740
|
-
onWakeWorkspace ? /* @__PURE__ */ jsx9(
|
|
5741
|
-
WakeButton,
|
|
5742
|
-
{
|
|
5743
|
-
onClick: () => {
|
|
5744
|
-
setLiveRequestedPath(viewPath);
|
|
5745
|
-
if (liveWorkspaceReady) void files.refresh();
|
|
5746
|
-
else onWakeWorkspace();
|
|
5747
|
-
},
|
|
5748
|
-
children: liveWorkspaceReady ? "Retry live file" : "Open live file"
|
|
5749
|
-
}
|
|
5750
|
-
) : null
|
|
5751
|
-
] }) : fileView.error ? /* @__PURE__ */ jsxs7(Notice, { announce: "alert", children: [
|
|
5752
|
-
"Could not open ",
|
|
5753
|
-
viewPath,
|
|
5754
|
-
": ",
|
|
5755
|
-
fileView.error.message
|
|
5756
|
-
] }) : fileView.loading ? /* @__PURE__ */ jsxs7(Notice, { announce: "status", children: [
|
|
5757
|
-
"Loading ",
|
|
5758
|
-
viewPath,
|
|
5759
|
-
"\u2026"
|
|
5760
|
-
] }) : fileView.isBinary ? /* @__PURE__ */ jsxs7(Notice, { children: [
|
|
5761
|
-
viewPath,
|
|
5762
|
-
" is a binary file (",
|
|
5763
|
-
fileView.sizeBytes ?? 0,
|
|
5764
|
-
" bytes)."
|
|
5765
|
-
] }) : fileView.content !== null ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
5766
|
-
fileView.truncated && /* @__PURE__ */ jsxs7("div", { className: "border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-xs text-og-status-running", children: [
|
|
5767
|
-
"Large file \u2014 showing a truncated preview (",
|
|
5768
|
-
fileView.sizeBytes ?? 0,
|
|
5769
|
-
" bytes loaded). Editing is disabled to avoid corrupting the file."
|
|
5770
|
-
] }),
|
|
5771
|
-
usePierre ? /* @__PURE__ */ jsx9(
|
|
5772
|
-
PierreFile,
|
|
5773
|
-
{
|
|
5774
|
-
path: viewPath,
|
|
5775
|
-
contents: fileView.content,
|
|
5776
|
-
themeType: resolvedTheme,
|
|
5777
|
-
fallback: /* @__PURE__ */ jsx9("pre", { className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg", children: fileView.content }),
|
|
5778
|
-
className: "p-1"
|
|
5779
|
-
}
|
|
5780
|
-
) : /* @__PURE__ */ jsx9("pre", { className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg", children: fileView.content })
|
|
5781
|
-
] }) : /* @__PURE__ */ jsxs7(Notice, { announce: "status", children: [
|
|
5782
|
-
"Loading ",
|
|
5783
|
-
viewPath,
|
|
5784
|
-
"\u2026"
|
|
5785
|
-
] }) : (
|
|
5786
|
-
// Nothing selected — the tree shows the whole workspace; pick a file.
|
|
5787
|
-
requestedPath && !requestedPathReady ? /* @__PURE__ */ jsxs7(
|
|
5788
|
-
Notice,
|
|
5789
|
-
{
|
|
5790
|
-
icon: /* @__PURE__ */ jsx9(
|
|
5791
|
-
LoaderCircleIcon,
|
|
5792
|
-
{
|
|
5793
|
-
className: "size-5 animate-spin motion-reduce:animate-none",
|
|
5794
|
-
"aria-hidden": true
|
|
5795
|
-
}
|
|
5796
|
-
),
|
|
5797
|
-
title: "Waking sandbox",
|
|
5798
|
-
announce: "status",
|
|
5799
|
-
children: [
|
|
5800
|
-
"Opening ",
|
|
5801
|
-
requestedPath,
|
|
5802
|
-
" when the live workspace is ready\u2026"
|
|
5803
|
-
]
|
|
5804
|
-
}
|
|
5805
|
-
) : /* @__PURE__ */ jsx9(Notice, { icon: /* @__PURE__ */ jsx9(FileCode2Icon, { className: "size-5", "aria-hidden": true }), title: "Choose a file", children: "Select a file in the tree to preview it." })
|
|
5806
|
-
) })
|
|
5807
|
-
]
|
|
5808
|
-
}
|
|
5809
|
-
)
|
|
5810
|
-
] })
|
|
5811
|
-
] });
|
|
5735
|
+
children: value
|
|
5736
|
+
},
|
|
5737
|
+
value
|
|
5738
|
+
)) });
|
|
5812
5739
|
}
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5740
|
+
|
|
5741
|
+
// src/components/diff-view.tsx
|
|
5742
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
5743
|
+
function DiffView({
|
|
5744
|
+
diff,
|
|
5745
|
+
fallback,
|
|
5746
|
+
layout = "unified",
|
|
5747
|
+
themeType,
|
|
5748
|
+
isRepo = true,
|
|
5749
|
+
emptyState,
|
|
5750
|
+
className
|
|
5751
|
+
}) {
|
|
5752
|
+
if (diff.length === 0) {
|
|
5753
|
+
return /* @__PURE__ */ jsx7("div", { className: cn("p-3 text-og-sm text-og-fg-subtle", className), children: emptyState ?? (isRepo ? "No changes" : "No repository mounted") });
|
|
5754
|
+
}
|
|
5755
|
+
return /* @__PURE__ */ jsx7(
|
|
5756
|
+
PierreDiff,
|
|
5816
5757
|
{
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5758
|
+
diff,
|
|
5759
|
+
layout,
|
|
5760
|
+
themeType,
|
|
5761
|
+
...fallback !== void 0 ? { fallback } : {},
|
|
5762
|
+
className
|
|
5821
5763
|
}
|
|
5822
5764
|
);
|
|
5823
5765
|
}
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
git.behind
|
|
5847
|
-
] })
|
|
5848
|
-
] }),
|
|
5849
|
-
dirty && /* @__PURE__ */ jsxs7(
|
|
5850
|
-
"span",
|
|
5851
|
-
{
|
|
5852
|
-
"aria-hidden": "true",
|
|
5853
|
-
"data-contrast-audited": true,
|
|
5854
|
-
className: "ml-auto shrink-0 text-og-xs text-og-fg-subtle",
|
|
5855
|
-
children: [
|
|
5856
|
-
dirtyCount,
|
|
5857
|
-
" changed"
|
|
5858
|
-
]
|
|
5859
|
-
}
|
|
5860
|
-
)
|
|
5861
|
-
] });
|
|
5862
|
-
}
|
|
5863
|
-
function Segmented({
|
|
5864
|
-
options,
|
|
5865
|
-
value,
|
|
5866
|
-
onChange
|
|
5766
|
+
|
|
5767
|
+
// src/components/pierre-file.tsx
|
|
5768
|
+
import {
|
|
5769
|
+
lazy,
|
|
5770
|
+
Suspense,
|
|
5771
|
+
useEffect as useEffect18,
|
|
5772
|
+
useState as useState15
|
|
5773
|
+
} from "react";
|
|
5774
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
5775
|
+
var LazyFile = lazy(async () => {
|
|
5776
|
+
const mod = await import("@pierre/diffs/react");
|
|
5777
|
+
return { default: mod.File };
|
|
5778
|
+
});
|
|
5779
|
+
function PierreFile({
|
|
5780
|
+
path,
|
|
5781
|
+
contents,
|
|
5782
|
+
themeType,
|
|
5783
|
+
theme,
|
|
5784
|
+
disableWorkerPool,
|
|
5785
|
+
loading,
|
|
5786
|
+
fallback,
|
|
5787
|
+
className
|
|
5867
5788
|
}) {
|
|
5868
|
-
|
|
5869
|
-
"button",
|
|
5870
|
-
{
|
|
5871
|
-
type: "button",
|
|
5872
|
-
onClick: () => onChange(opt.value),
|
|
5873
|
-
className: cn(
|
|
5874
|
-
"min-h-7 rounded-og-xs px-1.5 py-0.5 text-og-xs focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-h-11 max-[1023px]:min-w-11 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
|
|
5875
|
-
opt.value === value ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
5876
|
-
),
|
|
5877
|
-
children: opt.label
|
|
5878
|
-
},
|
|
5879
|
-
opt.value
|
|
5880
|
-
)) });
|
|
5881
|
-
}
|
|
5882
|
-
function useFileView(path, readFile, reloadRevision = 0) {
|
|
5883
|
-
const [state, setState] = useState15({
|
|
5884
|
-
content: null,
|
|
5885
|
-
isBinary: false,
|
|
5886
|
-
truncated: false,
|
|
5887
|
-
sizeBytes: null,
|
|
5888
|
-
loading: false,
|
|
5889
|
-
error: null
|
|
5890
|
-
});
|
|
5789
|
+
const [failed, setFailed] = useState15(false);
|
|
5891
5790
|
useEffect18(() => {
|
|
5892
|
-
if (!path) {
|
|
5893
|
-
setState({
|
|
5894
|
-
content: null,
|
|
5895
|
-
isBinary: false,
|
|
5896
|
-
truncated: false,
|
|
5897
|
-
sizeBytes: null,
|
|
5898
|
-
loading: false,
|
|
5899
|
-
error: null
|
|
5900
|
-
});
|
|
5901
|
-
return;
|
|
5902
|
-
}
|
|
5903
5791
|
let cancelled = false;
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
content: null,
|
|
5907
|
-
isBinary: false,
|
|
5908
|
-
truncated: false,
|
|
5909
|
-
sizeBytes: null,
|
|
5910
|
-
loading: true,
|
|
5911
|
-
error: null
|
|
5912
|
-
});
|
|
5913
|
-
void readFile(path, { signal: abort.signal }).then((res) => {
|
|
5914
|
-
if (cancelled) return;
|
|
5915
|
-
const content = res.isBinary ? null : res.encoding === "base64" ? decodeBase64Utf8(res.content) : res.content;
|
|
5916
|
-
setState({
|
|
5917
|
-
content,
|
|
5918
|
-
isBinary: res.isBinary,
|
|
5919
|
-
truncated: res.truncated,
|
|
5920
|
-
sizeBytes: res.sizeBytes,
|
|
5921
|
-
loading: false,
|
|
5922
|
-
error: null
|
|
5923
|
-
});
|
|
5924
|
-
}).catch((cause) => {
|
|
5925
|
-
if (cancelled) return;
|
|
5926
|
-
setState({
|
|
5927
|
-
content: null,
|
|
5928
|
-
isBinary: false,
|
|
5929
|
-
truncated: false,
|
|
5930
|
-
sizeBytes: null,
|
|
5931
|
-
loading: false,
|
|
5932
|
-
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
5933
|
-
});
|
|
5792
|
+
void import("@pierre/diffs/react").catch(() => {
|
|
5793
|
+
if (!cancelled) setFailed(true);
|
|
5934
5794
|
});
|
|
5935
5795
|
return () => {
|
|
5936
5796
|
cancelled = true;
|
|
5937
|
-
abort.abort();
|
|
5938
5797
|
};
|
|
5939
|
-
}, [
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
try {
|
|
5944
|
-
if (typeof atob === "function") {
|
|
5945
|
-
const binary = atob(b64);
|
|
5946
|
-
const bytes = new Uint8Array(binary.length);
|
|
5947
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
5948
|
-
return new TextDecoder().decode(bytes);
|
|
5949
|
-
}
|
|
5950
|
-
} catch {
|
|
5798
|
+
}, []);
|
|
5799
|
+
const name = path.split("/").filter(Boolean).pop() ?? path;
|
|
5800
|
+
if (failed) {
|
|
5801
|
+
return /* @__PURE__ */ jsx8("div", { className, children: fallback ?? /* @__PURE__ */ jsx8(PlainFile, { name, contents }) });
|
|
5951
5802
|
}
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
}
|
|
5961
|
-
|
|
5962
|
-
"
|
|
5803
|
+
const options = {
|
|
5804
|
+
overflow: "scroll",
|
|
5805
|
+
stickyHeader: true,
|
|
5806
|
+
showLineNumbers: true,
|
|
5807
|
+
...theme ? { theme } : {
|
|
5808
|
+
theme: {
|
|
5809
|
+
dark: "github-dark-high-contrast",
|
|
5810
|
+
light: "github-light-high-contrast"
|
|
5811
|
+
}
|
|
5812
|
+
},
|
|
5813
|
+
themeType: themeType ?? "dark"
|
|
5814
|
+
};
|
|
5815
|
+
const pierreVars = {
|
|
5816
|
+
"--diffs-dark-bg": "var(--og-color-bg)",
|
|
5817
|
+
"--diffs-light-bg": "var(--og-color-bg)",
|
|
5818
|
+
"--diffs-bg-buffer-override": "var(--og-color-surface-1)",
|
|
5819
|
+
"--diffs-bg-separator-override": "var(--og-color-surface-1)",
|
|
5820
|
+
"--diffs-font-size": "var(--og-code-font-size)",
|
|
5821
|
+
"--diffs-line-height": "var(--og-code-line-height)"
|
|
5822
|
+
};
|
|
5823
|
+
return /* @__PURE__ */ jsx8("div", { className: cn("min-w-0", className), "data-opengeni-pierre-file": true, style: pierreVars, children: /* @__PURE__ */ jsx8(Suspense, { fallback: loading ?? /* @__PURE__ */ jsx8(FileSkeleton, {}), children: /* @__PURE__ */ jsx8(
|
|
5824
|
+
LazyFile,
|
|
5963
5825
|
{
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5826
|
+
file: { name, contents },
|
|
5827
|
+
options,
|
|
5828
|
+
...disableWorkerPool !== void 0 ? { disableWorkerPool } : {}
|
|
5829
|
+
}
|
|
5830
|
+
) }) });
|
|
5831
|
+
}
|
|
5832
|
+
function PlainFile({ name, contents }) {
|
|
5833
|
+
return /* @__PURE__ */ jsx8(
|
|
5834
|
+
"pre",
|
|
5835
|
+
{
|
|
5836
|
+
className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg",
|
|
5837
|
+
"data-file": name,
|
|
5838
|
+
children: contents
|
|
5976
5839
|
}
|
|
5977
5840
|
);
|
|
5978
5841
|
}
|
|
5842
|
+
function FileSkeleton() {
|
|
5843
|
+
return /* @__PURE__ */ jsx8("div", { className: "p-3 text-og-sm text-og-fg-subtle", children: "Loading file\u2026" });
|
|
5844
|
+
}
|
|
5979
5845
|
|
|
5980
|
-
// src/components/
|
|
5981
|
-
import {
|
|
5982
|
-
import {
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5846
|
+
// src/components/code-editor.tsx
|
|
5847
|
+
import { Loader2Icon, SaveIcon } from "lucide-react";
|
|
5848
|
+
import {
|
|
5849
|
+
useCallback as useCallback19,
|
|
5850
|
+
useEffect as useEffect19,
|
|
5851
|
+
useMemo as useMemo10,
|
|
5852
|
+
useRef as useRef16,
|
|
5853
|
+
useState as useState16
|
|
5854
|
+
} from "react";
|
|
5855
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
5856
|
+
var LANGUAGE_LOADERS = {
|
|
5857
|
+
javascript: async () => (await import("@codemirror/lang-javascript")).javascript({ jsx: true, typescript: true }),
|
|
5858
|
+
json: async () => (await import("@codemirror/lang-json")).json(),
|
|
5859
|
+
python: async () => (await import("@codemirror/lang-python")).python(),
|
|
5860
|
+
markdown: async () => (await import("@codemirror/lang-markdown")).markdown(),
|
|
5861
|
+
css: async () => (await import("@codemirror/lang-css")).css(),
|
|
5862
|
+
html: async () => (await import("@codemirror/lang-html")).html()
|
|
5863
|
+
};
|
|
5864
|
+
function languageForPath(path) {
|
|
5865
|
+
const name = path.split("/").pop() ?? path;
|
|
5866
|
+
const ext = name.includes(".") ? (name.split(".").pop() ?? "").toLowerCase() : "";
|
|
5867
|
+
switch (ext) {
|
|
5868
|
+
case "js":
|
|
5869
|
+
case "jsx":
|
|
5870
|
+
case "ts":
|
|
5871
|
+
case "tsx":
|
|
5872
|
+
case "mjs":
|
|
5873
|
+
case "cjs":
|
|
5874
|
+
return "javascript";
|
|
5875
|
+
case "json":
|
|
5876
|
+
case "jsonc":
|
|
5877
|
+
return "json";
|
|
5878
|
+
case "py":
|
|
5879
|
+
case "pyi":
|
|
5880
|
+
return "python";
|
|
5881
|
+
case "md":
|
|
5882
|
+
case "markdown":
|
|
5883
|
+
case "mdx":
|
|
5884
|
+
return "markdown";
|
|
5885
|
+
case "css":
|
|
5886
|
+
case "scss":
|
|
5887
|
+
case "less":
|
|
5888
|
+
return "css";
|
|
5889
|
+
case "html":
|
|
5890
|
+
case "htm":
|
|
5891
|
+
case "xml":
|
|
5892
|
+
case "svg":
|
|
5893
|
+
case "vue":
|
|
5894
|
+
return "html";
|
|
5993
5895
|
default:
|
|
5994
|
-
return
|
|
5896
|
+
return null;
|
|
5995
5897
|
}
|
|
5996
5898
|
}
|
|
5997
|
-
function
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
renderUnavailable,
|
|
6009
|
-
renderWarming,
|
|
6010
|
-
renderViewerCap,
|
|
6011
|
-
viewerCapReached,
|
|
6012
|
-
connectTimeoutMs = 13e3,
|
|
5899
|
+
function CodeEditor({
|
|
5900
|
+
path,
|
|
5901
|
+
initialContents,
|
|
5902
|
+
onSave,
|
|
5903
|
+
onOverwrite,
|
|
5904
|
+
onReload,
|
|
5905
|
+
onEditIntent,
|
|
5906
|
+
readOnly = false,
|
|
5907
|
+
themeType = "dark",
|
|
5908
|
+
loading,
|
|
5909
|
+
fallback,
|
|
6013
5910
|
className
|
|
6014
5911
|
}) {
|
|
6015
|
-
const
|
|
6016
|
-
const [
|
|
6017
|
-
const [
|
|
6018
|
-
const
|
|
6019
|
-
const
|
|
6020
|
-
const
|
|
6021
|
-
const
|
|
6022
|
-
const
|
|
6023
|
-
const
|
|
6024
|
-
const
|
|
6025
|
-
const
|
|
6026
|
-
const noLiveAddress = Boolean(capability) && !transportNull && !capability.url;
|
|
6027
|
-
const coldWarmable = transportNull && reason === "lease_cold" || !transportNull && noLiveAddress;
|
|
6028
|
-
const hardUnavailable = transportNull && isHardUnavailable(reason);
|
|
6029
|
-
const accept = () => {
|
|
6030
|
-
setConsented(true);
|
|
6031
|
-
onAcknowledge?.();
|
|
6032
|
-
};
|
|
5912
|
+
const [failed, setFailed] = useState16(false);
|
|
5913
|
+
const [bundle, setBundle] = useState16(null);
|
|
5914
|
+
const [value, setValue] = useState16(initialContents);
|
|
5915
|
+
const [baseline, setBaseline] = useState16(initialContents);
|
|
5916
|
+
const [saving, setSaving] = useState16(false);
|
|
5917
|
+
const [saveError, setSaveError] = useState16(null);
|
|
5918
|
+
const [savedTick, setSavedTick] = useState16(false);
|
|
5919
|
+
const dirty = value !== baseline;
|
|
5920
|
+
const saveConflict = saveError !== null && saveError.code === "file_write_conflict";
|
|
5921
|
+
const editIntentFiredRef = useRef16(false);
|
|
5922
|
+
const lastSeed = useRef16({ path, contents: initialContents });
|
|
6033
5923
|
useEffect19(() => {
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
5924
|
+
const seedChanged = lastSeed.current.path !== path || lastSeed.current.contents !== initialContents;
|
|
5925
|
+
if (!seedChanged) return;
|
|
5926
|
+
lastSeed.current = { path, contents: initialContents };
|
|
5927
|
+
editIntentFiredRef.current = false;
|
|
5928
|
+
setValue(initialContents);
|
|
5929
|
+
setBaseline(initialContents);
|
|
5930
|
+
setSaveError(null);
|
|
5931
|
+
setSavedTick(false);
|
|
5932
|
+
}, [path, initialContents]);
|
|
5933
|
+
const noteEdit = useCallback19(
|
|
5934
|
+
(next) => {
|
|
5935
|
+
setValue(next);
|
|
5936
|
+
setSavedTick(false);
|
|
5937
|
+
if (!editIntentFiredRef.current && next !== baseline) {
|
|
5938
|
+
editIntentFiredRef.current = true;
|
|
5939
|
+
onEditIntent?.();
|
|
6039
5940
|
}
|
|
6040
|
-
}
|
|
6041
|
-
|
|
5941
|
+
},
|
|
5942
|
+
[baseline, onEditIntent]
|
|
5943
|
+
);
|
|
5944
|
+
const langKey = useMemo10(() => languageForPath(path), [path]);
|
|
5945
|
+
useEffect19(() => {
|
|
5946
|
+
let cancelled = false;
|
|
5947
|
+
void (async () => {
|
|
5948
|
+
try {
|
|
5949
|
+
const cmMod = await import("@uiw/react-codemirror");
|
|
5950
|
+
let languageExtension = null;
|
|
5951
|
+
if (langKey) {
|
|
5952
|
+
try {
|
|
5953
|
+
languageExtension = await LANGUAGE_LOADERS[langKey]?.() ?? null;
|
|
5954
|
+
} catch {
|
|
5955
|
+
languageExtension = null;
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5958
|
+
if (cancelled) return;
|
|
5959
|
+
const saveKeymapExtension = (run) => cmMod.Prec.highest(
|
|
5960
|
+
cmMod.keymap.of([
|
|
5961
|
+
{
|
|
5962
|
+
key: "Mod-s",
|
|
5963
|
+
preventDefault: true,
|
|
5964
|
+
run: () => {
|
|
5965
|
+
run();
|
|
5966
|
+
return true;
|
|
5967
|
+
}
|
|
5968
|
+
}
|
|
5969
|
+
])
|
|
5970
|
+
);
|
|
5971
|
+
setBundle({
|
|
5972
|
+
Editor: cmMod.default,
|
|
5973
|
+
saveKeymapExtension,
|
|
5974
|
+
languageExtension
|
|
5975
|
+
});
|
|
5976
|
+
setFailed(false);
|
|
5977
|
+
} catch {
|
|
5978
|
+
if (!cancelled) setFailed(true);
|
|
5979
|
+
}
|
|
5980
|
+
})();
|
|
6042
5981
|
return () => {
|
|
6043
|
-
|
|
5982
|
+
cancelled = true;
|
|
6044
5983
|
};
|
|
6045
|
-
}, [
|
|
6046
|
-
const
|
|
6047
|
-
const stream = useDesktopStream({
|
|
6048
|
-
capability: connectCapability,
|
|
6049
|
-
containerRef,
|
|
6050
|
-
interactive: inControl,
|
|
6051
|
-
...scaleViewport !== void 0 ? { scaleViewport } : {},
|
|
6052
|
-
...rfbFactory ? { rfbFactory } : {},
|
|
6053
|
-
...webSocketFactory ? { webSocketFactory } : {}
|
|
5984
|
+
}, [langKey]);
|
|
5985
|
+
const saveRef = useRef16(() => {
|
|
6054
5986
|
});
|
|
6055
|
-
const
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
5987
|
+
const save = useCallback19(async () => {
|
|
5988
|
+
if (readOnly) return;
|
|
5989
|
+
const snapshot = value;
|
|
5990
|
+
if (snapshot === baseline) return;
|
|
5991
|
+
setSaving(true);
|
|
5992
|
+
setSaveError(null);
|
|
5993
|
+
setSavedTick(false);
|
|
5994
|
+
try {
|
|
5995
|
+
await onSave(snapshot);
|
|
5996
|
+
setBaseline(snapshot);
|
|
5997
|
+
lastSeed.current = { path, contents: snapshot };
|
|
5998
|
+
setSavedTick(true);
|
|
5999
|
+
} catch (cause) {
|
|
6000
|
+
setSaveError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
6001
|
+
} finally {
|
|
6002
|
+
setSaving(false);
|
|
6064
6003
|
}
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6004
|
+
}, [readOnly, value, baseline, onSave, path]);
|
|
6005
|
+
const overwrite = useCallback19(async () => {
|
|
6006
|
+
if (readOnly || !onOverwrite) return;
|
|
6007
|
+
const snapshot = value;
|
|
6008
|
+
if (snapshot === baseline) return;
|
|
6009
|
+
setSaving(true);
|
|
6010
|
+
setSaveError(null);
|
|
6011
|
+
setSavedTick(false);
|
|
6012
|
+
try {
|
|
6013
|
+
await onOverwrite(snapshot);
|
|
6014
|
+
setBaseline(snapshot);
|
|
6015
|
+
lastSeed.current = { path, contents: snapshot };
|
|
6016
|
+
setSavedTick(true);
|
|
6017
|
+
} catch (cause) {
|
|
6018
|
+
setSaveError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
6019
|
+
} finally {
|
|
6020
|
+
setSaving(false);
|
|
6021
|
+
}
|
|
6022
|
+
}, [readOnly, onOverwrite, value, baseline, path]);
|
|
6023
|
+
saveRef.current = () => {
|
|
6024
|
+
void save();
|
|
6025
|
+
};
|
|
6083
6026
|
useEffect19(() => {
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
setConnectTimedOut(false);
|
|
6098
|
-
setReconnectNonce((n) => n + 1);
|
|
6099
|
-
stream.reconnect();
|
|
6100
|
-
};
|
|
6101
|
-
let uiState;
|
|
6102
|
-
if (viewerCapReached) uiState = "viewer_cap";
|
|
6103
|
-
else if (hardUnavailable) uiState = "unavailable";
|
|
6104
|
-
else if (needsAck && !isWatching) uiState = "consent";
|
|
6105
|
-
else if (coldWarmable) uiState = "warming";
|
|
6106
|
-
else if (connected) uiState = "connected";
|
|
6107
|
-
else if (stream.error) uiState = "error";
|
|
6108
|
-
else if (connectTimedOut) uiState = "connect_failed";
|
|
6109
|
-
else uiState = "connecting";
|
|
6110
|
-
const overlayShown = uiState !== "connected" && uiState !== "connecting";
|
|
6111
|
-
const showToggle = showControlToggle && !overlayShown;
|
|
6112
|
-
let overlay = null;
|
|
6113
|
-
switch (uiState) {
|
|
6114
|
-
case "viewer_cap":
|
|
6115
|
-
overlay = renderViewerCap?.() ?? defaultNotice(
|
|
6116
|
-
"Too many viewers",
|
|
6117
|
-
"This session has reached its live-viewer limit. Try again shortly."
|
|
6118
|
-
);
|
|
6119
|
-
break;
|
|
6120
|
-
case "unavailable":
|
|
6121
|
-
overlay = renderUnavailable?.(reason) ?? defaultNotice("Desktop unavailable", unavailableCopy(reason));
|
|
6122
|
-
break;
|
|
6123
|
-
case "consent":
|
|
6124
|
-
overlay = renderConsentGate ? renderConsentGate(accept, capability?.shared ?? false) : /* @__PURE__ */ jsx10(DefaultConsentGate, { shared: capability?.shared ?? false, onAccept: accept });
|
|
6125
|
-
break;
|
|
6126
|
-
case "warming":
|
|
6127
|
-
overlay = renderWarming?.() ?? /* @__PURE__ */ jsx10(WarmingNotice, {});
|
|
6128
|
-
break;
|
|
6129
|
-
case "connect_failed":
|
|
6130
|
-
overlay = defaultNotice(
|
|
6131
|
-
"Couldn\u2019t connect",
|
|
6132
|
-
"The desktop is warm but the live stream didn\u2019t come up. This usually clears on a retry.",
|
|
6133
|
-
reconnect
|
|
6134
|
-
);
|
|
6135
|
-
break;
|
|
6136
|
-
case "error":
|
|
6137
|
-
overlay = defaultNotice(
|
|
6138
|
-
"Desktop disconnected",
|
|
6139
|
-
stream.error?.message ?? "The stream dropped.",
|
|
6140
|
-
reconnect
|
|
6141
|
-
);
|
|
6142
|
-
break;
|
|
6143
|
-
case "connecting":
|
|
6144
|
-
case "connected":
|
|
6145
|
-
overlay = null;
|
|
6146
|
-
break;
|
|
6147
|
-
}
|
|
6148
|
-
return /* @__PURE__ */ jsxs8(
|
|
6027
|
+
if (!savedTick) return;
|
|
6028
|
+
const t = setTimeout(() => setSavedTick(false), 1800);
|
|
6029
|
+
return () => clearTimeout(t);
|
|
6030
|
+
}, [savedTick]);
|
|
6031
|
+
const fileName = path.split("/").filter(Boolean).pop() ?? path;
|
|
6032
|
+
const cmExtensions = useMemo10(() => {
|
|
6033
|
+
if (!bundle) return [];
|
|
6034
|
+
const exts = [bundle.saveKeymapExtension(() => saveRef.current())];
|
|
6035
|
+
if (bundle.languageExtension) exts.push(bundle.languageExtension);
|
|
6036
|
+
return exts;
|
|
6037
|
+
}, [bundle]);
|
|
6038
|
+
const Editor = bundle?.Editor;
|
|
6039
|
+
return /* @__PURE__ */ jsxs7(
|
|
6149
6040
|
"div",
|
|
6150
6041
|
{
|
|
6151
|
-
className: cn(
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
className
|
|
6155
|
-
),
|
|
6156
|
-
style: { backgroundColor: DESKTOP_MEDIA_BACKGROUND },
|
|
6157
|
-
"data-opengeni-desktop": true,
|
|
6158
|
-
"data-state": stream.state,
|
|
6159
|
-
"data-ui-state": uiState,
|
|
6160
|
-
"data-in-control": inControl ? "true" : void 0,
|
|
6042
|
+
className: cn("flex h-full min-h-0 flex-col", className),
|
|
6043
|
+
"data-opengeni-code-editor": true,
|
|
6044
|
+
style: editorVars,
|
|
6161
6045
|
children: [
|
|
6162
|
-
/* @__PURE__ */
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6046
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex min-h-9 shrink-0 items-center gap-2 border-b border-og-border bg-og-surface-1 px-2 py-1", children: [
|
|
6047
|
+
/* @__PURE__ */ jsx9(
|
|
6048
|
+
"span",
|
|
6049
|
+
{
|
|
6050
|
+
className: cn(
|
|
6051
|
+
"size-1.5 shrink-0 rounded-full transition-colors",
|
|
6052
|
+
readOnly ? "bg-transparent" : dirty ? "bg-og-status-running" : "bg-og-status-idle"
|
|
6053
|
+
),
|
|
6054
|
+
title: readOnly ? "read-only" : dirty ? "unsaved changes" : "saved"
|
|
6055
|
+
}
|
|
6056
|
+
),
|
|
6057
|
+
/* @__PURE__ */ jsxs7("span", { className: "truncate font-og-mono text-og-xs text-og-fg-muted", children: [
|
|
6058
|
+
fileName,
|
|
6059
|
+
dirty && !readOnly ? " \u2022" : ""
|
|
6060
|
+
] }),
|
|
6061
|
+
/* @__PURE__ */ jsxs7("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
|
|
6062
|
+
saveError && !saveConflict && /* @__PURE__ */ jsx9(
|
|
6063
|
+
"span",
|
|
6176
6064
|
{
|
|
6177
|
-
className: "
|
|
6178
|
-
|
|
6065
|
+
className: "max-w-[220px] truncate text-og-xs text-og-status-failed",
|
|
6066
|
+
title: saveError.message,
|
|
6067
|
+
children: saveError.message
|
|
6179
6068
|
}
|
|
6180
|
-
)
|
|
6181
|
-
|
|
6182
|
-
|
|
6069
|
+
),
|
|
6070
|
+
!saveError && savedTick && /* @__PURE__ */ jsx9("span", { className: "text-og-xs text-og-status-idle", children: "Saved" }),
|
|
6071
|
+
readOnly ? /* @__PURE__ */ jsx9("span", { className: "text-og-xs uppercase tracking-wide text-og-fg-subtle", children: "Read-only" }) : !saveConflict ? /* @__PURE__ */ jsxs7(
|
|
6072
|
+
"button",
|
|
6073
|
+
{
|
|
6074
|
+
type: "button",
|
|
6075
|
+
onClick: () => void save(),
|
|
6076
|
+
disabled: saving || !dirty,
|
|
6077
|
+
className: cn(
|
|
6078
|
+
"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-11",
|
|
6079
|
+
saving || !dirty ? "cursor-default text-og-fg-subtle opacity-60" : "text-og-fg hover:bg-og-accent-soft"
|
|
6080
|
+
),
|
|
6081
|
+
title: "Save (\u2318/Ctrl+S)",
|
|
6082
|
+
children: [
|
|
6083
|
+
saving ? /* @__PURE__ */ jsx9(Loader2Icon, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx9(SaveIcon, { className: "size-3" }),
|
|
6084
|
+
"Save"
|
|
6085
|
+
]
|
|
6086
|
+
}
|
|
6087
|
+
) : null
|
|
6088
|
+
] })
|
|
6183
6089
|
] }),
|
|
6184
|
-
|
|
6185
|
-
|
|
6090
|
+
saveConflict ? /* @__PURE__ */ jsxs7(
|
|
6091
|
+
"div",
|
|
6186
6092
|
{
|
|
6187
|
-
|
|
6188
|
-
|
|
6093
|
+
className: "flex shrink-0 flex-wrap items-center gap-x-3 gap-y-2 border-b border-og-status-failed/25 bg-og-status-failed/8 px-2 py-2",
|
|
6094
|
+
role: "alert",
|
|
6095
|
+
children: [
|
|
6096
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-[12rem] flex-1 text-og-xs text-og-fg-muted", children: [
|
|
6097
|
+
/* @__PURE__ */ jsx9("span", { className: "font-medium text-og-status-failed", children: "File changed on machine." }),
|
|
6098
|
+
" ",
|
|
6099
|
+
"Reloading discards your edits; overwriting replaces the live version."
|
|
6100
|
+
] }),
|
|
6101
|
+
/* @__PURE__ */ jsxs7("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
6102
|
+
onReload ? /* @__PURE__ */ jsx9(
|
|
6103
|
+
"button",
|
|
6104
|
+
{
|
|
6105
|
+
type: "button",
|
|
6106
|
+
onClick: () => {
|
|
6107
|
+
setSaveError(null);
|
|
6108
|
+
onReload();
|
|
6109
|
+
},
|
|
6110
|
+
className: "min-h-8 rounded-og-sm border border-og-border bg-og-surface-1 px-2 text-og-xs font-medium text-og-fg hover:bg-og-surface-2 pointer-coarse:min-h-11",
|
|
6111
|
+
children: "Reload live"
|
|
6112
|
+
}
|
|
6113
|
+
) : null,
|
|
6114
|
+
onOverwrite ? /* @__PURE__ */ jsx9(
|
|
6115
|
+
"button",
|
|
6116
|
+
{
|
|
6117
|
+
type: "button",
|
|
6118
|
+
onClick: () => void overwrite(),
|
|
6119
|
+
disabled: saving,
|
|
6120
|
+
className: "min-h-8 rounded-og-sm border border-og-status-failed/40 px-2 text-og-xs font-medium text-og-status-failed hover:bg-og-status-failed/10 disabled:opacity-50 pointer-coarse:min-h-11",
|
|
6121
|
+
children: "Overwrite"
|
|
6122
|
+
}
|
|
6123
|
+
) : null
|
|
6124
|
+
] })
|
|
6125
|
+
]
|
|
6189
6126
|
}
|
|
6190
|
-
),
|
|
6191
|
-
|
|
6192
|
-
|
|
6127
|
+
) : null,
|
|
6128
|
+
/* @__PURE__ */ jsx9("div", { className: "min-h-0 flex-1 overflow-auto", children: failed ? fallback ?? /* @__PURE__ */ jsx9(
|
|
6129
|
+
PlainTextarea,
|
|
6193
6130
|
{
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6131
|
+
value,
|
|
6132
|
+
readOnly,
|
|
6133
|
+
onChange: noteEdit,
|
|
6134
|
+
onSave: () => void save()
|
|
6197
6135
|
}
|
|
6198
|
-
)
|
|
6199
|
-
|
|
6136
|
+
) : Editor ? /* @__PURE__ */ jsx9(
|
|
6137
|
+
Editor,
|
|
6138
|
+
{
|
|
6139
|
+
value,
|
|
6140
|
+
theme: themeType === "light" ? "light" : "dark",
|
|
6141
|
+
editable: !readOnly,
|
|
6142
|
+
readOnly,
|
|
6143
|
+
basicSetup: true,
|
|
6144
|
+
extensions: cmExtensions,
|
|
6145
|
+
height: "100%",
|
|
6146
|
+
className: "og-cm-editor min-h-full text-og-sm",
|
|
6147
|
+
onChange: readOnly ? void 0 : noteEdit
|
|
6148
|
+
}
|
|
6149
|
+
) : loading ?? /* @__PURE__ */ jsx9(EditorSkeleton, {}) })
|
|
6200
6150
|
]
|
|
6201
6151
|
}
|
|
6202
6152
|
);
|
|
6203
6153
|
}
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6154
|
+
var editorVars = {
|
|
6155
|
+
"--og-cm-bg": "var(--og-color-bg)",
|
|
6156
|
+
fontFamily: "var(--og-font-mono)"
|
|
6157
|
+
};
|
|
6158
|
+
function PlainTextarea({
|
|
6159
|
+
value,
|
|
6160
|
+
readOnly,
|
|
6161
|
+
onChange,
|
|
6162
|
+
onSave
|
|
6208
6163
|
}) {
|
|
6209
|
-
return (
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
"outline-none transition-all duration-150 ease-out",
|
|
6226
|
-
"focus-visible:ring-2 focus-visible:ring-og-accent focus-visible:ring-offset-2 focus-visible:ring-offset-og-bg",
|
|
6227
|
-
disabled ? "cursor-not-allowed opacity-60" : cn(
|
|
6228
|
-
"cursor-pointer opacity-90 hover:-translate-y-0.5 hover:opacity-100",
|
|
6229
|
-
"hover:border-og-accent",
|
|
6230
|
-
"hover:bg-og-accent/10"
|
|
6231
|
-
)
|
|
6232
|
-
),
|
|
6233
|
-
children: [
|
|
6234
|
-
/* @__PURE__ */ jsx10(
|
|
6235
|
-
"span",
|
|
6236
|
-
{
|
|
6237
|
-
className: cn(
|
|
6238
|
-
"flex size-9 shrink-0 items-center justify-center rounded-full transition-colors",
|
|
6239
|
-
"bg-og-accent",
|
|
6240
|
-
"text-og-accent-fg",
|
|
6241
|
-
disabled ? "" : "group-hover:scale-105"
|
|
6242
|
-
),
|
|
6243
|
-
children: /* @__PURE__ */ jsx10(MousePointerClickIcon, { className: "size-5", strokeWidth: 2 })
|
|
6244
|
-
}
|
|
6245
|
-
),
|
|
6246
|
-
/* @__PURE__ */ jsxs8("span", { className: "flex flex-col items-start leading-tight", children: [
|
|
6247
|
-
/* @__PURE__ */ jsx10("span", { className: "text-og-base font-semibold text-og-fg", children: "Take control" }),
|
|
6248
|
-
/* @__PURE__ */ jsx10("span", { className: "text-og-xs text-og-fg-subtle", children: disabled && disabledReason ? disabledReason : "Drive the mouse & keyboard" })
|
|
6249
|
-
] })
|
|
6250
|
-
]
|
|
6251
|
-
}
|
|
6252
|
-
) })
|
|
6164
|
+
return /* @__PURE__ */ jsx9(
|
|
6165
|
+
"textarea",
|
|
6166
|
+
{
|
|
6167
|
+
value,
|
|
6168
|
+
readOnly,
|
|
6169
|
+
spellCheck: false,
|
|
6170
|
+
onChange: (e) => onChange(e.target.value),
|
|
6171
|
+
onKeyDown: (event) => {
|
|
6172
|
+
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "s") {
|
|
6173
|
+
event.preventDefault();
|
|
6174
|
+
onSave();
|
|
6175
|
+
}
|
|
6176
|
+
},
|
|
6177
|
+
"aria-label": "Plain text file editor",
|
|
6178
|
+
className: "h-full w-full resize-none bg-transparent p-2 font-og-mono text-og-sm text-og-fg outline-none"
|
|
6179
|
+
}
|
|
6253
6180
|
);
|
|
6254
6181
|
}
|
|
6255
|
-
function
|
|
6256
|
-
return /* @__PURE__ */
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6182
|
+
function EditorSkeleton() {
|
|
6183
|
+
return /* @__PURE__ */ jsx9("div", { className: "p-3 text-og-sm text-og-fg-subtle", children: "Loading editor\u2026" });
|
|
6184
|
+
}
|
|
6185
|
+
|
|
6186
|
+
// src/components/sandbox-files.tsx
|
|
6187
|
+
import { FileCode2Icon, FileWarningIcon as FileWarningIcon2, LoaderCircleIcon } from "lucide-react";
|
|
6188
|
+
import { useCallback as useCallback20, useEffect as useEffect20, useRef as useRef17, useState as useState17 } from "react";
|
|
6189
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
6190
|
+
function SandboxFiles({
|
|
6191
|
+
files,
|
|
6192
|
+
git,
|
|
6193
|
+
fileSystemAvailable = true,
|
|
6194
|
+
usePierre = true,
|
|
6195
|
+
editable = true,
|
|
6196
|
+
onEditIntent,
|
|
6197
|
+
requestedPath,
|
|
6198
|
+
requestedPathRequestId,
|
|
6199
|
+
requestedPathReady = true,
|
|
6200
|
+
workspaceResting = false,
|
|
6201
|
+
workspaceWaking = false,
|
|
6202
|
+
liveWorkspaceReady = true,
|
|
6203
|
+
onWakeWorkspace,
|
|
6204
|
+
themeType,
|
|
6205
|
+
className
|
|
6206
|
+
}) {
|
|
6207
|
+
const [selected, setSelected] = useState17(null);
|
|
6208
|
+
const [editMode, setEditMode] = useState17(false);
|
|
6209
|
+
const [liveRequestedPath, setLiveRequestedPath] = useState17(null);
|
|
6210
|
+
const [viewReloadRevision, setViewReloadRevision] = useState17(0);
|
|
6211
|
+
const pendingRequestRef = useRef17(null);
|
|
6212
|
+
const handledRequestRef = useRef17(null);
|
|
6213
|
+
const requestKey = requestedPath ? requestedPathRequestId ?? requestedPath : null;
|
|
6214
|
+
useEffect20(() => {
|
|
6215
|
+
if (!requestedPath || requestKey === null) {
|
|
6216
|
+
pendingRequestRef.current = null;
|
|
6217
|
+
handledRequestRef.current = null;
|
|
6218
|
+
return;
|
|
6219
|
+
}
|
|
6220
|
+
if (handledRequestRef.current === requestKey) {
|
|
6221
|
+
return;
|
|
6222
|
+
}
|
|
6223
|
+
if (!requestedPathReady) {
|
|
6224
|
+
pendingRequestRef.current = requestKey;
|
|
6225
|
+
return;
|
|
6226
|
+
}
|
|
6227
|
+
handledRequestRef.current = requestKey;
|
|
6228
|
+
pendingRequestRef.current = null;
|
|
6229
|
+
setSelected(requestedPath);
|
|
6230
|
+
setEditMode(false);
|
|
6231
|
+
}, [requestKey, requestedPath, requestedPathReady]);
|
|
6232
|
+
const rootRef = useRef17(null);
|
|
6233
|
+
const [wide, setWide] = useState17(false);
|
|
6234
|
+
useEffect20(() => {
|
|
6235
|
+
const el = rootRef.current;
|
|
6236
|
+
if (!el || typeof ResizeObserver === "undefined") return;
|
|
6237
|
+
const observer = new ResizeObserver((entries) => {
|
|
6238
|
+
const w = entries[0]?.contentRect.width ?? 0;
|
|
6239
|
+
setWide(w >= 720);
|
|
6240
|
+
});
|
|
6241
|
+
observer.observe(el);
|
|
6242
|
+
return () => observer.disconnect();
|
|
6243
|
+
}, []);
|
|
6244
|
+
const resolvedTheme = useThemeType(themeType);
|
|
6245
|
+
const viewPath = selected;
|
|
6246
|
+
const fileView = useFileView(viewPath, files.readFile, viewReloadRevision);
|
|
6247
|
+
const selectFile = useCallback20((path) => {
|
|
6248
|
+
if (pendingRequestRef.current !== null) {
|
|
6249
|
+
handledRequestRef.current = pendingRequestRef.current;
|
|
6250
|
+
pendingRequestRef.current = null;
|
|
6251
|
+
}
|
|
6252
|
+
setSelected(path);
|
|
6253
|
+
setEditMode(false);
|
|
6254
|
+
setLiveRequestedPath(null);
|
|
6255
|
+
setViewReloadRevision(0);
|
|
6256
|
+
}, []);
|
|
6257
|
+
const canEdit = editable && viewPath !== null && !fileView.loading && fileView.error === null && !fileView.isBinary && !fileView.truncated && fileView.content !== null;
|
|
6258
|
+
const showEditor = canEdit && editMode;
|
|
6259
|
+
const captureFileUnavailable = fileView.error instanceof CapturedFileUnavailableError ? fileView.error : null;
|
|
6260
|
+
const waitingForSelectedFile = liveRequestedPath === viewPath && (!liveWorkspaceReady || files.loading) && captureFileUnavailable !== null;
|
|
6261
|
+
if (!fileSystemAvailable) {
|
|
6262
|
+
return /* @__PURE__ */ jsx10(
|
|
6263
|
+
Notice,
|
|
6264
|
+
{
|
|
6265
|
+
className,
|
|
6266
|
+
icon: /* @__PURE__ */ jsx10(FileWarningIcon2, { className: "size-5", "aria-hidden": true }),
|
|
6267
|
+
title: "Files unavailable",
|
|
6268
|
+
announce: "alert",
|
|
6269
|
+
children: "This sandbox does not expose a file system."
|
|
6270
|
+
}
|
|
6271
|
+
);
|
|
6272
|
+
}
|
|
6273
|
+
if (workspaceResting || workspaceWaking) {
|
|
6274
|
+
return /* @__PURE__ */ jsx10("div", { className: cn("h-full", className), "data-opengeni-workspace-resting": true, children: /* @__PURE__ */ jsxs8(
|
|
6275
|
+
Notice,
|
|
6276
|
+
{
|
|
6277
|
+
icon: workspaceWaking ? /* @__PURE__ */ jsx10(
|
|
6278
|
+
LoaderCircleIcon,
|
|
6279
|
+
{
|
|
6280
|
+
className: "size-5 animate-spin motion-reduce:animate-none",
|
|
6281
|
+
"aria-hidden": true
|
|
6282
|
+
}
|
|
6283
|
+
) : /* @__PURE__ */ jsx10(FileCode2Icon, { className: "size-5", "aria-hidden": true }),
|
|
6284
|
+
title: workspaceWaking ? "Waking workspace" : "Workspace is resting",
|
|
6285
|
+
announce: "status",
|
|
6286
|
+
children: [
|
|
6287
|
+
/* @__PURE__ */ jsx10("p", { children: workspaceWaking ? "Connecting to the live file system\u2026" : "No captured revision is available yet. Wake the sandbox to browse its current files." }),
|
|
6288
|
+
!workspaceWaking && onWakeWorkspace ? /* @__PURE__ */ jsx10(WakeButton, { onClick: onWakeWorkspace, children: "Open live workspace" }) : null
|
|
6289
|
+
]
|
|
6290
|
+
}
|
|
6291
|
+
) });
|
|
6292
|
+
}
|
|
6293
|
+
return /* @__PURE__ */ jsxs8("div", { ref: rootRef, className: cn("flex h-full min-h-0 min-w-0 flex-col", className), children: [
|
|
6294
|
+
/* @__PURE__ */ jsx10(GitHeader, { git, dirtyCount: git.diff.length }),
|
|
6295
|
+
/* @__PURE__ */ jsxs8("div", { className: cn("flex min-h-0 flex-1", wide ? "flex-row" : "flex-col"), children: [
|
|
6296
|
+
/* @__PURE__ */ jsx10(
|
|
6297
|
+
"div",
|
|
6298
|
+
{
|
|
6299
|
+
className: cn(
|
|
6300
|
+
"flex min-h-0 flex-col",
|
|
6301
|
+
wide ? "w-[280px] shrink-0 border-r border-og-border" : "flex-1"
|
|
6302
|
+
),
|
|
6303
|
+
children: /* @__PURE__ */ jsx10(
|
|
6304
|
+
FileBrowser,
|
|
6305
|
+
{
|
|
6306
|
+
result: files,
|
|
6307
|
+
selectedPath: selected ?? void 0,
|
|
6308
|
+
onSelectFile: selectFile,
|
|
6309
|
+
editable,
|
|
6310
|
+
emptyState: "This directory is empty",
|
|
6311
|
+
className: "min-w-0 flex-1"
|
|
6312
|
+
}
|
|
6313
|
+
)
|
|
6314
|
+
}
|
|
6315
|
+
),
|
|
6264
6316
|
/* @__PURE__ */ jsxs8(
|
|
6265
|
-
"
|
|
6317
|
+
"div",
|
|
6266
6318
|
{
|
|
6267
|
-
type: "button",
|
|
6268
|
-
onClick: onRelease,
|
|
6269
|
-
title: "Return control (or press Ctrl+Alt+Shift)",
|
|
6270
6319
|
className: cn(
|
|
6271
|
-
"
|
|
6272
|
-
"
|
|
6273
|
-
"outline-none hover:bg-og-accent hover:text-og-accent-fg focus-visible:ring-2 focus-visible:ring-og-accent"
|
|
6320
|
+
"flex min-h-0 min-w-0 flex-col",
|
|
6321
|
+
wide ? "flex-1" : "flex-[1.4] border-t border-og-border"
|
|
6274
6322
|
),
|
|
6275
6323
|
children: [
|
|
6276
|
-
/* @__PURE__ */
|
|
6277
|
-
|
|
6324
|
+
/* @__PURE__ */ jsxs8("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: [
|
|
6325
|
+
/* @__PURE__ */ jsx10(
|
|
6326
|
+
"span",
|
|
6327
|
+
{
|
|
6328
|
+
"data-opengeni-selected-file": true,
|
|
6329
|
+
className: "min-w-0 truncate font-og-mono text-og-xs text-og-fg-muted",
|
|
6330
|
+
children: selected ?? "No file selected"
|
|
6331
|
+
}
|
|
6332
|
+
),
|
|
6333
|
+
canEdit && /* @__PURE__ */ jsx10(
|
|
6334
|
+
Segmented,
|
|
6335
|
+
{
|
|
6336
|
+
options: [
|
|
6337
|
+
{ value: "view", label: "View" },
|
|
6338
|
+
{ value: "edit", label: "Edit" }
|
|
6339
|
+
],
|
|
6340
|
+
value: editMode ? "edit" : "view",
|
|
6341
|
+
onChange: (v) => setEditMode(v === "edit")
|
|
6342
|
+
}
|
|
6343
|
+
)
|
|
6344
|
+
] }),
|
|
6345
|
+
/* @__PURE__ */ jsx10("div", { className: "min-h-0 flex-1 overflow-auto", children: viewPath ? showEditor && fileView.content !== null ? /* @__PURE__ */ jsx10(
|
|
6346
|
+
CodeEditor,
|
|
6347
|
+
{
|
|
6348
|
+
path: viewPath,
|
|
6349
|
+
initialContents: fileView.content,
|
|
6350
|
+
themeType: resolvedTheme,
|
|
6351
|
+
onSave: (contents) => files.writeFile(viewPath, contents, { expectedContent: fileView.content }),
|
|
6352
|
+
onOverwrite: (contents) => files.writeFile(viewPath, contents, { force: true }),
|
|
6353
|
+
onReload: () => setViewReloadRevision((revision) => revision + 1),
|
|
6354
|
+
...onEditIntent ? { onEditIntent } : {},
|
|
6355
|
+
className: "h-full"
|
|
6356
|
+
},
|
|
6357
|
+
viewPath
|
|
6358
|
+
) : waitingForSelectedFile ? /* @__PURE__ */ jsxs8(
|
|
6359
|
+
Notice,
|
|
6360
|
+
{
|
|
6361
|
+
icon: /* @__PURE__ */ jsx10(
|
|
6362
|
+
LoaderCircleIcon,
|
|
6363
|
+
{
|
|
6364
|
+
className: "size-5 animate-spin motion-reduce:animate-none",
|
|
6365
|
+
"aria-hidden": true
|
|
6366
|
+
}
|
|
6367
|
+
),
|
|
6368
|
+
title: "Waking workspace",
|
|
6369
|
+
announce: "status",
|
|
6370
|
+
children: [
|
|
6371
|
+
"Opening ",
|
|
6372
|
+
viewPath,
|
|
6373
|
+
" when the live file system is ready\u2026"
|
|
6374
|
+
]
|
|
6375
|
+
}
|
|
6376
|
+
) : captureFileUnavailable ? /* @__PURE__ */ jsxs8(Notice, { icon: /* @__PURE__ */ jsx10(FileCode2Icon, { className: "size-5", "aria-hidden": true }), title: "On machine", children: [
|
|
6377
|
+
/* @__PURE__ */ jsx10("p", { children: captureFileUnavailable.reason === "too-large" ? "This file is larger than the captured preview limit." : captureFileUnavailable.reason === "content-missing" ? "The captured copy is no longer available." : "This file was indexed, but it was not changed in the captured turn." }),
|
|
6378
|
+
onWakeWorkspace ? /* @__PURE__ */ jsx10(
|
|
6379
|
+
WakeButton,
|
|
6380
|
+
{
|
|
6381
|
+
onClick: () => {
|
|
6382
|
+
setLiveRequestedPath(viewPath);
|
|
6383
|
+
if (liveWorkspaceReady) void files.refresh();
|
|
6384
|
+
else onWakeWorkspace();
|
|
6385
|
+
},
|
|
6386
|
+
children: liveWorkspaceReady ? "Retry live file" : "Open live file"
|
|
6387
|
+
}
|
|
6388
|
+
) : null
|
|
6389
|
+
] }) : fileView.error ? /* @__PURE__ */ jsxs8(Notice, { announce: "alert", children: [
|
|
6390
|
+
"Could not open ",
|
|
6391
|
+
viewPath,
|
|
6392
|
+
": ",
|
|
6393
|
+
fileView.error.message
|
|
6394
|
+
] }) : fileView.loading ? /* @__PURE__ */ jsxs8(Notice, { announce: "status", children: [
|
|
6395
|
+
"Loading ",
|
|
6396
|
+
viewPath,
|
|
6397
|
+
"\u2026"
|
|
6398
|
+
] }) : fileView.isBinary ? /* @__PURE__ */ jsxs8(Notice, { children: [
|
|
6399
|
+
viewPath,
|
|
6400
|
+
" is a binary file (",
|
|
6401
|
+
fileView.sizeBytes ?? 0,
|
|
6402
|
+
" bytes)."
|
|
6403
|
+
] }) : fileView.content !== null ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
6404
|
+
fileView.truncated && /* @__PURE__ */ jsxs8("div", { className: "border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-xs text-og-status-running", children: [
|
|
6405
|
+
"Large file \u2014 showing a truncated preview (",
|
|
6406
|
+
fileView.sizeBytes ?? 0,
|
|
6407
|
+
" bytes loaded). Editing is disabled to avoid corrupting the file."
|
|
6408
|
+
] }),
|
|
6409
|
+
usePierre ? /* @__PURE__ */ jsx10(
|
|
6410
|
+
PierreFile,
|
|
6411
|
+
{
|
|
6412
|
+
path: viewPath,
|
|
6413
|
+
contents: fileView.content,
|
|
6414
|
+
themeType: resolvedTheme,
|
|
6415
|
+
fallback: /* @__PURE__ */ jsx10("pre", { className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg", children: fileView.content }),
|
|
6416
|
+
className: "p-1"
|
|
6417
|
+
}
|
|
6418
|
+
) : /* @__PURE__ */ jsx10("pre", { className: "overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg", children: fileView.content })
|
|
6419
|
+
] }) : /* @__PURE__ */ jsxs8(Notice, { announce: "status", children: [
|
|
6420
|
+
"Loading ",
|
|
6421
|
+
viewPath,
|
|
6422
|
+
"\u2026"
|
|
6423
|
+
] }) : (
|
|
6424
|
+
// Nothing selected — the tree shows the whole workspace; pick a file.
|
|
6425
|
+
requestedPath && !requestedPathReady ? /* @__PURE__ */ jsxs8(
|
|
6426
|
+
Notice,
|
|
6427
|
+
{
|
|
6428
|
+
icon: /* @__PURE__ */ jsx10(
|
|
6429
|
+
LoaderCircleIcon,
|
|
6430
|
+
{
|
|
6431
|
+
className: "size-5 animate-spin motion-reduce:animate-none",
|
|
6432
|
+
"aria-hidden": true
|
|
6433
|
+
}
|
|
6434
|
+
),
|
|
6435
|
+
title: "Waking sandbox",
|
|
6436
|
+
announce: "status",
|
|
6437
|
+
children: [
|
|
6438
|
+
"Opening ",
|
|
6439
|
+
requestedPath,
|
|
6440
|
+
" when the live workspace is ready\u2026"
|
|
6441
|
+
]
|
|
6442
|
+
}
|
|
6443
|
+
) : /* @__PURE__ */ jsx10(Notice, { icon: /* @__PURE__ */ jsx10(FileCode2Icon, { className: "size-5", "aria-hidden": true }), title: "Choose a file", children: "Select a file in the tree to preview it." })
|
|
6444
|
+
) })
|
|
6278
6445
|
]
|
|
6279
6446
|
}
|
|
6280
6447
|
)
|
|
6281
6448
|
] })
|
|
6282
6449
|
] });
|
|
6283
6450
|
}
|
|
6284
|
-
function
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
case "disabled_by_policy":
|
|
6295
|
-
return "Desktop streaming is disabled on this deployment.";
|
|
6296
|
-
case "lease_cold":
|
|
6297
|
-
return "Waiting for the sandbox to start\u2026";
|
|
6298
|
-
default:
|
|
6299
|
-
return "The desktop isn\u2019t available for this sandbox.";
|
|
6300
|
-
}
|
|
6451
|
+
function WakeButton({ children, onClick }) {
|
|
6452
|
+
return /* @__PURE__ */ jsx10(
|
|
6453
|
+
"button",
|
|
6454
|
+
{
|
|
6455
|
+
type: "button",
|
|
6456
|
+
onClick,
|
|
6457
|
+
className: "mt-1 inline-flex min-h-11 items-center justify-center rounded-og-md bg-og-accent-deep px-3 py-2 text-og-sm font-medium text-og-accent-fg shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent focus-visible:ring-offset-2 focus-visible:ring-offset-og-bg",
|
|
6458
|
+
children
|
|
6459
|
+
}
|
|
6460
|
+
);
|
|
6301
6461
|
}
|
|
6302
|
-
function
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
/* @__PURE__ */
|
|
6306
|
-
|
|
6307
|
-
/* @__PURE__ */ jsx10("p", { className: "text-og-sm text-og-fg-subtle", children: "Spinning up the desktop \u2014 this takes a few seconds." })
|
|
6308
|
-
] }),
|
|
6309
|
-
onRetry && /* @__PURE__ */ jsx10(
|
|
6310
|
-
"button",
|
|
6462
|
+
function GitHeader({ git, dirtyCount }) {
|
|
6463
|
+
const dirty = dirtyCount > 0;
|
|
6464
|
+
return /* @__PURE__ */ jsxs8("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: [
|
|
6465
|
+
/* @__PURE__ */ jsx10(
|
|
6466
|
+
"span",
|
|
6311
6467
|
{
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6468
|
+
"aria-hidden": "true",
|
|
6469
|
+
className: cn(
|
|
6470
|
+
"size-2 shrink-0 rounded-full",
|
|
6471
|
+
dirty ? "bg-og-status-running" : "bg-og-status-idle"
|
|
6472
|
+
)
|
|
6316
6473
|
}
|
|
6317
|
-
)
|
|
6318
|
-
|
|
6319
|
-
}
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
/* @__PURE__ */
|
|
6326
|
-
|
|
6327
|
-
|
|
6474
|
+
),
|
|
6475
|
+
/* @__PURE__ */ jsx10("span", { className: "sr-only", children: dirty ? `Working tree has ${dirtyCount} changed files` : "Working tree clean" }),
|
|
6476
|
+
/* @__PURE__ */ jsx10("span", { className: "truncate font-og-mono text-og-fg", children: git.repoCount > 1 ? `${git.repoCount} repositories` : git.branch ?? (git.isRepo ? "(detached)" : "no repo") }),
|
|
6477
|
+
(git.ahead > 0 || git.behind > 0) && /* @__PURE__ */ jsxs8("span", { className: "flex shrink-0 items-center gap-1.5 text-og-xs text-og-fg-subtle", children: [
|
|
6478
|
+
git.ahead > 0 && /* @__PURE__ */ jsxs8("span", { children: [
|
|
6479
|
+
"\u2191",
|
|
6480
|
+
git.ahead
|
|
6481
|
+
] }),
|
|
6482
|
+
git.behind > 0 && /* @__PURE__ */ jsxs8("span", { children: [
|
|
6483
|
+
"\u2193",
|
|
6484
|
+
git.behind
|
|
6485
|
+
] })
|
|
6328
6486
|
] }),
|
|
6329
|
-
/* @__PURE__ */
|
|
6330
|
-
"
|
|
6487
|
+
dirty && /* @__PURE__ */ jsxs8(
|
|
6488
|
+
"span",
|
|
6331
6489
|
{
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
className: "
|
|
6335
|
-
children:
|
|
6490
|
+
"aria-hidden": "true",
|
|
6491
|
+
"data-contrast-audited": true,
|
|
6492
|
+
className: "ml-auto shrink-0 text-og-xs text-og-fg-subtle",
|
|
6493
|
+
children: [
|
|
6494
|
+
dirtyCount,
|
|
6495
|
+
" changed"
|
|
6496
|
+
]
|
|
6336
6497
|
}
|
|
6337
6498
|
)
|
|
6338
6499
|
] });
|
|
6339
6500
|
}
|
|
6340
|
-
function
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
"button",
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6501
|
+
function Segmented({
|
|
6502
|
+
options,
|
|
6503
|
+
value,
|
|
6504
|
+
onChange
|
|
6505
|
+
}) {
|
|
6506
|
+
return /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap items-center rounded-og-sm border border-og-border p-0.5", children: options.map((opt) => /* @__PURE__ */ jsx10(
|
|
6507
|
+
"button",
|
|
6508
|
+
{
|
|
6509
|
+
type: "button",
|
|
6510
|
+
onClick: () => onChange(opt.value),
|
|
6511
|
+
className: cn(
|
|
6512
|
+
"min-h-7 rounded-og-xs px-1.5 py-0.5 text-og-xs focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-h-11 max-[1023px]:min-w-11 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
|
|
6513
|
+
opt.value === value ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
6514
|
+
),
|
|
6515
|
+
children: opt.label
|
|
6516
|
+
},
|
|
6517
|
+
opt.value
|
|
6518
|
+
)) });
|
|
6357
6519
|
}
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6520
|
+
function useFileView(path, readFile, reloadRevision = 0) {
|
|
6521
|
+
const [state, setState] = useState17({
|
|
6522
|
+
content: null,
|
|
6523
|
+
isBinary: false,
|
|
6524
|
+
truncated: false,
|
|
6525
|
+
sizeBytes: null,
|
|
6526
|
+
loading: false,
|
|
6527
|
+
error: null
|
|
6528
|
+
});
|
|
6529
|
+
useEffect20(() => {
|
|
6530
|
+
if (!path) {
|
|
6531
|
+
setState({
|
|
6532
|
+
content: null,
|
|
6533
|
+
isBinary: false,
|
|
6534
|
+
truncated: false,
|
|
6535
|
+
sizeBytes: null,
|
|
6536
|
+
loading: false,
|
|
6537
|
+
error: null
|
|
6538
|
+
});
|
|
6539
|
+
return;
|
|
6540
|
+
}
|
|
6541
|
+
let cancelled = false;
|
|
6542
|
+
const abort = new AbortController();
|
|
6543
|
+
setState({
|
|
6544
|
+
content: null,
|
|
6545
|
+
isBinary: false,
|
|
6546
|
+
truncated: false,
|
|
6547
|
+
sizeBytes: null,
|
|
6548
|
+
loading: true,
|
|
6549
|
+
error: null
|
|
6550
|
+
});
|
|
6551
|
+
void readFile(path, { signal: abort.signal }).then((res) => {
|
|
6552
|
+
if (cancelled) return;
|
|
6553
|
+
const content = res.isBinary ? null : res.encoding === "base64" ? decodeBase64Utf8(res.content) : res.content;
|
|
6554
|
+
setState({
|
|
6555
|
+
content,
|
|
6556
|
+
isBinary: res.isBinary,
|
|
6557
|
+
truncated: res.truncated,
|
|
6558
|
+
sizeBytes: res.sizeBytes,
|
|
6559
|
+
loading: false,
|
|
6560
|
+
error: null
|
|
6561
|
+
});
|
|
6562
|
+
}).catch((cause) => {
|
|
6563
|
+
if (cancelled) return;
|
|
6564
|
+
setState({
|
|
6565
|
+
content: null,
|
|
6566
|
+
isBinary: false,
|
|
6567
|
+
truncated: false,
|
|
6568
|
+
sizeBytes: null,
|
|
6569
|
+
loading: false,
|
|
6570
|
+
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
6571
|
+
});
|
|
6572
|
+
});
|
|
6573
|
+
return () => {
|
|
6574
|
+
cancelled = true;
|
|
6575
|
+
abort.abort();
|
|
6576
|
+
};
|
|
6577
|
+
}, [path, readFile, reloadRevision]);
|
|
6578
|
+
return state;
|
|
6579
|
+
}
|
|
6580
|
+
function decodeBase64Utf8(b64) {
|
|
6390
6581
|
try {
|
|
6391
|
-
|
|
6582
|
+
if (typeof atob === "function") {
|
|
6583
|
+
const binary = atob(b64);
|
|
6584
|
+
const bytes = new Uint8Array(binary.length);
|
|
6585
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
6586
|
+
return new TextDecoder().decode(bytes);
|
|
6587
|
+
}
|
|
6392
6588
|
} catch {
|
|
6393
|
-
return SERVER_LAYOUT_STORAGE;
|
|
6394
6589
|
}
|
|
6590
|
+
return b64;
|
|
6395
6591
|
}
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6592
|
+
function Notice({
|
|
6593
|
+
children,
|
|
6594
|
+
className,
|
|
6595
|
+
icon,
|
|
6596
|
+
title,
|
|
6597
|
+
announce
|
|
6598
|
+
}) {
|
|
6599
|
+
return /* @__PURE__ */ jsx10(
|
|
6600
|
+
"div",
|
|
6601
|
+
{
|
|
6602
|
+
role: announce,
|
|
6603
|
+
"aria-atomic": announce ? "true" : void 0,
|
|
6604
|
+
"aria-live": announce === "alert" ? "assertive" : announce === "status" ? "polite" : void 0,
|
|
6605
|
+
className: cn(
|
|
6606
|
+
"flex h-full items-center justify-center p-4 text-center text-og-sm text-og-fg-subtle",
|
|
6607
|
+
className
|
|
6608
|
+
),
|
|
6609
|
+
children: /* @__PURE__ */ jsxs8("div", { className: "flex max-w-sm flex-col items-center gap-2.5", children: [
|
|
6610
|
+
icon ? /* @__PURE__ */ jsx10("span", { className: "grid size-10 place-items-center rounded-og-lg border border-og-border bg-og-surface-1 text-og-fg-muted shadow-sm", children: icon }) : null,
|
|
6611
|
+
title ? /* @__PURE__ */ jsx10("p", { className: "font-medium text-og-fg", children: title }) : null,
|
|
6612
|
+
/* @__PURE__ */ jsx10("div", { className: "leading-5", children })
|
|
6613
|
+
] })
|
|
6410
6614
|
}
|
|
6411
|
-
|
|
6412
|
-
return () => mql.removeListener(update);
|
|
6413
|
-
}, [maxWidth]);
|
|
6414
|
-
return narrow;
|
|
6615
|
+
);
|
|
6415
6616
|
}
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6617
|
+
|
|
6618
|
+
// src/components/desktop-viewer.tsx
|
|
6619
|
+
import { LoaderCircleIcon as LoaderCircleIcon2, MonitorIcon, MousePointerClickIcon, WifiOffIcon } from "lucide-react";
|
|
6620
|
+
import { useEffect as useEffect21, useRef as useRef18, useState as useState18 } from "react";
|
|
6621
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
6622
|
+
var DESKTOP_MEDIA_BACKGROUND = "#000";
|
|
6623
|
+
function isHardUnavailable(reason) {
|
|
6624
|
+
switch (reason) {
|
|
6625
|
+
case "backend_unsupported":
|
|
6626
|
+
case "os_unsupported":
|
|
6627
|
+
case "not_provisioned":
|
|
6628
|
+
case "disabled_by_policy":
|
|
6629
|
+
case "tier_headless":
|
|
6630
|
+
return true;
|
|
6631
|
+
default:
|
|
6632
|
+
return false;
|
|
6633
|
+
}
|
|
6634
|
+
}
|
|
6635
|
+
function DesktopViewer({
|
|
6636
|
+
capability,
|
|
6637
|
+
interactive,
|
|
6638
|
+
showControlToggle = true,
|
|
6639
|
+
scaleViewport,
|
|
6640
|
+
rfbFactory,
|
|
6641
|
+
webSocketFactory,
|
|
6642
|
+
renderConsentGate,
|
|
6643
|
+
onAcknowledge,
|
|
6644
|
+
watching,
|
|
6645
|
+
onWarm,
|
|
6646
|
+
renderUnavailable,
|
|
6647
|
+
renderWarming,
|
|
6648
|
+
renderViewerCap,
|
|
6649
|
+
viewerCapReached,
|
|
6650
|
+
connectTimeoutMs = 13e3,
|
|
6429
6651
|
className
|
|
6430
6652
|
}) {
|
|
6431
|
-
const
|
|
6432
|
-
const
|
|
6433
|
-
const
|
|
6434
|
-
const
|
|
6435
|
-
const
|
|
6436
|
-
const
|
|
6437
|
-
const
|
|
6438
|
-
const
|
|
6439
|
-
const
|
|
6440
|
-
const
|
|
6441
|
-
const
|
|
6442
|
-
const
|
|
6443
|
-
const
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
const requestedTabIsValid = tabIds.includes(requestedTab);
|
|
6452
|
-
const current = requestedTabIsValid ? requestedTab : firstTabId;
|
|
6453
|
-
const setTab = useCallback19(
|
|
6454
|
-
(id) => {
|
|
6455
|
-
setInternalTab(id);
|
|
6456
|
-
onActiveTabChange?.(id);
|
|
6457
|
-
},
|
|
6458
|
-
[onActiveTabChange]
|
|
6459
|
-
);
|
|
6460
|
-
const setCollapsed = useCallback19(
|
|
6461
|
-
(next) => {
|
|
6462
|
-
setInternalCollapsed((previous) => previous === next ? previous : next);
|
|
6463
|
-
onCollapsedChange?.(next);
|
|
6464
|
-
},
|
|
6465
|
-
[onCollapsedChange]
|
|
6466
|
-
);
|
|
6467
|
-
useDockLayoutEffect(() => {
|
|
6468
|
-
if (collapsedProp === void 0) {
|
|
6469
|
-
return;
|
|
6470
|
-
}
|
|
6471
|
-
if (collapsedProp) {
|
|
6472
|
-
dockPanelRef.current?.collapse();
|
|
6473
|
-
setMaximized(false);
|
|
6474
|
-
} else {
|
|
6475
|
-
dockPanelRef.current?.expand();
|
|
6476
|
-
}
|
|
6477
|
-
}, [collapsedProp, dockPanelRef]);
|
|
6478
|
-
useEffect20(() => {
|
|
6479
|
-
const previous = previousCollapsedRef.current;
|
|
6480
|
-
previousCollapsedRef.current = collapsed;
|
|
6481
|
-
if (previous === collapsed) return;
|
|
6482
|
-
if (!collapsed) {
|
|
6483
|
-
const active = document.activeElement;
|
|
6484
|
-
const workspaceSurface = rootRef.current?.querySelector(
|
|
6485
|
-
narrow ? '[role="dialog"]' : "[data-workspace-surface]"
|
|
6486
|
-
);
|
|
6487
|
-
if (active instanceof HTMLElement && !workspaceSurface?.contains(active)) {
|
|
6488
|
-
returnFocusRef.current = active;
|
|
6489
|
-
}
|
|
6490
|
-
if (narrow) {
|
|
6491
|
-
const frame2 = requestAnimationFrame(() => {
|
|
6492
|
-
rootRef.current?.querySelector('[role="dialog"] [role="tab"][aria-selected="true"]')?.focus();
|
|
6493
|
-
});
|
|
6494
|
-
return () => cancelAnimationFrame(frame2);
|
|
6495
|
-
}
|
|
6496
|
-
return;
|
|
6497
|
-
}
|
|
6498
|
-
const frame = requestAnimationFrame(() => {
|
|
6499
|
-
if (!hostControlled) {
|
|
6500
|
-
reopenRef.current?.focus();
|
|
6501
|
-
return;
|
|
6502
|
-
}
|
|
6503
|
-
const target = returnFocusRef.current;
|
|
6504
|
-
if (target?.isConnected) target.focus();
|
|
6505
|
-
});
|
|
6506
|
-
return () => cancelAnimationFrame(frame);
|
|
6507
|
-
}, [collapsed, hostControlled, narrow]);
|
|
6508
|
-
useEffect20(() => {
|
|
6509
|
-
if (!narrow || collapsed || initialNarrowFocusRef.current) return;
|
|
6510
|
-
initialNarrowFocusRef.current = true;
|
|
6511
|
-
const active = document.activeElement;
|
|
6512
|
-
const workspaceSurface = rootRef.current?.querySelector('[role="dialog"]');
|
|
6513
|
-
if (active instanceof HTMLElement && !workspaceSurface?.contains(active)) {
|
|
6514
|
-
returnFocusRef.current = active;
|
|
6515
|
-
}
|
|
6516
|
-
const frame = requestAnimationFrame(() => {
|
|
6517
|
-
workspaceSurface?.querySelector('[role="tab"][aria-selected="true"]')?.focus();
|
|
6518
|
-
});
|
|
6519
|
-
return () => cancelAnimationFrame(frame);
|
|
6520
|
-
}, [collapsed, narrow]);
|
|
6521
|
-
useEffect20(() => {
|
|
6522
|
-
if (firstTabId && !requestedTabIsValid) {
|
|
6523
|
-
setTab(firstTabId);
|
|
6524
|
-
}
|
|
6525
|
-
}, [firstTabId, requestedTabIsValid, setTab]);
|
|
6526
|
-
const collapse = useCallback19(() => {
|
|
6527
|
-
dockPanelRef.current?.collapse();
|
|
6528
|
-
setCollapsed(true);
|
|
6529
|
-
}, [dockPanelRef, setCollapsed]);
|
|
6530
|
-
const expand = useCallback19(() => {
|
|
6531
|
-
dockPanelRef.current?.expand();
|
|
6532
|
-
setCollapsed(false);
|
|
6533
|
-
}, [dockPanelRef, setCollapsed]);
|
|
6534
|
-
useEffect20(() => {
|
|
6535
|
-
const overlayOpen = maximized || narrow && !collapsed;
|
|
6536
|
-
if (!overlayOpen) return;
|
|
6653
|
+
const containerRef = useRef18(null);
|
|
6654
|
+
const [consented, setConsented] = useState18(false);
|
|
6655
|
+
const [takeControl, setTakeControl] = useState18(interactive ?? false);
|
|
6656
|
+
const externallyControlled = interactive !== void 0;
|
|
6657
|
+
const serverAllowsControl = capability?.mode !== "read-only";
|
|
6658
|
+
const wantControl = externallyControlled ? interactive : takeControl;
|
|
6659
|
+
const inControl = Boolean(wantControl) && serverAllowsControl;
|
|
6660
|
+
const isWatching = watching ?? consented;
|
|
6661
|
+
const transportNull = !capability || capability.transport === null;
|
|
6662
|
+
const reason = capability?.reason ?? null;
|
|
6663
|
+
const needsAck = capability?.requiresAcknowledgment === true && capability.acknowledged !== true && !consented;
|
|
6664
|
+
const noLiveAddress = Boolean(capability) && !transportNull && !capability.url;
|
|
6665
|
+
const coldWarmable = transportNull && reason === "lease_cold" || !transportNull && noLiveAddress;
|
|
6666
|
+
const hardUnavailable = transportNull && isHardUnavailable(reason);
|
|
6667
|
+
const accept = () => {
|
|
6668
|
+
setConsented(true);
|
|
6669
|
+
onAcknowledge?.();
|
|
6670
|
+
};
|
|
6671
|
+
useEffect21(() => {
|
|
6672
|
+
if (!inControl || externallyControlled) return;
|
|
6537
6673
|
const onKey = (event) => {
|
|
6538
|
-
if (event.key === "
|
|
6539
|
-
if (maximized) setMaximized(false);
|
|
6540
|
-
else collapse();
|
|
6541
|
-
return;
|
|
6542
|
-
}
|
|
6543
|
-
if (event.key !== "Tab") return;
|
|
6544
|
-
const surface = rootRef.current?.querySelector(
|
|
6545
|
-
narrow ? '[role="dialog"]' : "[data-workspace-surface]"
|
|
6546
|
-
);
|
|
6547
|
-
if (!surface) return;
|
|
6548
|
-
const focusable = Array.from(surface.querySelectorAll("*")).filter(
|
|
6549
|
-
(element) => element.tabIndex >= 0 && !element.hasAttribute("disabled") && element.getClientRects().length > 0 && getComputedStyle(element).visibility !== "hidden"
|
|
6550
|
-
);
|
|
6551
|
-
const first = focusable[0];
|
|
6552
|
-
const last = focusable.at(-1);
|
|
6553
|
-
const active = document.activeElement;
|
|
6554
|
-
if (!first || !last) {
|
|
6555
|
-
event.preventDefault();
|
|
6556
|
-
surface.focus();
|
|
6557
|
-
return;
|
|
6558
|
-
}
|
|
6559
|
-
if (!surface.contains(active)) {
|
|
6560
|
-
event.preventDefault();
|
|
6561
|
-
(event.shiftKey ? last : first).focus();
|
|
6562
|
-
return;
|
|
6563
|
-
}
|
|
6564
|
-
if (event.shiftKey && active === first || !event.shiftKey && active === last) {
|
|
6674
|
+
if (event.ctrlKey && event.altKey && event.shiftKey && (event.key === "Control" || event.key === "Alt" || event.key === "Shift")) {
|
|
6565
6675
|
event.preventDefault();
|
|
6566
|
-
(
|
|
6567
|
-
return;
|
|
6676
|
+
setTakeControl(false);
|
|
6568
6677
|
}
|
|
6569
|
-
requestAnimationFrame(() => {
|
|
6570
|
-
const next = document.activeElement;
|
|
6571
|
-
if (!surface.contains(next)) (event.shiftKey ? last : first).focus();
|
|
6572
|
-
});
|
|
6573
6678
|
};
|
|
6574
6679
|
window.addEventListener("keydown", onKey);
|
|
6575
|
-
return () =>
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6680
|
+
return () => {
|
|
6681
|
+
window.removeEventListener("keydown", onKey);
|
|
6682
|
+
};
|
|
6683
|
+
}, [inControl, externallyControlled]);
|
|
6684
|
+
const connectCapability = !transportNull && !needsAck && !viewerCapReached ? capability : null;
|
|
6685
|
+
const stream = useDesktopStream({
|
|
6686
|
+
capability: connectCapability,
|
|
6687
|
+
containerRef,
|
|
6688
|
+
interactive: inControl,
|
|
6689
|
+
...scaleViewport !== void 0 ? { scaleViewport } : {},
|
|
6690
|
+
...rfbFactory ? { rfbFactory } : {},
|
|
6691
|
+
...webSocketFactory ? { webSocketFactory } : {}
|
|
6692
|
+
});
|
|
6693
|
+
const connected = stream.state === "connected";
|
|
6694
|
+
const hasLiveUrl = Boolean(connectCapability?.url);
|
|
6695
|
+
const streamStateRef = useRef18(stream.state);
|
|
6696
|
+
streamStateRef.current = stream.state;
|
|
6697
|
+
const warmKeyRef = useRef18(null);
|
|
6698
|
+
useEffect21(() => {
|
|
6699
|
+
if (!isWatching || !coldWarmable || needsAck || viewerCapReached) {
|
|
6700
|
+
if (!coldWarmable) warmKeyRef.current = null;
|
|
6701
|
+
return;
|
|
6702
|
+
}
|
|
6703
|
+
const warm = onWarm ?? onAcknowledge;
|
|
6704
|
+
if (!warm) return;
|
|
6705
|
+
const key = `${capability?.reason ?? ""}:${capability?.url ?? ""}:${capability?.expiresAt ?? ""}`;
|
|
6706
|
+
if (warmKeyRef.current === key) return;
|
|
6707
|
+
warmKeyRef.current = key;
|
|
6708
|
+
warm();
|
|
6709
|
+
}, [isWatching, coldWarmable, needsAck, viewerCapReached, capability, onWarm, onAcknowledge]);
|
|
6710
|
+
useEffect21(() => {
|
|
6711
|
+
if (!hasLiveUrl || typeof document === "undefined") return;
|
|
6712
|
+
const maybeReattach = () => {
|
|
6713
|
+
if (document.visibilityState !== "visible") return;
|
|
6714
|
+
if (streamStateRef.current === "idle") stream.reconnect();
|
|
6715
|
+
};
|
|
6716
|
+
document.addEventListener("visibilitychange", maybeReattach);
|
|
6717
|
+
return () => document.removeEventListener("visibilitychange", maybeReattach);
|
|
6718
|
+
}, [hasLiveUrl, connectCapability?.url]);
|
|
6719
|
+
const [connectTimedOut, setConnectTimedOut] = useState18(false);
|
|
6720
|
+
const [reconnectNonce, setReconnectNonce] = useState18(0);
|
|
6721
|
+
useEffect21(() => {
|
|
6722
|
+
setConnectTimedOut(false);
|
|
6723
|
+
if (!hasLiveUrl || connected || stream.error || connectTimeoutMs <= 0) return;
|
|
6724
|
+
const timer = setTimeout(() => setConnectTimedOut(true), connectTimeoutMs);
|
|
6725
|
+
return () => clearTimeout(timer);
|
|
6726
|
+
}, [
|
|
6727
|
+
hasLiveUrl,
|
|
6728
|
+
connected,
|
|
6729
|
+
connectTimeoutMs,
|
|
6730
|
+
connectCapability?.url,
|
|
6731
|
+
stream.error,
|
|
6732
|
+
reconnectNonce
|
|
6733
|
+
]);
|
|
6734
|
+
const reconnect = () => {
|
|
6735
|
+
setConnectTimedOut(false);
|
|
6736
|
+
setReconnectNonce((n) => n + 1);
|
|
6737
|
+
stream.reconnect();
|
|
6738
|
+
};
|
|
6739
|
+
let uiState;
|
|
6740
|
+
if (viewerCapReached) uiState = "viewer_cap";
|
|
6741
|
+
else if (hardUnavailable) uiState = "unavailable";
|
|
6742
|
+
else if (needsAck && !isWatching) uiState = "consent";
|
|
6743
|
+
else if (coldWarmable) uiState = "warming";
|
|
6744
|
+
else if (connected) uiState = "connected";
|
|
6745
|
+
else if (stream.error) uiState = "error";
|
|
6746
|
+
else if (connectTimedOut) uiState = "connect_failed";
|
|
6747
|
+
else uiState = "connecting";
|
|
6748
|
+
const overlayShown = uiState !== "connected" && uiState !== "connecting";
|
|
6749
|
+
const showToggle = showControlToggle && !overlayShown;
|
|
6750
|
+
let overlay = null;
|
|
6751
|
+
switch (uiState) {
|
|
6752
|
+
case "viewer_cap":
|
|
6753
|
+
overlay = renderViewerCap?.() ?? defaultNotice(
|
|
6754
|
+
"Too many viewers",
|
|
6755
|
+
"This session has reached its live-viewer limit. Try again shortly."
|
|
6756
|
+
);
|
|
6757
|
+
break;
|
|
6758
|
+
case "unavailable":
|
|
6759
|
+
overlay = renderUnavailable?.(reason) ?? defaultNotice("Desktop unavailable", unavailableCopy(reason));
|
|
6760
|
+
break;
|
|
6761
|
+
case "consent":
|
|
6762
|
+
overlay = renderConsentGate ? renderConsentGate(accept, capability?.shared ?? false) : /* @__PURE__ */ jsx11(DefaultConsentGate, { shared: capability?.shared ?? false, onAccept: accept });
|
|
6763
|
+
break;
|
|
6764
|
+
case "warming":
|
|
6765
|
+
overlay = renderWarming?.() ?? /* @__PURE__ */ jsx11(WarmingNotice, {});
|
|
6766
|
+
break;
|
|
6767
|
+
case "connect_failed":
|
|
6768
|
+
overlay = defaultNotice(
|
|
6769
|
+
"Couldn\u2019t connect",
|
|
6770
|
+
"The desktop is warm but the live stream didn\u2019t come up. This usually clears on a retry.",
|
|
6771
|
+
reconnect
|
|
6772
|
+
);
|
|
6773
|
+
break;
|
|
6774
|
+
case "error":
|
|
6775
|
+
overlay = defaultNotice(
|
|
6776
|
+
"Desktop disconnected",
|
|
6777
|
+
stream.error?.message ?? "The stream dropped.",
|
|
6778
|
+
reconnect
|
|
6779
|
+
);
|
|
6780
|
+
break;
|
|
6781
|
+
case "connecting":
|
|
6782
|
+
case "connected":
|
|
6783
|
+
overlay = null;
|
|
6784
|
+
break;
|
|
6629
6785
|
}
|
|
6630
|
-
|
|
6631
|
-
|
|
6786
|
+
return /* @__PURE__ */ jsxs9(
|
|
6787
|
+
"div",
|
|
6632
6788
|
{
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6789
|
+
className: cn(
|
|
6790
|
+
"relative h-full w-full overflow-hidden",
|
|
6791
|
+
inControl && "ring-2 ring-inset ring-og-accent",
|
|
6792
|
+
className
|
|
6793
|
+
),
|
|
6794
|
+
style: { backgroundColor: DESKTOP_MEDIA_BACKGROUND },
|
|
6795
|
+
"data-opengeni-desktop": true,
|
|
6796
|
+
"data-state": stream.state,
|
|
6797
|
+
"data-ui-state": uiState,
|
|
6798
|
+
"data-in-control": inControl ? "true" : void 0,
|
|
6799
|
+
children: [
|
|
6638
6800
|
/* @__PURE__ */ jsx11(
|
|
6639
|
-
|
|
6801
|
+
"div",
|
|
6640
6802
|
{
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6803
|
+
ref: containerRef,
|
|
6804
|
+
className: "absolute inset-0 overflow-hidden",
|
|
6805
|
+
"data-opengeni-desktop-canvas": true,
|
|
6806
|
+
"data-state": stream.state
|
|
6645
6807
|
}
|
|
6646
6808
|
),
|
|
6647
|
-
|
|
6648
|
-
|
|
6809
|
+
uiState === "connecting" && /* @__PURE__ */ jsxs9("div", { className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center gap-3 text-og-fg-subtle", children: [
|
|
6810
|
+
/* @__PURE__ */ jsxs9("span", { className: "relative flex items-center justify-center", children: [
|
|
6811
|
+
/* @__PURE__ */ jsx11(MonitorIcon, { className: "size-8 opacity-30", strokeWidth: 1.5 }),
|
|
6812
|
+
/* @__PURE__ */ jsx11(
|
|
6813
|
+
LoaderCircleIcon2,
|
|
6814
|
+
{
|
|
6815
|
+
className: "absolute size-12 animate-og-spin text-og-accent opacity-70",
|
|
6816
|
+
strokeWidth: 1.25
|
|
6817
|
+
}
|
|
6818
|
+
)
|
|
6819
|
+
] }),
|
|
6820
|
+
/* @__PURE__ */ jsx11("span", { className: "text-og-sm", children: "Connecting to the desktop\u2026" })
|
|
6821
|
+
] }),
|
|
6822
|
+
showToggle && !externallyControlled && inControl && /* @__PURE__ */ jsx11(
|
|
6823
|
+
InControlBar,
|
|
6824
|
+
{
|
|
6825
|
+
shared: capability?.shared ?? false,
|
|
6826
|
+
onRelease: () => setTakeControl(false)
|
|
6827
|
+
}
|
|
6828
|
+
),
|
|
6829
|
+
showToggle && !externallyControlled && !inControl && connected && /* @__PURE__ */ jsx11(
|
|
6830
|
+
TakeControlCallToAction,
|
|
6831
|
+
{
|
|
6832
|
+
disabled: !serverAllowsControl,
|
|
6833
|
+
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,
|
|
6834
|
+
onTakeControl: () => setTakeControl(true)
|
|
6835
|
+
}
|
|
6836
|
+
),
|
|
6837
|
+
overlay && /* @__PURE__ */ jsx11("div", { className: "absolute inset-0 flex items-center justify-center p-4", children: overlay })
|
|
6838
|
+
]
|
|
6649
6839
|
}
|
|
6650
6840
|
);
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6841
|
+
}
|
|
6842
|
+
function TakeControlCallToAction({
|
|
6843
|
+
disabled,
|
|
6844
|
+
disabledReason,
|
|
6845
|
+
onTakeControl
|
|
6846
|
+
}) {
|
|
6847
|
+
return (
|
|
6848
|
+
// The wrapper spans the surface but is click-through (pointer-events-none); only
|
|
6849
|
+
// the button itself is interactive, so watchers can still see the desktop.
|
|
6850
|
+
/* @__PURE__ */ jsx11("div", { className: "pointer-events-none absolute inset-0 flex items-end justify-center pb-[8%]", children: /* @__PURE__ */ jsxs9(
|
|
6851
|
+
"button",
|
|
6654
6852
|
{
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6853
|
+
type: "button",
|
|
6854
|
+
disabled,
|
|
6855
|
+
"aria-label": "Take control of the desktop",
|
|
6856
|
+
title: disabled ? disabledReason : "Take control of the desktop",
|
|
6857
|
+
onClick: onTakeControl,
|
|
6858
|
+
className: cn(
|
|
6859
|
+
"group pointer-events-auto flex items-center gap-3 rounded-og-lg border px-5 py-3",
|
|
6860
|
+
"border-og-border",
|
|
6861
|
+
"bg-og-bg/85 backdrop-blur-md",
|
|
6862
|
+
"shadow-og-lg",
|
|
6863
|
+
"outline-none transition-all duration-150 ease-out",
|
|
6864
|
+
"focus-visible:ring-2 focus-visible:ring-og-accent focus-visible:ring-offset-2 focus-visible:ring-offset-og-bg",
|
|
6865
|
+
disabled ? "cursor-not-allowed opacity-60" : cn(
|
|
6866
|
+
"cursor-pointer opacity-90 hover:-translate-y-0.5 hover:opacity-100",
|
|
6867
|
+
"hover:border-og-accent",
|
|
6868
|
+
"hover:bg-og-accent/10"
|
|
6869
|
+
)
|
|
6870
|
+
),
|
|
6659
6871
|
children: [
|
|
6660
|
-
/* @__PURE__ */ jsx11(Panel, { id: "primary", minSize: "30%", className: "min-h-0 min-w-0", children: /* @__PURE__ */ jsx11(
|
|
6661
|
-
"div",
|
|
6662
|
-
{
|
|
6663
|
-
"data-workspace-primary": true,
|
|
6664
|
-
"aria-hidden": maximized ? true : void 0,
|
|
6665
|
-
className: "h-full min-h-0 min-w-0",
|
|
6666
|
-
inert: maximized ? true : void 0,
|
|
6667
|
-
children: primary
|
|
6668
|
-
}
|
|
6669
|
-
) }),
|
|
6670
|
-
!collapsed && /* @__PURE__ */ jsx11(Separator, { className: "group relative z-10 w-1.5 shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent max-[1023px]:-mx-[19px] max-[1023px]:w-11 pointer-coarse:-mx-[19px] pointer-coarse:w-11", children: /* @__PURE__ */ jsx11("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-focus-visible:bg-og-accent group-data-[separator-state=dragging]:bg-og-accent" }) }),
|
|
6671
6872
|
/* @__PURE__ */ jsx11(
|
|
6672
|
-
|
|
6873
|
+
"span",
|
|
6673
6874
|
{
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
onResize: (size, _id, previousSize) => {
|
|
6682
|
-
const isCollapsed = size.asPercentage <= 1;
|
|
6683
|
-
const canInferCollapse = collapsedProp === void 0 || previousSize !== void 0;
|
|
6684
|
-
if (canInferCollapse && isCollapsed !== collapsed) {
|
|
6685
|
-
setCollapsed(isCollapsed);
|
|
6686
|
-
}
|
|
6687
|
-
},
|
|
6688
|
-
className: "min-h-0 min-w-0",
|
|
6689
|
-
children: /* @__PURE__ */ jsx11(
|
|
6690
|
-
"div",
|
|
6691
|
-
{
|
|
6692
|
-
"data-workspace-surface": true,
|
|
6693
|
-
role: maximized ? "dialog" : void 0,
|
|
6694
|
-
"aria-modal": maximized ? true : void 0,
|
|
6695
|
-
"aria-label": maximized ? "Workspace" : void 0,
|
|
6696
|
-
"aria-hidden": collapsed ? true : void 0,
|
|
6697
|
-
className: cn(
|
|
6698
|
-
"flex h-full min-h-0 min-w-0 flex-col bg-og-bg",
|
|
6699
|
-
maximized ? "fixed inset-0 z-40" : "border-l border-og-border",
|
|
6700
|
-
collapsed && "invisible pointer-events-none"
|
|
6701
|
-
),
|
|
6702
|
-
children: dockChrome
|
|
6703
|
-
}
|
|
6704
|
-
)
|
|
6875
|
+
className: cn(
|
|
6876
|
+
"flex size-9 shrink-0 items-center justify-center rounded-full transition-colors",
|
|
6877
|
+
"bg-og-accent",
|
|
6878
|
+
"text-og-accent-fg",
|
|
6879
|
+
disabled ? "" : "group-hover:scale-105"
|
|
6880
|
+
),
|
|
6881
|
+
children: /* @__PURE__ */ jsx11(MousePointerClickIcon, { className: "size-5", strokeWidth: 2 })
|
|
6705
6882
|
}
|
|
6706
|
-
)
|
|
6883
|
+
),
|
|
6884
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex flex-col items-start leading-tight", children: [
|
|
6885
|
+
/* @__PURE__ */ jsx11("span", { className: "text-og-base font-semibold text-og-fg", children: "Take control" }),
|
|
6886
|
+
/* @__PURE__ */ jsx11("span", { className: "text-og-xs text-og-fg-subtle", children: disabled && disabledReason ? disabledReason : "Drive the mouse & keyboard" })
|
|
6887
|
+
] })
|
|
6707
6888
|
]
|
|
6708
6889
|
}
|
|
6709
|
-
)
|
|
6710
|
-
collapsed && !maximized && !hostControlled && /* @__PURE__ */ jsx11(
|
|
6711
|
-
"button",
|
|
6712
|
-
{
|
|
6713
|
-
ref: reopenRef,
|
|
6714
|
-
type: "button",
|
|
6715
|
-
onClick: expand,
|
|
6716
|
-
title: "Open workspace",
|
|
6717
|
-
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",
|
|
6718
|
-
children: /* @__PURE__ */ jsx11(ChevronsLeftRightIcon, { className: "size-3.5" })
|
|
6719
|
-
}
|
|
6720
|
-
)
|
|
6721
|
-
] });
|
|
6722
|
-
}
|
|
6723
|
-
function ChromeButton({
|
|
6724
|
-
onClick,
|
|
6725
|
-
title,
|
|
6726
|
-
label,
|
|
6727
|
-
children
|
|
6728
|
-
}) {
|
|
6729
|
-
return /* @__PURE__ */ jsx11(
|
|
6730
|
-
"button",
|
|
6731
|
-
{
|
|
6732
|
-
type: "button",
|
|
6733
|
-
onClick,
|
|
6734
|
-
title,
|
|
6735
|
-
"aria-label": label,
|
|
6736
|
-
className: "inline-flex size-7 items-center justify-center rounded-og-sm p-1 transition-colors hover:bg-og-surface-2 hover:text-og-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:size-11 pointer-coarse:size-11",
|
|
6737
|
-
children
|
|
6738
|
-
}
|
|
6890
|
+
) })
|
|
6739
6891
|
);
|
|
6740
6892
|
}
|
|
6741
|
-
function
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
const tabListRef = useRef17(null);
|
|
6753
|
-
const [visitedTabs, setVisitedTabs] = useState17(() => /* @__PURE__ */ new Set());
|
|
6754
|
-
const [tabOverflow, setTabOverflow] = useState17({ start: false, end: false });
|
|
6755
|
-
const activeId = active?.id ?? "";
|
|
6756
|
-
const activeTabIndex = tabs.findIndex((tab) => tab.id === activeId);
|
|
6757
|
-
const keepActiveTabVisible = useCallback19(() => {
|
|
6758
|
-
const selected = activeTabIndex >= 0 ? tabRefs.current[activeTabIndex] : null;
|
|
6759
|
-
selected?.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
6760
|
-
}, [activeTabIndex]);
|
|
6761
|
-
useEffect20(() => {
|
|
6762
|
-
if (!activeId) return;
|
|
6763
|
-
setVisitedTabs((previous) => {
|
|
6764
|
-
if (previous.has(activeId)) return previous;
|
|
6765
|
-
const next = new Set(previous);
|
|
6766
|
-
next.add(activeId);
|
|
6767
|
-
return next;
|
|
6768
|
-
});
|
|
6769
|
-
}, [activeId]);
|
|
6770
|
-
useDockLayoutEffect(() => {
|
|
6771
|
-
keepActiveTabVisible();
|
|
6772
|
-
}, [activeId, keepActiveTabVisible]);
|
|
6773
|
-
useDockLayoutEffect(() => {
|
|
6774
|
-
const list = tabListRef.current;
|
|
6775
|
-
if (!list) return;
|
|
6776
|
-
const update = () => {
|
|
6777
|
-
const max = Math.max(0, list.scrollWidth - list.clientWidth);
|
|
6778
|
-
const next = { start: list.scrollLeft > 1, end: list.scrollLeft < max - 1 };
|
|
6779
|
-
setTabOverflow(
|
|
6780
|
-
(previous) => previous.start === next.start && previous.end === next.end ? previous : next
|
|
6781
|
-
);
|
|
6782
|
-
};
|
|
6783
|
-
update();
|
|
6784
|
-
list.addEventListener("scroll", update, { passive: true });
|
|
6785
|
-
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => {
|
|
6786
|
-
keepActiveTabVisible();
|
|
6787
|
-
update();
|
|
6788
|
-
});
|
|
6789
|
-
observer?.observe(list);
|
|
6790
|
-
for (const tab of tabRefs.current) {
|
|
6791
|
-
if (tab) observer?.observe(tab);
|
|
6792
|
-
}
|
|
6793
|
-
return () => {
|
|
6794
|
-
list.removeEventListener("scroll", update);
|
|
6795
|
-
observer?.disconnect();
|
|
6796
|
-
};
|
|
6797
|
-
}, [activeId, keepActiveTabVisible, tabs.length]);
|
|
6798
|
-
const tabMask = tabOverflow.start && tabOverflow.end ? "linear-gradient(to right, transparent 0, black 14px, black calc(100% - 14px), transparent 100%)" : tabOverflow.start ? "linear-gradient(to right, transparent 0, black 14px, black 100%)" : tabOverflow.end ? "linear-gradient(to right, black 0, black calc(100% - 14px), transparent 100%)" : void 0;
|
|
6799
|
-
const activateTab = (index) => {
|
|
6800
|
-
const tab = tabs[index];
|
|
6801
|
-
if (!tab) {
|
|
6802
|
-
return;
|
|
6803
|
-
}
|
|
6804
|
-
onTab(tab.id);
|
|
6805
|
-
tabRefs.current[index]?.focus();
|
|
6806
|
-
};
|
|
6807
|
-
const onTabKeyDown = (event, index) => {
|
|
6808
|
-
if (tabs.length === 0) return;
|
|
6809
|
-
let nextIndex = null;
|
|
6810
|
-
if (event.key === "ArrowRight") nextIndex = (index + 1) % tabs.length;
|
|
6811
|
-
else if (event.key === "ArrowLeft") nextIndex = (index - 1 + tabs.length) % tabs.length;
|
|
6812
|
-
else if (event.key === "Home") nextIndex = 0;
|
|
6813
|
-
else if (event.key === "End") nextIndex = tabs.length - 1;
|
|
6814
|
-
if (nextIndex === null) return;
|
|
6815
|
-
event.preventDefault();
|
|
6816
|
-
activateTab(nextIndex);
|
|
6817
|
-
};
|
|
6818
|
-
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
6819
|
-
/* @__PURE__ */ jsxs9("div", { className: "grid shrink-0 grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-x-2 border-b border-og-border px-1.5 py-1 max-[1023px]:grid-cols-[auto_minmax(0,1fr)_auto] max-[1023px]:gap-y-0 max-[1023px]:px-2 max-[1023px]:pb-1 max-[1023px]:pt-0 min-[640px]:max-[1023px]:grid-cols-[auto_minmax(0,1fr)_auto_auto]", children: [
|
|
6820
|
-
/* @__PURE__ */ jsx11("div", { className: "flex min-w-0 shrink-0 items-center max-[1023px]:min-h-11 min-[640px]:max-[1023px]:col-start-1 min-[640px]:max-[1023px]:row-start-1", children: leading ?? /* @__PURE__ */ jsx11("span", { className: "hidden truncate px-1 text-og-sm font-semibold text-og-fg max-[1023px]:inline", children: "Workspace" }) }),
|
|
6821
|
-
/* @__PURE__ */ jsx11(
|
|
6822
|
-
"div",
|
|
6893
|
+
function InControlBar({ shared, onRelease }) {
|
|
6894
|
+
return /* @__PURE__ */ jsxs9("div", { className: "pointer-events-none absolute inset-x-0 top-0 flex items-center justify-between gap-2 p-2", children: [
|
|
6895
|
+
/* @__PURE__ */ jsxs9("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: [
|
|
6896
|
+
/* @__PURE__ */ jsx11("span", { className: "size-1.5 animate-pulse rounded-full bg-current", "aria-hidden": true }),
|
|
6897
|
+
"You're in control",
|
|
6898
|
+
/* @__PURE__ */ jsx11("span", { className: "opacity-75", children: "\xB7 click Return control (or Ctrl+Alt+Shift)" })
|
|
6899
|
+
] }),
|
|
6900
|
+
/* @__PURE__ */ jsxs9("div", { className: "pointer-events-auto flex items-center gap-1.5", children: [
|
|
6901
|
+
shared && /* @__PURE__ */ jsx11("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" }),
|
|
6902
|
+
/* @__PURE__ */ jsxs9(
|
|
6903
|
+
"button",
|
|
6823
6904
|
{
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
"
|
|
6835
|
-
|
|
6836
|
-
ref: (node) => {
|
|
6837
|
-
tabRefs.current[index] = node;
|
|
6838
|
-
},
|
|
6839
|
-
id: `${tabsetId}-tab-${index}`,
|
|
6840
|
-
type: "button",
|
|
6841
|
-
role: "tab",
|
|
6842
|
-
"aria-selected": tab.id === current,
|
|
6843
|
-
"aria-controls": `${tabsetId}-panel-${index}`,
|
|
6844
|
-
tabIndex: tab.id === current ? 0 : -1,
|
|
6845
|
-
onClick: () => onTab(tab.id),
|
|
6846
|
-
onKeyDown: (event) => onTabKeyDown(event, index),
|
|
6847
|
-
className: cn(
|
|
6848
|
-
"flex min-h-7 shrink-0 items-center justify-center gap-1 rounded-og-sm px-2 py-1 text-og-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-h-11 max-[1023px]:min-w-11 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
|
|
6849
|
-
tab.id === current ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
6850
|
-
),
|
|
6851
|
-
children: [
|
|
6852
|
-
/* @__PURE__ */ jsx11("span", { "data-contrast-audited": true, children: tab.label }),
|
|
6853
|
-
tab.badge
|
|
6854
|
-
]
|
|
6855
|
-
},
|
|
6856
|
-
tab.id
|
|
6857
|
-
))
|
|
6905
|
+
type: "button",
|
|
6906
|
+
onClick: onRelease,
|
|
6907
|
+
title: "Return control (or press Ctrl+Alt+Shift)",
|
|
6908
|
+
className: cn(
|
|
6909
|
+
"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",
|
|
6910
|
+
"border-og-accent bg-og-bg/90 text-og-fg backdrop-blur-sm",
|
|
6911
|
+
"outline-none hover:bg-og-accent hover:text-og-accent-fg focus-visible:ring-2 focus-visible:ring-og-accent"
|
|
6912
|
+
),
|
|
6913
|
+
children: [
|
|
6914
|
+
/* @__PURE__ */ jsx11(MonitorIcon, { className: "size-3.5", strokeWidth: 2, "aria-hidden": true }),
|
|
6915
|
+
"Return control"
|
|
6916
|
+
]
|
|
6858
6917
|
}
|
|
6859
|
-
)
|
|
6860
|
-
|
|
6861
|
-
|
|
6918
|
+
)
|
|
6919
|
+
] })
|
|
6920
|
+
] });
|
|
6921
|
+
}
|
|
6922
|
+
function unavailableCopy(reason) {
|
|
6923
|
+
switch (reason) {
|
|
6924
|
+
case "backend_unsupported":
|
|
6925
|
+
return "This sandbox backend cannot stream a desktop.";
|
|
6926
|
+
case "tier_headless":
|
|
6927
|
+
return "This deployment is headless \u2014 terminal, files, and diff only.";
|
|
6928
|
+
case "os_unsupported":
|
|
6929
|
+
return "The sandbox OS does not support a desktop stream.";
|
|
6930
|
+
case "not_provisioned":
|
|
6931
|
+
return "This sandbox doesn't have a desktop yet.";
|
|
6932
|
+
case "disabled_by_policy":
|
|
6933
|
+
return "Desktop streaming is disabled on this deployment.";
|
|
6934
|
+
case "lease_cold":
|
|
6935
|
+
return "Waiting for the sandbox to start\u2026";
|
|
6936
|
+
default:
|
|
6937
|
+
return "The desktop isn\u2019t available for this sandbox.";
|
|
6938
|
+
}
|
|
6939
|
+
}
|
|
6940
|
+
function WarmingNotice({ onRetry }) {
|
|
6941
|
+
return /* @__PURE__ */ jsxs9("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: [
|
|
6942
|
+
/* @__PURE__ */ jsx11(LoaderCircleIcon2, { className: "size-7 animate-og-spin text-og-accent", strokeWidth: 1.5 }),
|
|
6943
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
|
|
6944
|
+
/* @__PURE__ */ jsx11("div", { className: "font-medium", children: "Warming the sandbox\u2026" }),
|
|
6945
|
+
/* @__PURE__ */ jsx11("p", { className: "text-og-sm text-og-fg-subtle", children: "Spinning up the desktop \u2014 this takes a few seconds." })
|
|
6862
6946
|
] }),
|
|
6863
|
-
/* @__PURE__ */ jsx11(
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6947
|
+
onRetry && /* @__PURE__ */ jsx11(
|
|
6948
|
+
"button",
|
|
6949
|
+
{
|
|
6950
|
+
type: "button",
|
|
6951
|
+
onClick: onRetry,
|
|
6952
|
+
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-11",
|
|
6953
|
+
children: "Taking too long? Retry"
|
|
6954
|
+
}
|
|
6955
|
+
)
|
|
6956
|
+
] });
|
|
6957
|
+
}
|
|
6958
|
+
function DefaultConsentGate({ shared, onAccept }) {
|
|
6959
|
+
return /* @__PURE__ */ jsxs9("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: [
|
|
6960
|
+
/* @__PURE__ */ jsx11("div", { className: "mb-1 font-medium", children: "Watch the live desktop?" }),
|
|
6961
|
+
/* @__PURE__ */ jsxs9("p", { className: "mb-3 text-og-sm text-og-fg-subtle", children: [
|
|
6962
|
+
"The desktop pixel stream is ",
|
|
6963
|
+
/* @__PURE__ */ jsx11("strong", { children: "un-redacted" }),
|
|
6964
|
+
" \u2014 it can show secrets the agent prints on screen.",
|
|
6965
|
+
shared ? " This sandbox is shared: you'll also see other sessions' agents on the same screen." : ""
|
|
6966
|
+
] }),
|
|
6967
|
+
/* @__PURE__ */ jsx11(
|
|
6968
|
+
"button",
|
|
6969
|
+
{
|
|
6970
|
+
type: "button",
|
|
6971
|
+
onClick: onAccept,
|
|
6972
|
+
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-11",
|
|
6973
|
+
children: "I understand \u2014 show the desktop"
|
|
6974
|
+
}
|
|
6975
|
+
)
|
|
6976
|
+
] });
|
|
6977
|
+
}
|
|
6978
|
+
function defaultNotice(title, body, onRetry) {
|
|
6979
|
+
return /* @__PURE__ */ jsxs9("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: [
|
|
6980
|
+
/* @__PURE__ */ jsxs9("div", { className: "mb-1 flex items-center justify-center gap-1.5 font-medium", children: [
|
|
6981
|
+
onRetry && /* @__PURE__ */ jsx11(WifiOffIcon, { className: "size-4 opacity-70", strokeWidth: 1.75 }),
|
|
6982
|
+
title
|
|
6983
|
+
] }),
|
|
6984
|
+
/* @__PURE__ */ jsx11("p", { className: "text-og-sm text-og-fg-subtle", children: body }),
|
|
6985
|
+
onRetry && /* @__PURE__ */ jsx11(
|
|
6986
|
+
"button",
|
|
6987
|
+
{
|
|
6988
|
+
type: "button",
|
|
6989
|
+
onClick: onRetry,
|
|
6990
|
+
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-11",
|
|
6991
|
+
children: "Reconnect"
|
|
6992
|
+
}
|
|
6993
|
+
)
|
|
6879
6994
|
] });
|
|
6880
6995
|
}
|
|
6881
6996
|
|
|
6882
|
-
// src/components/
|
|
6883
|
-
import { useCallback as useCallback22, useEffect as useEffect23, useMemo as useMemo11, useRef as useRef20, useState as useState20 } from "react";
|
|
6884
|
-
import { Popover } from "radix-ui";
|
|
6885
|
-
import {
|
|
6886
|
-
CircleCheckIcon,
|
|
6887
|
-
CpuIcon,
|
|
6888
|
-
LaptopIcon,
|
|
6889
|
-
LoaderCircleIcon as LoaderCircleIcon3,
|
|
6890
|
-
RefreshCwIcon as RefreshCwIcon2,
|
|
6891
|
-
TriangleAlertIcon as TriangleAlertIcon2
|
|
6892
|
-
} from "lucide-react";
|
|
6893
|
-
|
|
6894
|
-
// src/components/workbench-changes.tsx
|
|
6895
|
-
import { ArrowUpRightIcon, FileWarningIcon as FileWarningIcon2, HistoryIcon } from "lucide-react";
|
|
6997
|
+
// src/components/workspace-dock.tsx
|
|
6896
6998
|
import {
|
|
6897
6999
|
useCallback as useCallback21,
|
|
6898
7000
|
useEffect as useEffect22,
|
|
6899
7001
|
useId as useId4,
|
|
6900
|
-
useLayoutEffect as useLayoutEffect3,
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
if (secBottom > top && secTop < bottom) {
|
|
6923
|
-
if (firstVisible === -1) firstVisible = i;
|
|
6924
|
-
lastVisible = i;
|
|
6925
|
-
}
|
|
6926
|
-
acc = secBottom;
|
|
6927
|
-
}
|
|
6928
|
-
if (firstVisible === -1) {
|
|
6929
|
-
firstVisible = anchor;
|
|
6930
|
-
lastVisible = anchor;
|
|
6931
|
-
}
|
|
6932
|
-
return {
|
|
6933
|
-
start: Math.max(0, firstVisible - overscan),
|
|
6934
|
-
end: Math.min(n, lastVisible + 1 + overscan)
|
|
6935
|
-
};
|
|
6936
|
-
}
|
|
6937
|
-
function useWindowedSections(opts) {
|
|
6938
|
-
const { count, estimateHeight, overscan = 3 } = opts;
|
|
6939
|
-
const scrollRef = useRef18(null);
|
|
6940
|
-
const [heights, setHeights] = useState18(
|
|
6941
|
-
() => Array.from({ length: count }, (_, i) => estimateHeight(i))
|
|
6942
|
-
);
|
|
6943
|
-
useEffect21(() => {
|
|
6944
|
-
setHeights((prev) => {
|
|
6945
|
-
if (prev.length === count) return prev;
|
|
6946
|
-
return Array.from({ length: count }, (_, i) => prev[i] ?? estimateHeight(i));
|
|
6947
|
-
});
|
|
6948
|
-
}, [count]);
|
|
6949
|
-
const heightsRef = useRef18(heights);
|
|
6950
|
-
heightsRef.current = heights;
|
|
6951
|
-
const [range, setRange] = useState18(() => ({
|
|
6952
|
-
start: 0,
|
|
6953
|
-
end: Math.min(count, overscan + 1)
|
|
6954
|
-
}));
|
|
6955
|
-
const recompute = useCallback20(() => {
|
|
6956
|
-
const el = scrollRef.current;
|
|
6957
|
-
if (!el) return;
|
|
6958
|
-
const next = computeWindowRange(heightsRef.current, el.scrollTop, el.clientHeight, overscan);
|
|
6959
|
-
setRange((prev) => prev.start === next.start && prev.end === next.end ? prev : next);
|
|
6960
|
-
}, [overscan]);
|
|
6961
|
-
useEffect21(() => {
|
|
6962
|
-
const el = scrollRef.current;
|
|
6963
|
-
if (!el) return;
|
|
6964
|
-
let raf = 0;
|
|
6965
|
-
const onScroll = () => {
|
|
6966
|
-
if (raf) return;
|
|
6967
|
-
raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame(() => {
|
|
6968
|
-
raf = 0;
|
|
6969
|
-
recompute();
|
|
6970
|
-
}) : (recompute(), 0);
|
|
6971
|
-
};
|
|
6972
|
-
el.addEventListener("scroll", onScroll, { passive: true });
|
|
6973
|
-
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => recompute()) : null;
|
|
6974
|
-
ro?.observe(el);
|
|
6975
|
-
recompute();
|
|
6976
|
-
return () => {
|
|
6977
|
-
el.removeEventListener("scroll", onScroll);
|
|
6978
|
-
ro?.disconnect();
|
|
6979
|
-
if (raf && typeof cancelAnimationFrame === "function") cancelAnimationFrame(raf);
|
|
6980
|
-
};
|
|
6981
|
-
}, [recompute, count]);
|
|
6982
|
-
const measure = useCallback20((index, height) => {
|
|
6983
|
-
if (height <= 0) return;
|
|
6984
|
-
setHeights((prev) => {
|
|
6985
|
-
if (Math.abs((prev[index] ?? 0) - height) < 1) return prev;
|
|
6986
|
-
const next = prev.slice();
|
|
6987
|
-
next[index] = height;
|
|
6988
|
-
return next;
|
|
6989
|
-
});
|
|
6990
|
-
}, []);
|
|
6991
|
-
const offsets = useMemo9(() => {
|
|
6992
|
-
const out = new Array(count + 1);
|
|
6993
|
-
out[0] = 0;
|
|
6994
|
-
for (let i = 0; i < count; i++) out[i + 1] = (out[i] ?? 0) + Math.max(heights[i] ?? 0, 0);
|
|
6995
|
-
return out;
|
|
6996
|
-
}, [heights, count]);
|
|
6997
|
-
useEffect21(() => {
|
|
6998
|
-
recompute();
|
|
6999
|
-
}, [offsets, recompute]);
|
|
7000
|
-
const scrollToIndex = useCallback20(
|
|
7001
|
-
(index) => {
|
|
7002
|
-
const el = scrollRef.current;
|
|
7003
|
-
if (!el) return;
|
|
7004
|
-
const clamped = Math.max(0, Math.min(count - 1, index));
|
|
7005
|
-
el.scrollTop = offsets[clamped] ?? 0;
|
|
7006
|
-
},
|
|
7007
|
-
[offsets, count]
|
|
7008
|
-
);
|
|
7009
|
-
return {
|
|
7010
|
-
scrollRef,
|
|
7011
|
-
range,
|
|
7012
|
-
offsets,
|
|
7013
|
-
totalHeight: offsets[count] ?? 0,
|
|
7014
|
-
measure,
|
|
7015
|
-
scrollToIndex
|
|
7016
|
-
};
|
|
7017
|
-
}
|
|
7018
|
-
|
|
7019
|
-
// src/components/workbench-changes.tsx
|
|
7020
|
-
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
7021
|
-
var GROUP_THRESHOLD = 20;
|
|
7022
|
-
var OVERSCAN = 2;
|
|
7023
|
-
var HEADER_PX = 30;
|
|
7024
|
-
var LINE_PX = 18;
|
|
7025
|
-
var GUARD_BODY_PX = 52;
|
|
7026
|
-
var COMPACT_SURFACE_PX = 560;
|
|
7027
|
-
var useChangesLayoutEffect = typeof window === "undefined" ? useEffect22 : useLayoutEffect3;
|
|
7028
|
-
var STATUS_TINT2 = {
|
|
7029
|
-
added: "text-og-status-idle",
|
|
7030
|
-
modified: "text-og-status-running",
|
|
7031
|
-
deleted: "text-og-status-failed",
|
|
7032
|
-
renamed: "text-og-accent",
|
|
7033
|
-
copied: "text-og-accent",
|
|
7034
|
-
untracked: "text-og-fg-subtle",
|
|
7035
|
-
ignored: "text-og-fg-subtle",
|
|
7036
|
-
conflicted: "text-og-status-failed",
|
|
7037
|
-
typechange: "text-og-status-running"
|
|
7038
|
-
};
|
|
7039
|
-
var STATUS_LETTER = {
|
|
7040
|
-
added: "A",
|
|
7041
|
-
modified: "M",
|
|
7042
|
-
deleted: "D",
|
|
7043
|
-
renamed: "R",
|
|
7044
|
-
copied: "C",
|
|
7045
|
-
untracked: "U",
|
|
7046
|
-
ignored: "I",
|
|
7047
|
-
conflicted: "!",
|
|
7048
|
-
typechange: "T"
|
|
7049
|
-
};
|
|
7050
|
-
function compactFileLabel(file) {
|
|
7051
|
-
const slash = file.path.lastIndexOf("/");
|
|
7052
|
-
const basename = slash >= 0 ? file.path.slice(slash + 1) : file.path;
|
|
7053
|
-
const parent = slash >= 0 ? file.path.slice(0, slash + 1) : "";
|
|
7054
|
-
return `${STATUS_LETTER[file.status]} \xB7 ${basename}${parent ? ` \u2014 ${parent}` : ""}`;
|
|
7055
|
-
}
|
|
7056
|
-
function buildRail(files) {
|
|
7057
|
-
const roots = new Set(
|
|
7058
|
-
files.flatMap((file) => file.repoRoot === void 0 ? [] : [file.repoRoot])
|
|
7059
|
-
);
|
|
7060
|
-
const groupByRepo = roots.size > 1;
|
|
7061
|
-
if (!groupByRepo && files.length <= GROUP_THRESHOLD) {
|
|
7062
|
-
return {
|
|
7063
|
-
orderedFiles: files,
|
|
7064
|
-
rows: files.map((file, index) => ({ kind: "file", file, index })),
|
|
7065
|
-
grouped: false
|
|
7066
|
-
};
|
|
7067
|
-
}
|
|
7068
|
-
const groups = /* @__PURE__ */ new Map();
|
|
7069
|
-
for (const file of files) {
|
|
7070
|
-
const slash = file.path.indexOf("/");
|
|
7071
|
-
const key = groupByRepo ? file.repoRoot || "(workspace)" : slash > 0 ? file.path.slice(0, slash) : "(root)";
|
|
7072
|
-
const bucket = groups.get(key);
|
|
7073
|
-
if (bucket) bucket.push(file);
|
|
7074
|
-
else groups.set(key, [file]);
|
|
7002
|
+
useLayoutEffect as useLayoutEffect3,
|
|
7003
|
+
useRef as useRef19,
|
|
7004
|
+
useState as useState19
|
|
7005
|
+
} from "react";
|
|
7006
|
+
import {
|
|
7007
|
+
ChevronsLeftRightIcon,
|
|
7008
|
+
Maximize2Icon,
|
|
7009
|
+
Minimize2Icon,
|
|
7010
|
+
PanelRightCloseIcon,
|
|
7011
|
+
XIcon as XIcon2
|
|
7012
|
+
} from "lucide-react";
|
|
7013
|
+
import {
|
|
7014
|
+
Group,
|
|
7015
|
+
Panel,
|
|
7016
|
+
Separator,
|
|
7017
|
+
useDefaultLayout,
|
|
7018
|
+
usePanelRef
|
|
7019
|
+
} from "react-resizable-panels";
|
|
7020
|
+
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
7021
|
+
var SERVER_LAYOUT_STORAGE = {
|
|
7022
|
+
getItem: () => null,
|
|
7023
|
+
setItem: () => {
|
|
7075
7024
|
}
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
rows.push({ kind: "file", file, index: orderedFiles.length });
|
|
7084
|
-
orderedFiles.push(file);
|
|
7085
|
-
}
|
|
7025
|
+
};
|
|
7026
|
+
function getLayoutStorage() {
|
|
7027
|
+
if (typeof window === "undefined") return SERVER_LAYOUT_STORAGE;
|
|
7028
|
+
try {
|
|
7029
|
+
return window.localStorage;
|
|
7030
|
+
} catch {
|
|
7031
|
+
return SERVER_LAYOUT_STORAGE;
|
|
7086
7032
|
}
|
|
7087
|
-
return { orderedFiles, rows, grouped: true };
|
|
7088
|
-
}
|
|
7089
|
-
function isGuarded(file) {
|
|
7090
|
-
return file.isBinary || file.truncated;
|
|
7091
7033
|
}
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7034
|
+
var useDockLayoutEffect = typeof window === "undefined" ? useEffect22 : useLayoutEffect3;
|
|
7035
|
+
var DOCK_OVERLAY_BREAKPOINT = 1024;
|
|
7036
|
+
function useIsNarrow(maxWidth) {
|
|
7037
|
+
const [narrow, setNarrow] = useState19(false);
|
|
7038
|
+
useDockLayoutEffect(() => {
|
|
7039
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7040
|
+
return;
|
|
7041
|
+
}
|
|
7042
|
+
const mql = window.matchMedia(`(max-width: ${maxWidth - 1}px)`);
|
|
7043
|
+
const update = () => setNarrow(mql.matches);
|
|
7044
|
+
update();
|
|
7045
|
+
if (typeof mql.addEventListener === "function") {
|
|
7046
|
+
mql.addEventListener("change", update);
|
|
7047
|
+
return () => mql.removeEventListener("change", update);
|
|
7048
|
+
}
|
|
7049
|
+
mql.addListener(update);
|
|
7050
|
+
return () => mql.removeListener(update);
|
|
7051
|
+
}, [maxWidth]);
|
|
7052
|
+
return narrow;
|
|
7097
7053
|
}
|
|
7098
|
-
function
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7054
|
+
function WorkspaceDock({
|
|
7055
|
+
primary,
|
|
7056
|
+
tabs,
|
|
7057
|
+
activeTab,
|
|
7058
|
+
onActiveTabChange,
|
|
7059
|
+
collapsed: collapsedProp,
|
|
7060
|
+
onCollapsedChange,
|
|
7061
|
+
headerAccessory,
|
|
7062
|
+
mobileLeadingControl,
|
|
7063
|
+
autoSaveId = "og.session.dock",
|
|
7064
|
+
defaultSize = 34,
|
|
7065
|
+
minSize = 22,
|
|
7066
|
+
maxSize = 70,
|
|
7105
7067
|
className
|
|
7106
7068
|
}) {
|
|
7069
|
+
const narrow = useIsNarrow(DOCK_OVERLAY_BREAKPOINT);
|
|
7107
7070
|
const rootRef = useRef19(null);
|
|
7108
|
-
const
|
|
7109
|
-
const
|
|
7110
|
-
const
|
|
7111
|
-
const
|
|
7112
|
-
const [
|
|
7113
|
-
const
|
|
7114
|
-
const
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
);
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
observer.observe(root);
|
|
7133
|
-
return () => observer.disconnect();
|
|
7134
|
-
}, []);
|
|
7135
|
-
useChangesLayoutEffect(() => {
|
|
7136
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
7137
|
-
const query = window.matchMedia("(pointer: coarse)");
|
|
7138
|
-
const update = () => setCoarsePointer(query.matches);
|
|
7139
|
-
update();
|
|
7140
|
-
if (typeof query.addEventListener === "function") {
|
|
7141
|
-
query.addEventListener("change", update);
|
|
7142
|
-
return () => query.removeEventListener("change", update);
|
|
7143
|
-
}
|
|
7144
|
-
if (typeof query.addListener === "function") {
|
|
7145
|
-
query.addListener(update);
|
|
7146
|
-
return () => query.removeListener(update);
|
|
7147
|
-
}
|
|
7148
|
-
}, []);
|
|
7149
|
-
const additions = useMemo10(() => diff.reduce((sum, f) => sum + f.additions, 0), [diff]);
|
|
7150
|
-
const deletions = useMemo10(() => diff.reduce((sum, f) => sum + f.deletions, 0), [diff]);
|
|
7151
|
-
const estimateHeight = useCallback21(
|
|
7152
|
-
(index) => {
|
|
7153
|
-
const file = orderedFiles[index];
|
|
7154
|
-
return file ? estimateSectionHeight(file) : HEADER_PX + LINE_PX;
|
|
7071
|
+
const reopenRef = useRef19(null);
|
|
7072
|
+
const returnFocusRef = useRef19(null);
|
|
7073
|
+
const initialNarrowFocusRef = useRef19(false);
|
|
7074
|
+
const dockPanelRef = usePanelRef();
|
|
7075
|
+
const [internalCollapsed, setInternalCollapsed] = useState19(false);
|
|
7076
|
+
const [maximized, setMaximized] = useState19(false);
|
|
7077
|
+
const [internalTab, setInternalTab] = useState19(tabs[0]?.id ?? "");
|
|
7078
|
+
const collapsed = collapsedProp ?? internalCollapsed;
|
|
7079
|
+
const hostControlled = collapsedProp !== void 0;
|
|
7080
|
+
const previousCollapsedRef = useRef19(collapsed);
|
|
7081
|
+
const { defaultLayout, onLayoutChanged } = useDefaultLayout({
|
|
7082
|
+
panelIds: ["primary", "dock"],
|
|
7083
|
+
storage: getLayoutStorage(),
|
|
7084
|
+
id: autoSaveId
|
|
7085
|
+
});
|
|
7086
|
+
const requestedTab = activeTab ?? internalTab;
|
|
7087
|
+
const tabIds = tabs.map((tab) => tab.id);
|
|
7088
|
+
const firstTabId = tabs[0]?.id ?? "";
|
|
7089
|
+
const requestedTabIsValid = tabIds.includes(requestedTab);
|
|
7090
|
+
const current = requestedTabIsValid ? requestedTab : firstTabId;
|
|
7091
|
+
const setTab = useCallback21(
|
|
7092
|
+
(id) => {
|
|
7093
|
+
setInternalTab(id);
|
|
7094
|
+
onActiveTabChange?.(id);
|
|
7155
7095
|
},
|
|
7156
|
-
[
|
|
7096
|
+
[onActiveTabChange]
|
|
7157
7097
|
);
|
|
7158
|
-
const
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
});
|
|
7163
|
-
const jumpTo = useCallback21(
|
|
7164
|
-
(index) => {
|
|
7165
|
-
setActivePath(orderedFiles[index]?.path ?? null);
|
|
7166
|
-
windowed.scrollToIndex(index);
|
|
7098
|
+
const setCollapsed = useCallback21(
|
|
7099
|
+
(next) => {
|
|
7100
|
+
setInternalCollapsed((previous) => previous === next ? previous : next);
|
|
7101
|
+
onCollapsedChange?.(next);
|
|
7167
7102
|
},
|
|
7168
|
-
[
|
|
7103
|
+
[onCollapsedChange]
|
|
7169
7104
|
);
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
if (!el) {
|
|
7105
|
+
useDockLayoutEffect(() => {
|
|
7106
|
+
if (collapsedProp === void 0) {
|
|
7173
7107
|
return;
|
|
7174
7108
|
}
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
else break;
|
|
7109
|
+
if (collapsedProp) {
|
|
7110
|
+
dockPanelRef.current?.collapse();
|
|
7111
|
+
setMaximized(false);
|
|
7112
|
+
} else {
|
|
7113
|
+
dockPanelRef.current?.expand();
|
|
7181
7114
|
}
|
|
7182
|
-
|
|
7183
|
-
setActivePath((previous) => previous === nextPath ? previous : nextPath);
|
|
7184
|
-
}, [windowed, orderedFiles]);
|
|
7115
|
+
}, [collapsedProp, dockPanelRef]);
|
|
7185
7116
|
useEffect22(() => {
|
|
7186
|
-
const
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7117
|
+
const previous = previousCollapsedRef.current;
|
|
7118
|
+
previousCollapsedRef.current = collapsed;
|
|
7119
|
+
if (previous === collapsed) return;
|
|
7120
|
+
if (!collapsed) {
|
|
7121
|
+
const active = document.activeElement;
|
|
7122
|
+
const workspaceSurface = rootRef.current?.querySelector(
|
|
7123
|
+
narrow ? '[role="dialog"]' : "[data-workspace-surface]"
|
|
7124
|
+
);
|
|
7125
|
+
if (active instanceof HTMLElement && !workspaceSurface?.contains(active)) {
|
|
7126
|
+
returnFocusRef.current = active;
|
|
7127
|
+
}
|
|
7128
|
+
if (narrow) {
|
|
7129
|
+
const frame2 = requestAnimationFrame(() => {
|
|
7130
|
+
rootRef.current?.querySelector('[role="dialog"] [role="tab"][aria-selected="true"]')?.focus();
|
|
7131
|
+
});
|
|
7132
|
+
return () => cancelAnimationFrame(frame2);
|
|
7133
|
+
}
|
|
7134
|
+
return;
|
|
7135
|
+
}
|
|
7136
|
+
const frame = requestAnimationFrame(() => {
|
|
7137
|
+
if (!hostControlled) {
|
|
7138
|
+
reopenRef.current?.focus();
|
|
7139
|
+
return;
|
|
7140
|
+
}
|
|
7141
|
+
const target = returnFocusRef.current;
|
|
7142
|
+
if (target?.isConnected) target.focus();
|
|
7143
|
+
});
|
|
7144
|
+
return () => cancelAnimationFrame(frame);
|
|
7145
|
+
}, [collapsed, hostControlled, narrow]);
|
|
7146
|
+
useEffect22(() => {
|
|
7147
|
+
if (!narrow || collapsed || initialNarrowFocusRef.current) return;
|
|
7148
|
+
initialNarrowFocusRef.current = true;
|
|
7149
|
+
const active = document.activeElement;
|
|
7150
|
+
const workspaceSurface = rootRef.current?.querySelector('[role="dialog"]');
|
|
7151
|
+
if (active instanceof HTMLElement && !workspaceSurface?.contains(active)) {
|
|
7152
|
+
returnFocusRef.current = active;
|
|
7153
|
+
}
|
|
7154
|
+
const frame = requestAnimationFrame(() => {
|
|
7155
|
+
workspaceSurface?.querySelector('[role="tab"][aria-selected="true"]')?.focus();
|
|
7156
|
+
});
|
|
7157
|
+
return () => cancelAnimationFrame(frame);
|
|
7158
|
+
}, [collapsed, narrow]);
|
|
7159
|
+
useEffect22(() => {
|
|
7160
|
+
if (firstTabId && !requestedTabIsValid) {
|
|
7161
|
+
setTab(firstTabId);
|
|
7162
|
+
}
|
|
7163
|
+
}, [firstTabId, requestedTabIsValid, setTab]);
|
|
7164
|
+
const collapse = useCallback21(() => {
|
|
7165
|
+
dockPanelRef.current?.collapse();
|
|
7166
|
+
setCollapsed(true);
|
|
7167
|
+
}, [dockPanelRef, setCollapsed]);
|
|
7168
|
+
const expand = useCallback21(() => {
|
|
7169
|
+
dockPanelRef.current?.expand();
|
|
7170
|
+
setCollapsed(false);
|
|
7171
|
+
}, [dockPanelRef, setCollapsed]);
|
|
7172
|
+
useEffect22(() => {
|
|
7173
|
+
const overlayOpen = maximized || narrow && !collapsed;
|
|
7174
|
+
if (!overlayOpen) return;
|
|
7175
|
+
const onKey = (event) => {
|
|
7176
|
+
if (event.key === "Escape") {
|
|
7177
|
+
if (maximized) setMaximized(false);
|
|
7178
|
+
else collapse();
|
|
7179
|
+
return;
|
|
7180
|
+
}
|
|
7181
|
+
if (event.key !== "Tab") return;
|
|
7182
|
+
const surface = rootRef.current?.querySelector(
|
|
7183
|
+
narrow ? '[role="dialog"]' : "[data-workspace-surface]"
|
|
7184
|
+
);
|
|
7185
|
+
if (!surface) return;
|
|
7186
|
+
const focusable = Array.from(surface.querySelectorAll("*")).filter(
|
|
7187
|
+
(element) => element.tabIndex >= 0 && !element.hasAttribute("disabled") && element.getClientRects().length > 0 && getComputedStyle(element).visibility !== "hidden"
|
|
7188
|
+
);
|
|
7189
|
+
const first = focusable[0];
|
|
7190
|
+
const last = focusable.at(-1);
|
|
7191
|
+
const active = document.activeElement;
|
|
7192
|
+
if (!first || !last) {
|
|
7193
|
+
event.preventDefault();
|
|
7194
|
+
surface.focus();
|
|
7195
|
+
return;
|
|
7196
|
+
}
|
|
7197
|
+
if (!surface.contains(active)) {
|
|
7198
|
+
event.preventDefault();
|
|
7199
|
+
(event.shiftKey ? last : first).focus();
|
|
7200
|
+
return;
|
|
7201
|
+
}
|
|
7202
|
+
if (event.shiftKey && active === first || !event.shiftKey && active === last) {
|
|
7203
|
+
event.preventDefault();
|
|
7204
|
+
(event.shiftKey ? last : first).focus();
|
|
7205
|
+
return;
|
|
7206
|
+
}
|
|
7207
|
+
requestAnimationFrame(() => {
|
|
7208
|
+
const next = document.activeElement;
|
|
7209
|
+
if (!surface.contains(next)) (event.shiftKey ? last : first).focus();
|
|
7210
|
+
});
|
|
7211
|
+
};
|
|
7212
|
+
window.addEventListener("keydown", onKey);
|
|
7213
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
7214
|
+
}, [maximized, narrow, collapsed, collapse]);
|
|
7215
|
+
if (narrow) {
|
|
7216
|
+
return /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: cn("relative flex h-full min-h-0 w-full min-w-0", className), children: [
|
|
7217
|
+
/* @__PURE__ */ jsx12(
|
|
7218
|
+
"div",
|
|
7219
|
+
{
|
|
7220
|
+
"data-workspace-primary": true,
|
|
7221
|
+
"aria-hidden": !collapsed ? true : void 0,
|
|
7222
|
+
className: "min-h-0 min-w-0 flex-1",
|
|
7223
|
+
inert: !collapsed ? true : void 0,
|
|
7224
|
+
children: primary
|
|
7225
|
+
}
|
|
7226
|
+
),
|
|
7227
|
+
/* @__PURE__ */ jsx12(
|
|
7228
|
+
"div",
|
|
7229
|
+
{
|
|
7230
|
+
"data-workspace-surface": true,
|
|
7231
|
+
role: "dialog",
|
|
7232
|
+
"aria-modal": "true",
|
|
7233
|
+
"aria-label": "Workspace",
|
|
7234
|
+
className: "fixed inset-0 z-40 flex flex-col bg-og-bg",
|
|
7235
|
+
hidden: collapsed,
|
|
7236
|
+
style: {
|
|
7237
|
+
paddingTop: "env(safe-area-inset-top)",
|
|
7238
|
+
paddingBottom: "env(safe-area-inset-bottom)"
|
|
7239
|
+
},
|
|
7240
|
+
children: /* @__PURE__ */ jsx12(
|
|
7241
|
+
DockChrome,
|
|
7242
|
+
{
|
|
7243
|
+
tabs,
|
|
7244
|
+
current,
|
|
7245
|
+
onTab: setTab,
|
|
7246
|
+
leading: mobileLeadingControl,
|
|
7247
|
+
accessory: headerAccessory,
|
|
7248
|
+
controls: /* @__PURE__ */ jsx12(ChromeButton, { onClick: collapse, title: "Close workspace", label: "Close workspace", children: /* @__PURE__ */ jsx12(XIcon2, { className: "size-4" }) })
|
|
7249
|
+
}
|
|
7250
|
+
)
|
|
7251
|
+
}
|
|
7252
|
+
),
|
|
7253
|
+
collapsed && !hostControlled ? /* @__PURE__ */ jsx12(
|
|
7254
|
+
"button",
|
|
7255
|
+
{
|
|
7256
|
+
ref: reopenRef,
|
|
7257
|
+
type: "button",
|
|
7258
|
+
onClick: expand,
|
|
7259
|
+
title: "Open workspace",
|
|
7260
|
+
"aria-label": "Open workspace",
|
|
7261
|
+
className: "absolute right-3 top-3 z-30 inline-flex size-11 items-center justify-center rounded-og-md border border-og-border bg-og-surface-1 text-og-fg-muted shadow-lg transition-colors hover:border-og-border-strong hover:text-og-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent",
|
|
7262
|
+
style: { marginTop: "env(safe-area-inset-top)" },
|
|
7263
|
+
children: /* @__PURE__ */ jsx12(ChevronsLeftRightIcon, { className: "size-4", "aria-hidden": true })
|
|
7264
|
+
}
|
|
7265
|
+
) : null
|
|
7266
|
+
] });
|
|
7267
|
+
}
|
|
7268
|
+
const dockChrome = /* @__PURE__ */ jsx12(
|
|
7269
|
+
DockChrome,
|
|
7195
7270
|
{
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7271
|
+
tabs,
|
|
7272
|
+
current,
|
|
7273
|
+
onTab: setTab,
|
|
7274
|
+
accessory: headerAccessory,
|
|
7275
|
+
controls: /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
7276
|
+
/* @__PURE__ */ jsx12(
|
|
7277
|
+
ChromeButton,
|
|
7202
7278
|
{
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
),
|
|
7207
|
-
children: [
|
|
7208
|
-
/* @__PURE__ */ jsxs10(
|
|
7209
|
-
"span",
|
|
7210
|
-
{
|
|
7211
|
-
role: "status",
|
|
7212
|
-
"aria-atomic": "true",
|
|
7213
|
-
"aria-live": "polite",
|
|
7214
|
-
"data-contrast-audited": true,
|
|
7215
|
-
className: "min-w-0 text-og-xs text-og-fg-muted",
|
|
7216
|
-
children: [
|
|
7217
|
-
diff.length,
|
|
7218
|
-
" ",
|
|
7219
|
-
diff.length === 1 ? "file" : "files",
|
|
7220
|
-
" changed",
|
|
7221
|
-
/* @__PURE__ */ jsxs10("span", { "data-contrast-audited": true, className: "ml-2 text-og-status-idle", children: [
|
|
7222
|
-
"+",
|
|
7223
|
-
additions
|
|
7224
|
-
] }),
|
|
7225
|
-
/* @__PURE__ */ jsxs10("span", { "data-contrast-audited": true, className: "ml-1 text-og-status-failed", children: [
|
|
7226
|
-
"\u2212",
|
|
7227
|
-
deletions
|
|
7228
|
-
] })
|
|
7229
|
-
]
|
|
7230
|
-
}
|
|
7231
|
-
),
|
|
7232
|
-
/* @__PURE__ */ jsxs10(
|
|
7233
|
-
"div",
|
|
7234
|
-
{
|
|
7235
|
-
className: cn(
|
|
7236
|
-
"flex shrink-0 items-center gap-2",
|
|
7237
|
-
compact && source === "capture" && "self-start"
|
|
7238
|
-
),
|
|
7239
|
-
children: [
|
|
7240
|
-
compact ? null : /* @__PURE__ */ jsx12(LayoutToggle, { layout, onChange: setLayout }),
|
|
7241
|
-
/* @__PURE__ */ jsx12(SourceBadge, { source, capturedAt, label: sourceBadge })
|
|
7242
|
-
]
|
|
7243
|
-
}
|
|
7244
|
-
)
|
|
7245
|
-
]
|
|
7279
|
+
onClick: () => setMaximized((m) => !m),
|
|
7280
|
+
title: maximized ? "Restore (Esc)" : "Maximize",
|
|
7281
|
+
label: maximized ? "Restore dock" : "Maximize dock",
|
|
7282
|
+
children: maximized ? /* @__PURE__ */ jsx12(Minimize2Icon, { className: "size-3.5" }) : /* @__PURE__ */ jsx12(Maximize2Icon, { className: "size-3.5" })
|
|
7246
7283
|
}
|
|
7247
7284
|
),
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
className: "h-11 w-full rounded-og-md border border-og-border bg-og-bg px-3 font-og-mono text-og-sm text-og-fg outline-none transition-colors focus:border-og-accent focus:ring-2 focus:ring-og-accent-soft",
|
|
7264
|
-
children: orderedFiles.map((file, index) => /* @__PURE__ */ jsx12("option", { value: index, children: compactFileLabel(file) }, file.path))
|
|
7265
|
-
}
|
|
7266
|
-
)
|
|
7267
|
-
] }),
|
|
7268
|
-
/* @__PURE__ */ jsx12("div", { className: "min-h-0 min-w-0 flex-1 overflow-auto", "data-opengeni-changes-pane": true, children: activeFile ? /* @__PURE__ */ jsx12(
|
|
7269
|
-
DiffSection,
|
|
7270
|
-
{
|
|
7271
|
-
file: activeFile,
|
|
7272
|
-
layout: "unified",
|
|
7273
|
-
themeType: resolvedTheme,
|
|
7274
|
-
...onOpenFile ? { onOpenFile } : {}
|
|
7275
|
-
}
|
|
7276
|
-
) : null })
|
|
7277
|
-
] }) : /* @__PURE__ */ jsxs10("div", { className: "flex min-h-0 flex-1", children: [
|
|
7278
|
-
/* @__PURE__ */ jsx12("div", { className: "w-[clamp(12rem,28%,15rem)] shrink-0 border-r border-og-border bg-og-surface-1/35", children: /* @__PURE__ */ jsx12(
|
|
7279
|
-
VList2,
|
|
7285
|
+
hostControlled ? null : /* @__PURE__ */ jsx12(ChromeButton, { onClick: collapse, title: "Collapse", label: "Collapse dock", children: /* @__PURE__ */ jsx12(PanelRightCloseIcon, { className: "size-3.5" }) })
|
|
7286
|
+
] })
|
|
7287
|
+
}
|
|
7288
|
+
);
|
|
7289
|
+
return /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: cn("relative flex h-full min-h-0 w-full min-w-0", className), children: [
|
|
7290
|
+
/* @__PURE__ */ jsxs10(
|
|
7291
|
+
Group,
|
|
7292
|
+
{
|
|
7293
|
+
orientation: "horizontal",
|
|
7294
|
+
className: "min-h-0 flex-1",
|
|
7295
|
+
...defaultLayout ? { defaultLayout } : {},
|
|
7296
|
+
onLayoutChanged,
|
|
7297
|
+
children: [
|
|
7298
|
+
/* @__PURE__ */ jsx12(Panel, { id: "primary", minSize: "30%", className: "min-h-0 min-w-0", children: /* @__PURE__ */ jsx12(
|
|
7299
|
+
"div",
|
|
7280
7300
|
{
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
"div",
|
|
7287
|
-
{
|
|
7288
|
-
"data-rail-group": true,
|
|
7289
|
-
className: "flex items-center gap-1.5 px-2 pb-0.5 pt-2 text-og-xs font-medium uppercase tracking-wide text-og-fg-subtle",
|
|
7290
|
-
children: [
|
|
7291
|
-
/* @__PURE__ */ jsx12("span", { className: "min-w-0 truncate", children: row.label }),
|
|
7292
|
-
/* @__PURE__ */ jsx12("span", { className: "shrink-0", children: row.count })
|
|
7293
|
-
]
|
|
7294
|
-
},
|
|
7295
|
-
`g:${row.label}`
|
|
7296
|
-
) : /* @__PURE__ */ jsx12(
|
|
7297
|
-
RailFileRow,
|
|
7298
|
-
{
|
|
7299
|
-
file: row.file,
|
|
7300
|
-
grouped,
|
|
7301
|
-
active: row.index === activeIndex,
|
|
7302
|
-
onClick: () => jumpTo(row.index)
|
|
7303
|
-
},
|
|
7304
|
-
row.file.path
|
|
7305
|
-
)
|
|
7306
|
-
)
|
|
7301
|
+
"data-workspace-primary": true,
|
|
7302
|
+
"aria-hidden": maximized ? true : void 0,
|
|
7303
|
+
className: "h-full min-h-0 min-w-0",
|
|
7304
|
+
inert: maximized ? true : void 0,
|
|
7305
|
+
children: primary
|
|
7307
7306
|
}
|
|
7308
7307
|
) }),
|
|
7308
|
+
!collapsed && /* @__PURE__ */ jsx12(Separator, { className: "group relative z-10 w-1.5 shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent max-[1023px]:-mx-[19px] max-[1023px]:w-11 pointer-coarse:-mx-[19px] pointer-coarse:w-11", children: /* @__PURE__ */ jsx12("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-focus-visible:bg-og-accent group-data-[separator-state=dragging]:bg-og-accent" }) }),
|
|
7309
7309
|
/* @__PURE__ */ jsx12(
|
|
7310
|
-
|
|
7310
|
+
Panel,
|
|
7311
7311
|
{
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7312
|
+
id: "dock",
|
|
7313
|
+
panelRef: dockPanelRef,
|
|
7314
|
+
collapsible: true,
|
|
7315
|
+
collapsedSize: "0%",
|
|
7316
|
+
defaultSize: `${defaultSize}%`,
|
|
7317
|
+
minSize: `${minSize}%`,
|
|
7318
|
+
maxSize: `${maxSize}%`,
|
|
7319
|
+
onResize: (size, _id, previousSize) => {
|
|
7320
|
+
const isCollapsed = size.asPercentage <= 1;
|
|
7321
|
+
const canInferCollapse = collapsedProp === void 0 || previousSize !== void 0;
|
|
7322
|
+
if (canInferCollapse && isCollapsed !== collapsed) {
|
|
7323
|
+
setCollapsed(isCollapsed);
|
|
7324
|
+
}
|
|
7325
|
+
},
|
|
7326
|
+
className: "min-h-0 min-w-0",
|
|
7327
|
+
children: /* @__PURE__ */ jsx12(
|
|
7328
|
+
"div",
|
|
7329
|
+
{
|
|
7330
|
+
"data-workspace-surface": true,
|
|
7331
|
+
role: maximized ? "dialog" : void 0,
|
|
7332
|
+
"aria-modal": maximized ? true : void 0,
|
|
7333
|
+
"aria-label": maximized ? "Workspace" : void 0,
|
|
7334
|
+
"aria-hidden": collapsed ? true : void 0,
|
|
7335
|
+
className: cn(
|
|
7336
|
+
"flex h-full min-h-0 min-w-0 flex-col bg-og-bg",
|
|
7337
|
+
maximized ? "fixed inset-0 z-40" : "border-l border-og-border",
|
|
7338
|
+
collapsed && "invisible pointer-events-none"
|
|
7339
|
+
),
|
|
7340
|
+
children: dockChrome
|
|
7341
|
+
}
|
|
7342
|
+
)
|
|
7336
7343
|
}
|
|
7337
7344
|
)
|
|
7338
|
-
] })
|
|
7339
|
-
]
|
|
7340
|
-
}
|
|
7341
|
-
);
|
|
7342
|
-
}
|
|
7343
|
-
function SourceBadge({
|
|
7344
|
-
source,
|
|
7345
|
-
capturedAt,
|
|
7346
|
-
label
|
|
7347
|
-
}) {
|
|
7348
|
-
if (source === "capture" && capturedAt) {
|
|
7349
|
-
return /* @__PURE__ */ jsxs10(
|
|
7350
|
-
"span",
|
|
7351
|
-
{
|
|
7352
|
-
className: "inline-flex items-center gap-1 rounded-og-xs border border-og-border px-1.5 py-px text-og-xs text-og-fg-muted",
|
|
7353
|
-
title: new Date(capturedAt).toLocaleString(),
|
|
7354
|
-
children: [
|
|
7355
|
-
/* @__PURE__ */ jsx12(HistoryIcon, { className: "size-3 shrink-0 text-og-status-running", "aria-hidden": true }),
|
|
7356
|
-
label
|
|
7357
7345
|
]
|
|
7358
7346
|
}
|
|
7359
|
-
)
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7347
|
+
),
|
|
7348
|
+
collapsed && !maximized && !hostControlled && /* @__PURE__ */ jsx12(
|
|
7349
|
+
"button",
|
|
7350
|
+
{
|
|
7351
|
+
ref: reopenRef,
|
|
7352
|
+
type: "button",
|
|
7353
|
+
onClick: expand,
|
|
7354
|
+
title: "Open workspace",
|
|
7355
|
+
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",
|
|
7356
|
+
children: /* @__PURE__ */ jsx12(ChevronsLeftRightIcon, { className: "size-3.5" })
|
|
7357
|
+
}
|
|
7358
|
+
)
|
|
7359
|
+
] });
|
|
7367
7360
|
}
|
|
7368
|
-
function
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7361
|
+
function ChromeButton({
|
|
7362
|
+
onClick,
|
|
7363
|
+
title,
|
|
7364
|
+
label,
|
|
7365
|
+
children
|
|
7373
7366
|
}) {
|
|
7374
|
-
|
|
7375
|
-
const shown = grouped ? file.repoRoot !== void 0 ? repoPrefix && file.path.startsWith(repoPrefix) ? file.path.slice(repoPrefix.length) : file.path : file.path.slice(file.path.indexOf("/") + 1) || file.path : file.path;
|
|
7376
|
-
return /* @__PURE__ */ jsxs10(
|
|
7367
|
+
return /* @__PURE__ */ jsx12(
|
|
7377
7368
|
"button",
|
|
7378
7369
|
{
|
|
7379
7370
|
type: "button",
|
|
7380
7371
|
onClick,
|
|
7381
|
-
title
|
|
7382
|
-
"
|
|
7383
|
-
className:
|
|
7384
|
-
|
|
7385
|
-
grouped && "pl-3",
|
|
7386
|
-
active && "bg-og-accent-soft text-og-fg before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-r-full before:bg-og-accent"
|
|
7387
|
-
),
|
|
7388
|
-
children: [
|
|
7389
|
-
/* @__PURE__ */ jsx12(
|
|
7390
|
-
"span",
|
|
7391
|
-
{
|
|
7392
|
-
"data-contrast-audited": true,
|
|
7393
|
-
className: cn("w-3 shrink-0 text-center font-og-mono text-og-xs", STATUS_TINT2[file.status]),
|
|
7394
|
-
children: STATUS_LETTER[file.status]
|
|
7395
|
-
}
|
|
7396
|
-
),
|
|
7397
|
-
/* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1 truncate", children: shown }),
|
|
7398
|
-
/* @__PURE__ */ jsxs10("span", { className: "ml-auto flex shrink-0 items-center gap-1 pl-1 font-og-mono text-og-xs", children: [
|
|
7399
|
-
/* @__PURE__ */ jsxs10("span", { "data-contrast-audited": true, className: "text-og-status-idle", children: [
|
|
7400
|
-
"+",
|
|
7401
|
-
file.additions
|
|
7402
|
-
] }),
|
|
7403
|
-
/* @__PURE__ */ jsxs10("span", { "data-contrast-audited": true, className: "text-og-status-failed", children: [
|
|
7404
|
-
"\u2212",
|
|
7405
|
-
file.deletions
|
|
7406
|
-
] })
|
|
7407
|
-
] })
|
|
7408
|
-
]
|
|
7372
|
+
title,
|
|
7373
|
+
"aria-label": label,
|
|
7374
|
+
className: "inline-flex size-7 items-center justify-center rounded-og-sm p-1 transition-colors hover:bg-og-surface-2 hover:text-og-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:size-11 pointer-coarse:size-11",
|
|
7375
|
+
children
|
|
7409
7376
|
}
|
|
7410
7377
|
);
|
|
7411
7378
|
}
|
|
7412
|
-
function
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7379
|
+
function DockChrome({
|
|
7380
|
+
tabs,
|
|
7381
|
+
current,
|
|
7382
|
+
onTab,
|
|
7383
|
+
leading,
|
|
7384
|
+
accessory,
|
|
7385
|
+
controls
|
|
7417
7386
|
}) {
|
|
7418
|
-
const
|
|
7387
|
+
const active = tabs.find((t) => t.id === current) ?? tabs[0];
|
|
7388
|
+
const tabsetId = useId4();
|
|
7389
|
+
const tabRefs = useRef19([]);
|
|
7390
|
+
const tabListRef = useRef19(null);
|
|
7391
|
+
const [visitedTabs, setVisitedTabs] = useState19(() => /* @__PURE__ */ new Set());
|
|
7392
|
+
const [tabOverflow, setTabOverflow] = useState19({ start: false, end: false });
|
|
7393
|
+
const activeId = active?.id ?? "";
|
|
7394
|
+
const activeTabIndex = tabs.findIndex((tab) => tab.id === activeId);
|
|
7395
|
+
const keepActiveTabVisible = useCallback21(() => {
|
|
7396
|
+
const selected = activeTabIndex >= 0 ? tabRefs.current[activeTabIndex] : null;
|
|
7397
|
+
selected?.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
7398
|
+
}, [activeTabIndex]);
|
|
7419
7399
|
useEffect22(() => {
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
}, [
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7400
|
+
if (!activeId) return;
|
|
7401
|
+
setVisitedTabs((previous) => {
|
|
7402
|
+
if (previous.has(activeId)) return previous;
|
|
7403
|
+
const next = new Set(previous);
|
|
7404
|
+
next.add(activeId);
|
|
7405
|
+
return next;
|
|
7406
|
+
});
|
|
7407
|
+
}, [activeId]);
|
|
7408
|
+
useDockLayoutEffect(() => {
|
|
7409
|
+
keepActiveTabVisible();
|
|
7410
|
+
}, [activeId, keepActiveTabVisible]);
|
|
7411
|
+
useDockLayoutEffect(() => {
|
|
7412
|
+
const list = tabListRef.current;
|
|
7413
|
+
if (!list) return;
|
|
7414
|
+
const update = () => {
|
|
7415
|
+
const max = Math.max(0, list.scrollWidth - list.clientWidth);
|
|
7416
|
+
const next = { start: list.scrollLeft > 1, end: list.scrollLeft < max - 1 };
|
|
7417
|
+
setTabOverflow(
|
|
7418
|
+
(previous) => previous.start === next.start && previous.end === next.end ? previous : next
|
|
7419
|
+
);
|
|
7420
|
+
};
|
|
7421
|
+
update();
|
|
7422
|
+
list.addEventListener("scroll", update, { passive: true });
|
|
7423
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => {
|
|
7424
|
+
keepActiveTabVisible();
|
|
7425
|
+
update();
|
|
7426
|
+
});
|
|
7427
|
+
observer?.observe(list);
|
|
7428
|
+
for (const tab of tabRefs.current) {
|
|
7429
|
+
if (tab) observer?.observe(tab);
|
|
7436
7430
|
}
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7431
|
+
return () => {
|
|
7432
|
+
list.removeEventListener("scroll", update);
|
|
7433
|
+
observer?.disconnect();
|
|
7434
|
+
};
|
|
7435
|
+
}, [activeId, keepActiveTabVisible, tabs.length]);
|
|
7436
|
+
const tabMask = tabOverflow.start && tabOverflow.end ? "linear-gradient(to right, transparent 0, black 14px, black calc(100% - 14px), transparent 100%)" : tabOverflow.start ? "linear-gradient(to right, transparent 0, black 14px, black 100%)" : tabOverflow.end ? "linear-gradient(to right, black 0, black calc(100% - 14px), transparent 100%)" : void 0;
|
|
7437
|
+
const activateTab = (index) => {
|
|
7438
|
+
const tab = tabs[index];
|
|
7439
|
+
if (!tab) {
|
|
7440
|
+
return;
|
|
7441
|
+
}
|
|
7442
|
+
onTab(tab.id);
|
|
7443
|
+
tabRefs.current[index]?.focus();
|
|
7444
|
+
};
|
|
7445
|
+
const onTabKeyDown = (event, index) => {
|
|
7446
|
+
if (tabs.length === 0) return;
|
|
7447
|
+
let nextIndex = null;
|
|
7448
|
+
if (event.key === "ArrowRight") nextIndex = (index + 1) % tabs.length;
|
|
7449
|
+
else if (event.key === "ArrowLeft") nextIndex = (index - 1 + tabs.length) % tabs.length;
|
|
7450
|
+
else if (event.key === "Home") nextIndex = 0;
|
|
7451
|
+
else if (event.key === "End") nextIndex = tabs.length - 1;
|
|
7452
|
+
if (nextIndex === null) return;
|
|
7453
|
+
event.preventDefault();
|
|
7454
|
+
activateTab(nextIndex);
|
|
7455
|
+
};
|
|
7456
|
+
return /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
7457
|
+
/* @__PURE__ */ jsxs10("div", { className: "grid shrink-0 grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-x-2 border-b border-og-border px-1.5 py-1 max-[1023px]:grid-cols-[auto_minmax(0,1fr)_auto] max-[1023px]:gap-y-0 max-[1023px]:px-2 max-[1023px]:pb-1 max-[1023px]:pt-0 min-[640px]:max-[1023px]:grid-cols-[auto_minmax(0,1fr)_auto_auto]", children: [
|
|
7458
|
+
/* @__PURE__ */ jsx12("div", { className: "flex min-w-0 shrink-0 items-center max-[1023px]:min-h-11 min-[640px]:max-[1023px]:col-start-1 min-[640px]:max-[1023px]:row-start-1", children: leading ?? /* @__PURE__ */ jsx12("span", { className: "hidden truncate px-1 text-og-sm font-semibold text-og-fg max-[1023px]:inline", children: "Workspace" }) }),
|
|
7459
|
+
/* @__PURE__ */ jsx12(
|
|
7460
|
+
"div",
|
|
7461
|
+
{
|
|
7462
|
+
ref: tabListRef,
|
|
7463
|
+
className: "flex min-w-0 items-center gap-0.5 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden max-[1023px]:col-span-3 max-[1023px]:row-start-2 max-[1023px]:w-full min-[640px]:max-[1023px]:col-span-1 min-[640px]:max-[1023px]:col-start-2 min-[640px]:max-[1023px]:row-start-1",
|
|
7464
|
+
role: "tablist",
|
|
7465
|
+
"aria-orientation": "horizontal",
|
|
7466
|
+
style: {
|
|
7467
|
+
maskImage: tabMask,
|
|
7468
|
+
WebkitMaskImage: tabMask,
|
|
7469
|
+
scrollPaddingInline: "16px"
|
|
7470
|
+
},
|
|
7471
|
+
children: tabs.map((tab, index) => /* @__PURE__ */ jsxs10(
|
|
7472
|
+
"button",
|
|
7473
|
+
{
|
|
7474
|
+
ref: (node) => {
|
|
7475
|
+
tabRefs.current[index] = node;
|
|
7476
|
+
},
|
|
7477
|
+
id: `${tabsetId}-tab-${index}`,
|
|
7478
|
+
type: "button",
|
|
7479
|
+
role: "tab",
|
|
7480
|
+
"aria-selected": tab.id === current,
|
|
7481
|
+
"aria-controls": `${tabsetId}-panel-${index}`,
|
|
7482
|
+
tabIndex: tab.id === current ? 0 : -1,
|
|
7483
|
+
onClick: () => onTab(tab.id),
|
|
7484
|
+
onKeyDown: (event) => onTabKeyDown(event, index),
|
|
7485
|
+
className: cn(
|
|
7486
|
+
"flex min-h-7 shrink-0 items-center justify-center gap-1 rounded-og-sm px-2 py-1 text-og-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-h-11 max-[1023px]:min-w-11 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
|
|
7487
|
+
tab.id === current ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
7488
|
+
),
|
|
7489
|
+
children: [
|
|
7490
|
+
/* @__PURE__ */ jsx12("span", { "data-contrast-audited": true, children: tab.label }),
|
|
7491
|
+
tab.badge
|
|
7492
|
+
]
|
|
7493
|
+
},
|
|
7494
|
+
tab.id
|
|
7495
|
+
))
|
|
7496
|
+
}
|
|
7497
|
+
),
|
|
7498
|
+
/* @__PURE__ */ jsx12("div", { className: "flex min-w-0 shrink-0 items-center justify-self-end min-[640px]:max-[1023px]:col-start-3 min-[640px]:max-[1023px]:row-start-1", children: accessory }),
|
|
7499
|
+
/* @__PURE__ */ jsx12("div", { className: "flex shrink-0 items-center gap-0.5 text-og-fg-subtle min-[640px]:max-[1023px]:col-start-4 min-[640px]:max-[1023px]:row-start-1", children: controls })
|
|
7476
7500
|
] }),
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
"
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7501
|
+
/* @__PURE__ */ jsx12("div", { className: "min-h-0 min-w-0 flex-1 overflow-hidden", children: tabs.length > 0 ? tabs.map((tab, index) => {
|
|
7502
|
+
const selected = tab.id === activeId;
|
|
7503
|
+
const shouldMount = selected || visitedTabs.has(tab.id);
|
|
7504
|
+
return /* @__PURE__ */ jsx12(
|
|
7505
|
+
"div",
|
|
7506
|
+
{
|
|
7507
|
+
id: `${tabsetId}-panel-${index}`,
|
|
7508
|
+
"aria-labelledby": `${tabsetId}-tab-${index}`,
|
|
7509
|
+
className: "h-full min-h-0 min-w-0 overflow-hidden",
|
|
7510
|
+
hidden: !selected,
|
|
7511
|
+
role: "tabpanel",
|
|
7512
|
+
children: shouldMount ? tab.content : null
|
|
7513
|
+
},
|
|
7514
|
+
tab.id
|
|
7515
|
+
);
|
|
7516
|
+
}) : /* @__PURE__ */ jsx12("div", { className: "h-full min-h-0 min-w-0", "aria-label": "Workspace", role: "tabpanel" }) })
|
|
7489
7517
|
] });
|
|
7490
7518
|
}
|
|
7491
|
-
function LayoutToggle({
|
|
7492
|
-
layout,
|
|
7493
|
-
onChange
|
|
7494
|
-
}) {
|
|
7495
|
-
return /* @__PURE__ */ jsx12("div", { className: "inline-flex items-center rounded-og-sm border border-og-border p-0.5", children: ["unified", "split"].map((value) => /* @__PURE__ */ jsx12(
|
|
7496
|
-
"button",
|
|
7497
|
-
{
|
|
7498
|
-
type: "button",
|
|
7499
|
-
onClick: () => onChange(value),
|
|
7500
|
-
className: cn(
|
|
7501
|
-
"min-h-7 rounded-og-xs px-1.5 py-0.5 text-og-xs capitalize focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-w-11 pointer-coarse:min-h-11 pointer-coarse:min-w-11",
|
|
7502
|
-
layout === value ? "bg-og-accent-soft text-og-fg" : "text-og-fg-subtle hover:text-og-fg"
|
|
7503
|
-
),
|
|
7504
|
-
children: value
|
|
7505
|
-
},
|
|
7506
|
-
value
|
|
7507
|
-
)) });
|
|
7508
|
-
}
|
|
7509
7519
|
|
|
7510
7520
|
// src/components/sandbox-workspace.tsx
|
|
7521
|
+
import { useCallback as useCallback22, useEffect as useEffect23, useMemo as useMemo11, useRef as useRef20, useState as useState20 } from "react";
|
|
7522
|
+
import { Popover } from "radix-ui";
|
|
7523
|
+
import {
|
|
7524
|
+
CircleCheckIcon,
|
|
7525
|
+
CpuIcon,
|
|
7526
|
+
LaptopIcon,
|
|
7527
|
+
LoaderCircleIcon as LoaderCircleIcon3,
|
|
7528
|
+
RefreshCwIcon as RefreshCwIcon2,
|
|
7529
|
+
TriangleAlertIcon as TriangleAlertIcon2
|
|
7530
|
+
} from "lucide-react";
|
|
7511
7531
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7512
7532
|
var WORKBENCH_TAB_CHANGES = "changes";
|
|
7513
7533
|
var WORKBENCH_TAB_FILES = "files";
|
|
@@ -8376,6 +8396,7 @@ export {
|
|
|
8376
8396
|
ActivityRail,
|
|
8377
8397
|
ApprovalSurface,
|
|
8378
8398
|
BUILT_IN_TURN_SUMMARY_FACET_IDS,
|
|
8399
|
+
BillingClassMark,
|
|
8379
8400
|
BodyNote,
|
|
8380
8401
|
COMPOSER_PAYMENT_REQUIRED_MESSAGE,
|
|
8381
8402
|
CONNECTION_STATUS_META,
|
|
@@ -8400,6 +8421,7 @@ export {
|
|
|
8400
8421
|
FleetTile,
|
|
8401
8422
|
HEALTH_TOKEN,
|
|
8402
8423
|
HumanInputForm,
|
|
8424
|
+
HumanInputSurface,
|
|
8403
8425
|
INITIAL_TRANSCRIPTION_CONTROL_STATE,
|
|
8404
8426
|
LightboxProvider,
|
|
8405
8427
|
MACHINE_STATE_BADGE_META,
|
|
@@ -8419,9 +8441,14 @@ export {
|
|
|
8419
8441
|
MetricHistoryChart,
|
|
8420
8442
|
MetricSparkline,
|
|
8421
8443
|
ModelPicker,
|
|
8444
|
+
ModelPolicyPicker,
|
|
8445
|
+
ModelPolicyPickerMenu,
|
|
8422
8446
|
OPEN_WORKSTREAM_CONTROL_EVENT,
|
|
8423
8447
|
OpenGeniProvider,
|
|
8424
8448
|
PayloadBlock,
|
|
8449
|
+
PickerAnimatedPage,
|
|
8450
|
+
PickerBackHeader,
|
|
8451
|
+
PickerNavRow,
|
|
8425
8452
|
PierreDiff,
|
|
8426
8453
|
PierreFile,
|
|
8427
8454
|
QueueSurface,
|
|
@@ -8453,6 +8480,7 @@ export {
|
|
|
8453
8480
|
WORKBENCH_TAB_DESKTOP,
|
|
8454
8481
|
WORKBENCH_TAB_FILES,
|
|
8455
8482
|
WORKBENCH_TAB_TERMINAL,
|
|
8483
|
+
WorkbenchChanges,
|
|
8456
8484
|
WorkspaceDock,
|
|
8457
8485
|
advancedSourceSummary,
|
|
8458
8486
|
answersFromDrafts,
|
|
@@ -8480,6 +8508,7 @@ export {
|
|
|
8480
8508
|
defaultCommands,
|
|
8481
8509
|
defaultEffortForModel,
|
|
8482
8510
|
defaultHumanInputFormMessages,
|
|
8511
|
+
defaultModelPolicyPickerMessages,
|
|
8483
8512
|
defaultToolRegistry,
|
|
8484
8513
|
deriveHealth,
|
|
8485
8514
|
deriveMachineChip,
|
|
@@ -8513,6 +8542,7 @@ export {
|
|
|
8513
8542
|
isTitleEvent,
|
|
8514
8543
|
isTurnQueueEvent,
|
|
8515
8544
|
labelLatencyMode,
|
|
8545
|
+
labelReasoningEffort,
|
|
8516
8546
|
languageForPath,
|
|
8517
8547
|
looksBinary,
|
|
8518
8548
|
matchCommand,
|
|
@@ -8521,6 +8551,7 @@ export {
|
|
|
8521
8551
|
parseToolArgs,
|
|
8522
8552
|
payerSummaryForModel,
|
|
8523
8553
|
pointsFor,
|
|
8554
|
+
projectClientModelRows,
|
|
8524
8555
|
projectPendingApprovals,
|
|
8525
8556
|
projectPendingHumanInputRequests,
|
|
8526
8557
|
projectPickerRows,
|