@opengeni/react 0.45.0 → 0.48.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 +68 -12
- package/dist/{chunk-U3CSCMWA.js → chunk-FK6VG4LL.js} +9 -13
- package/dist/chunk-FK6VG4LL.js.map +1 -0
- package/dist/{chunk-HFO4ERGQ.js → chunk-FWXGSNXT.js} +2 -2
- package/dist/{chunk-SRFUT2ZU.js → chunk-I4MPFDRP.js} +119 -63
- package/dist/chunk-I4MPFDRP.js.map +1 -0
- package/dist/{chunk-EB67J347.js → chunk-KZ73RL76.js} +111 -31
- package/dist/chunk-KZ73RL76.js.map +1 -0
- package/dist/{chunk-LWR4MXSS.js → chunk-LHLYWG5R.js} +10 -1
- package/dist/chunk-LHLYWG5R.js.map +1 -0
- package/dist/{chunk-L3EWO3UK.js → chunk-NJ7M2B6Z.js} +445 -84
- package/dist/chunk-NJ7M2B6Z.js.map +1 -0
- package/dist/{chunk-VCBFUSUZ.js → chunk-O4VXOBGF.js} +3 -3
- package/dist/{chunk-VCBFUSUZ.js.map → chunk-O4VXOBGF.js.map} +1 -1
- package/dist/{chunk-6EDV6YFE.js → chunk-OL6QVXGF.js} +121 -29
- package/dist/chunk-OL6QVXGF.js.map +1 -0
- package/dist/chunk-VZTQ73XT.js +86 -0
- package/dist/chunk-VZTQ73XT.js.map +1 -0
- package/dist/{chunk-EHSYZ4KP.js → chunk-WYA65Y3F.js} +16 -16
- package/dist/chunk-WYA65Y3F.js.map +1 -0
- package/dist/{chunk-FD72GJMK.js → chunk-XCNTXWBB.js} +274 -125
- package/dist/chunk-XCNTXWBB.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/components/chat-composer.d.ts +7 -2
- package/dist/components/composer-transcription-control.d.ts +2 -0
- package/dist/components/composer.d.ts +14 -0
- package/dist/components/machines/machine-detail.d.ts +3 -1
- package/dist/components/machines-dashboard.d.ts +3 -3
- package/dist/components/message-timeline.d.ts +12 -2
- package/dist/components/sandbox-files.d.ts +2 -2
- package/dist/components/sandbox-terminal.d.ts +29 -0
- package/dist/components/sandbox-workspace.d.ts +5 -1
- package/dist/components/workspace-dock.d.ts +3 -1
- package/dist/composer.d.ts +2 -2
- package/dist/composer.js +6 -6
- package/dist/hooks/internal.d.ts +6 -0
- package/dist/hooks/use-codex-accounts.d.ts +1 -1
- package/dist/hooks/use-environments.d.ts +10 -4
- package/dist/hooks/use-machines.d.ts +7 -0
- package/dist/hooks/use-sandbox-files.d.ts +19 -0
- package/dist/hooks/use-sandbox-git.d.ts +7 -0
- package/dist/hooks/use-transcription.d.ts +2 -2
- package/dist/hooks/use-voice-input.d.ts +13 -4
- package/dist/index.d.ts +6 -5
- package/dist/index.js +904 -538
- package/dist/index.js.map +1 -1
- package/dist/lib/composer-responsive-context.d.ts +9 -0
- package/dist/lib/use-portal-token-style.d.ts +14 -3
- package/dist/machines.js +2 -2
- package/dist/{queue-surface-implementation-J4XJFKRW.js → queue-surface-implementation-U5JFG7HT.js} +19 -18
- package/dist/queue-surface-implementation-U5JFG7HT.js.map +1 -0
- package/dist/realtime/realtime-control.d.ts +9 -0
- package/dist/realtime.js +29 -32
- package/dist/realtime.js.map +1 -1
- package/dist/session-ui.js +5 -5
- package/dist/session.js +4 -4
- package/dist/timeline/activity-rail.d.ts +3 -2
- package/dist/timeline/index.d.ts +2 -2
- package/dist/timeline/parsers.d.ts +3 -3
- package/dist/timeline/registry.d.ts +3 -0
- package/dist/timeline/screenshot-lightbox.d.ts +1 -1
- package/dist/timeline/types.d.ts +4 -0
- package/dist/voice-recording-store.d.ts +8 -2
- package/package.json +20 -4
- package/src/client.ts +3 -0
- package/src/components/chat-composer.tsx +12 -2
- package/src/components/code-editor.tsx +1 -1
- package/src/components/command-palette.tsx +1 -1
- package/src/components/composer-transcription-control.tsx +41 -16
- package/src/components/composer.tsx +52 -26
- package/src/components/copy-button.tsx +2 -2
- package/src/components/desktop-viewer.tsx +2 -2
- package/src/components/file-browser.tsx +39 -17
- package/src/components/human-input-form.tsx +2 -2
- package/src/components/machine-card.tsx +1 -1
- package/src/components/machines/machine-detail.tsx +39 -15
- package/src/components/machines-dashboard.tsx +7 -6
- package/src/components/message-timeline.tsx +44 -11
- package/src/components/model-picker.tsx +2 -2
- package/src/components/model-policy-picker.tsx +16 -15
- package/src/components/queue-surface-implementation.tsx +20 -16
- package/src/components/queue-surface-state.tsx +2 -2
- package/src/components/sandbox-files.tsx +140 -60
- package/src/components/sandbox-terminal.tsx +24 -5
- package/src/components/sandbox-workspace.tsx +180 -142
- package/src/components/session-chrome.tsx +14 -14
- package/src/components/tooltip.tsx +13 -16
- package/src/components/user-message-body.tsx +1 -1
- package/src/components/workbench-changes.tsx +4 -4
- package/src/components/workspace-dock.tsx +13 -5
- package/src/composer.ts +3 -0
- package/src/hooks/internal.ts +132 -38
- package/src/hooks/use-codex-accounts.ts +4 -4
- package/src/hooks/use-environments.ts +24 -5
- package/src/hooks/use-file-attachments.ts +70 -32
- package/src/hooks/use-goal.ts +17 -5
- package/src/hooks/use-machines.ts +47 -1
- package/src/hooks/use-sandbox-files.ts +310 -59
- package/src/hooks/use-sandbox-git.ts +148 -41
- package/src/hooks/use-session-capabilities.ts +35 -24
- package/src/hooks/use-session-events.ts +18 -4
- package/src/hooks/use-transcription.ts +4 -14
- package/src/hooks/use-turn-queue.ts +17 -5
- package/src/hooks/use-voice-input.ts +481 -36
- package/src/hooks/use-windowed-sections.ts +9 -7
- package/src/index.ts +11 -6
- package/src/lib/composer-responsive-context.ts +15 -0
- package/src/lib/use-portal-token-style.ts +60 -15
- package/src/provider.tsx +52 -7
- package/src/realtime/dropdown-menu.tsx +15 -19
- package/src/realtime/realtime-control.tsx +18 -7
- package/src/timeline/activity-rail.tsx +15 -6
- package/src/timeline/index.ts +1 -1
- package/src/timeline/parsers.ts +33 -20
- package/src/timeline/projection.ts +23 -0
- package/src/timeline/registry.ts +7 -0
- package/src/timeline/screenshot-lightbox.tsx +15 -4
- package/src/timeline/shared.tsx +8 -8
- package/src/timeline/tool-renderers.tsx +166 -22
- package/src/timeline/turn-summary.tsx +6 -6
- package/src/timeline/types.ts +4 -0
- package/src/voice-recording-store.ts +15 -0
- package/styles/compiled.css +5065 -0
- package/styles/compiled.d.ts +2 -0
- package/styles/effective-tokens.css +27 -0
- package/styles/index.css +3 -0
- package/styles/responsive.css +196 -0
- package/styles/responsive.d.ts +2 -0
- package/styles/tokens.css +50 -17
- package/dist/chunk-6EDV6YFE.js.map +0 -1
- package/dist/chunk-EB67J347.js.map +0 -1
- package/dist/chunk-EHSYZ4KP.js.map +0 -1
- package/dist/chunk-FD72GJMK.js.map +0 -1
- package/dist/chunk-JB5725BI.js +0 -48
- package/dist/chunk-JB5725BI.js.map +0 -1
- package/dist/chunk-L3EWO3UK.js.map +0 -1
- package/dist/chunk-LWR4MXSS.js.map +0 -1
- package/dist/chunk-SRFUT2ZU.js.map +0 -1
- package/dist/chunk-U3CSCMWA.js.map +0 -1
- package/dist/queue-surface-implementation-J4XJFKRW.js.map +0 -1
- /package/dist/{chunk-HFO4ERGQ.js.map → chunk-FWXGSNXT.js.map} +0 -0
|
@@ -81,7 +81,7 @@ export function MachineCard({
|
|
|
81
81
|
"og-root group relative flex flex-col gap-3 overflow-hidden rounded-og-lg border border-og-border",
|
|
82
82
|
"bg-og-surface-1 p-4 shadow-og-sm transition-colors",
|
|
83
83
|
openable &&
|
|
84
|
-
"cursor-pointer hover:border-og-border-strong focus-visible:border-og-accent/60 focus-visible:outline-
|
|
84
|
+
"cursor-pointer hover:border-og-border-strong focus-visible:border-og-accent/60 focus-visible:outline-hidden",
|
|
85
85
|
machine.active && "border-og-accent/40",
|
|
86
86
|
className,
|
|
87
87
|
)}
|
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
// how have they moved over the chosen window. Built entirely on the existing
|
|
7
7
|
// `og-*` token system — no new visual language, just the missing depth.
|
|
8
8
|
// ----------------------------------------------------------------------------
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
ArrowLeftIcon,
|
|
11
|
+
CpuIcon,
|
|
12
|
+
LaptopIcon,
|
|
13
|
+
RadioIcon,
|
|
14
|
+
ServerIcon,
|
|
15
|
+
Trash2Icon,
|
|
16
|
+
} from "lucide-react";
|
|
10
17
|
import { cn } from "../../lib/cn";
|
|
11
18
|
import { formatRelativeTime } from "../../lib/format";
|
|
12
19
|
import type { MachineView, MetricSample } from "../../types/machines";
|
|
@@ -23,6 +30,8 @@ export type MachineDetailProps = {
|
|
|
23
30
|
onWindowChange: (w: MetricWindow) => void;
|
|
24
31
|
loadingSeries?: boolean | undefined;
|
|
25
32
|
onBack?: (() => void) | undefined;
|
|
33
|
+
/** Open the workspace-admin removal confirmation for a self-hosted machine. */
|
|
34
|
+
onRemove?: ((machine: MachineView) => void) | undefined;
|
|
26
35
|
now?: number | undefined;
|
|
27
36
|
className?: string | undefined;
|
|
28
37
|
};
|
|
@@ -40,6 +49,7 @@ export function MachineDetail({
|
|
|
40
49
|
onWindowChange,
|
|
41
50
|
loadingSeries,
|
|
42
51
|
onBack,
|
|
52
|
+
onRemove,
|
|
43
53
|
now = Date.now(),
|
|
44
54
|
className,
|
|
45
55
|
}: MachineDetailProps) {
|
|
@@ -78,24 +88,38 @@ export function MachineDetail({
|
|
|
78
88
|
</span>
|
|
79
89
|
</div>
|
|
80
90
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
{METRIC_WINDOWS.map((w) => (
|
|
91
|
+
<div className="flex shrink-0 items-center gap-2">
|
|
92
|
+
{onRemove && machine.enrollmentId && !machine.isSessionGroup ? (
|
|
84
93
|
<button
|
|
85
|
-
key={w}
|
|
86
94
|
type="button"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
w === window
|
|
92
|
-
? "bg-og-surface-3 text-og-fg shadow-og-sm"
|
|
93
|
-
: "text-og-fg-subtle hover:text-og-fg-muted",
|
|
94
|
-
)}
|
|
95
|
+
data-remove-machine
|
|
96
|
+
aria-label={`Remove machine ${machine.name}`}
|
|
97
|
+
onClick={() => onRemove(machine)}
|
|
98
|
+
className="inline-flex min-h-9 items-center gap-1.5 rounded-og-sm border border-og-status-failed/40 px-2.5 py-1 font-medium text-og-xs text-og-status-failed transition-colors hover:bg-og-status-failed/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-og-status-failed/50 pointer-coarse:min-h-11"
|
|
95
99
|
>
|
|
96
|
-
|
|
100
|
+
<Trash2Icon className="size-3.5" aria-hidden />
|
|
101
|
+
<span className="hidden sm:inline">Remove machine</span>
|
|
97
102
|
</button>
|
|
98
|
-
)
|
|
103
|
+
) : null}
|
|
104
|
+
{/* range selector */}
|
|
105
|
+
<div className="flex items-center gap-0.5 rounded-og-md border border-og-border bg-og-surface-1 p-0.5">
|
|
106
|
+
{METRIC_WINDOWS.map((w) => (
|
|
107
|
+
<button
|
|
108
|
+
key={w}
|
|
109
|
+
type="button"
|
|
110
|
+
onClick={() => onWindowChange(w)}
|
|
111
|
+
data-active={w === window}
|
|
112
|
+
className={cn(
|
|
113
|
+
"rounded-og-sm px-2 py-1 font-og-mono text-og-xs transition-colors",
|
|
114
|
+
w === window
|
|
115
|
+
? "bg-og-surface-3 text-og-fg shadow-og-sm"
|
|
116
|
+
: "text-og-fg-subtle hover:text-og-fg-muted",
|
|
117
|
+
)}
|
|
118
|
+
>
|
|
119
|
+
{w}
|
|
120
|
+
</button>
|
|
121
|
+
))}
|
|
122
|
+
</div>
|
|
99
123
|
</div>
|
|
100
124
|
</div>
|
|
101
125
|
|
|
@@ -20,7 +20,7 @@ export type MachinesDashboardProps = {
|
|
|
20
20
|
onOpenDetail?: ((machine: MachineView) => void) | undefined;
|
|
21
21
|
/** Shared clock so freshness/relative times render consistently across cards. */
|
|
22
22
|
now?: number | undefined;
|
|
23
|
-
/** Open the
|
|
23
|
+
/** Open the connection flow (the "Connect a machine" CTA). */
|
|
24
24
|
onEnroll?: (() => void) | undefined;
|
|
25
25
|
onRefresh?: (() => void) | undefined;
|
|
26
26
|
className?: string | undefined;
|
|
@@ -38,7 +38,8 @@ function EmptyState({ onEnroll }: { onEnroll?: (() => void) | undefined }) {
|
|
|
38
38
|
<div className="space-y-1">
|
|
39
39
|
<p className="text-og-base font-medium text-og-fg">No machines yet</p>
|
|
40
40
|
<p className="max-w-xs text-og-sm text-og-fg-muted">
|
|
41
|
-
|
|
41
|
+
Connect your own computer to run the agent on it — your files, your terminal, your
|
|
42
|
+
desktop.
|
|
42
43
|
</p>
|
|
43
44
|
</div>
|
|
44
45
|
{onEnroll ? (
|
|
@@ -49,7 +50,7 @@ function EmptyState({ onEnroll }: { onEnroll?: (() => void) | undefined }) {
|
|
|
49
50
|
className="inline-flex items-center gap-1.5 rounded-og-sm bg-og-accent px-3 py-1.5 text-og-sm font-medium text-og-accent-fg transition-colors hover:bg-og-accent-strong pointer-coarse:min-h-11"
|
|
50
51
|
>
|
|
51
52
|
<PlusIcon className="size-3.5" aria-hidden />
|
|
52
|
-
|
|
53
|
+
Connect a machine
|
|
53
54
|
</button>
|
|
54
55
|
) : null}
|
|
55
56
|
</div>
|
|
@@ -93,7 +94,7 @@ function Header({
|
|
|
93
94
|
className="inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2.5 py-1 text-og-sm font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:text-og-fg pointer-coarse:min-h-11"
|
|
94
95
|
>
|
|
95
96
|
<PlusIcon className="size-3.5" aria-hidden />
|
|
96
|
-
|
|
97
|
+
Connect a machine
|
|
97
98
|
</button>
|
|
98
99
|
) : null}
|
|
99
100
|
</div>
|
|
@@ -102,10 +103,10 @@ function Header({
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
/**
|
|
105
|
-
* The workspace Machines dashboard: the fleet of
|
|
106
|
+
* The workspace Machines dashboard: the fleet of Connected Machines + the
|
|
106
107
|
* session's managed sandbox, each with its connection-status pill, state badges,
|
|
107
108
|
* latest metrics, and an attach/swap affordance. Renders the empty state (no
|
|
108
|
-
* machines →
|
|
109
|
+
* machines → connect CTA), a load error, and the populated grid. The component
|
|
109
110
|
* is purely presentational — feed it `MachinesResponse` data via `useMachines`.
|
|
110
111
|
*/
|
|
111
112
|
export function MachinesDashboard({
|
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
type NoticeItem,
|
|
69
69
|
type TimelineGroup,
|
|
70
70
|
type TimelineItem,
|
|
71
|
+
type RetainedScreenshotLoader,
|
|
71
72
|
type ToolRegistry,
|
|
72
73
|
type TurnSummaryOptions,
|
|
73
74
|
type UserMessageItem,
|
|
@@ -123,6 +124,12 @@ export type MessageTimelineProps = {
|
|
|
123
124
|
* a Reconnect button without a handler to run it.
|
|
124
125
|
*/
|
|
125
126
|
onReconnect?: ((item: AuthNeededItem) => void | Promise<void>) | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Decide which durable authentication notices this timeline presents.
|
|
129
|
+
* Defaults to showing every notice. Embedded hosts can suppress notices for
|
|
130
|
+
* credentials they manage elsewhere without discarding the underlying event.
|
|
131
|
+
*/
|
|
132
|
+
shouldRenderAuthNeeded?: ((item: AuthNeededItem) => boolean) | undefined;
|
|
126
133
|
/**
|
|
127
134
|
* Resolve a provider domain (from a reconnect card) to a logo URL the host
|
|
128
135
|
* serves itself — the app maps it through its catalog + `catalogAssetUrl`.
|
|
@@ -137,6 +144,8 @@ export type MessageTimelineProps = {
|
|
|
137
144
|
* `createDefaultToolRegistry({ entries })` to add custom tool renderers.
|
|
138
145
|
*/
|
|
139
146
|
toolRegistry?: ToolRegistry | undefined;
|
|
147
|
+
/** Resolve opaque retained screenshot receipts through the authenticated host SDK. */
|
|
148
|
+
loadRetainedScreenshot?: RetainedScreenshotLoader | undefined;
|
|
140
149
|
/**
|
|
141
150
|
* Display name of the session's active compute target (Connected Machine or
|
|
142
151
|
* cloud sandbox). When set, exec_command collapsed previews prefix `on {label}`.
|
|
@@ -167,6 +176,8 @@ export type MessageTimelineProps = {
|
|
|
167
176
|
* scrolls the in-memory window.
|
|
168
177
|
*/
|
|
169
178
|
onJumpToLatest?: (() => void | Promise<void>) | undefined;
|
|
179
|
+
/** Host-owned content appended after timeline groups, such as startup progress. */
|
|
180
|
+
trailingState?: ReactNode | undefined;
|
|
170
181
|
emptyState?: ReactNode | undefined;
|
|
171
182
|
className?: string | undefined;
|
|
172
183
|
};
|
|
@@ -277,8 +288,10 @@ export function MessageTimeline({
|
|
|
277
288
|
onOpenSession,
|
|
278
289
|
onMemoryClick,
|
|
279
290
|
onReconnect,
|
|
291
|
+
shouldRenderAuthNeeded,
|
|
280
292
|
resolveProviderLogo,
|
|
281
293
|
toolRegistry = defaultToolRegistry,
|
|
294
|
+
loadRetainedScreenshot,
|
|
282
295
|
computeLabel = null,
|
|
283
296
|
turnSummary,
|
|
284
297
|
autoFollow = true,
|
|
@@ -291,10 +304,17 @@ export function MessageTimeline({
|
|
|
291
304
|
loadingNewer = false,
|
|
292
305
|
onLoadNewer,
|
|
293
306
|
onJumpToLatest,
|
|
307
|
+
trailingState,
|
|
294
308
|
emptyState,
|
|
295
309
|
className,
|
|
296
310
|
}: MessageTimelineProps) {
|
|
297
|
-
const resolvedItems = useMemo(() =>
|
|
311
|
+
const resolvedItems = useMemo(() => {
|
|
312
|
+
const projected = items ?? buildTimeline(events ?? []);
|
|
313
|
+
if (!shouldRenderAuthNeeded) {
|
|
314
|
+
return projected;
|
|
315
|
+
}
|
|
316
|
+
return projected.filter((item) => item.kind !== "auth-needed" || shouldRenderAuthNeeded(item));
|
|
317
|
+
}, [items, events, shouldRenderAuthNeeded]);
|
|
298
318
|
const allGroups = useMemo(() => groupTimeline(resolvedItems), [resolvedItems]);
|
|
299
319
|
const groups = useStableTimelineGroupKeys(allGroups);
|
|
300
320
|
const scrollRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -1278,7 +1298,7 @@ export function MessageTimeline({
|
|
|
1278
1298
|
className={cn(
|
|
1279
1299
|
// tabIndex=-1 is programmatic only — never paint a focus ring on
|
|
1280
1300
|
// the whole scroller (click + Shift used to flash a blue outline).
|
|
1281
|
-
"min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 sm:px-6 outline-
|
|
1301
|
+
"min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 sm:px-6 outline-hidden",
|
|
1282
1302
|
autoFollow && pinned && !hasNewer
|
|
1283
1303
|
? "[overflow-anchor:none]"
|
|
1284
1304
|
: "[overflow-anchor:auto]",
|
|
@@ -1325,6 +1345,7 @@ export function MessageTimeline({
|
|
|
1325
1345
|
onReconnect,
|
|
1326
1346
|
resolveProviderLogo,
|
|
1327
1347
|
toolRegistry,
|
|
1348
|
+
loadRetainedScreenshot,
|
|
1328
1349
|
turnSummary,
|
|
1329
1350
|
]}
|
|
1330
1351
|
>
|
|
@@ -1337,6 +1358,7 @@ export function MessageTimeline({
|
|
|
1337
1358
|
onReconnect={onReconnect}
|
|
1338
1359
|
resolveProviderLogo={resolveProviderLogo}
|
|
1339
1360
|
toolRegistry={toolRegistry}
|
|
1361
|
+
loadRetainedScreenshot={loadRetainedScreenshot}
|
|
1340
1362
|
turnSummary={turnSummary}
|
|
1341
1363
|
foldLiveCluster={isAgentProgress(next)}
|
|
1342
1364
|
trailingAgentText={trailingAgentTextAfterTurn(group, next)}
|
|
@@ -1349,6 +1371,9 @@ export function MessageTimeline({
|
|
|
1349
1371
|
</div>
|
|
1350
1372
|
);
|
|
1351
1373
|
})}
|
|
1374
|
+
{groups.length > 0 && trailingState ? (
|
|
1375
|
+
<div data-og-timeline-trailing-state="">{trailingState}</div>
|
|
1376
|
+
) : null}
|
|
1352
1377
|
{hasNewer ? (
|
|
1353
1378
|
<div
|
|
1354
1379
|
ref={bottomSentinelRef}
|
|
@@ -1502,7 +1527,7 @@ export function MessageTimeline({
|
|
|
1502
1527
|
}
|
|
1503
1528
|
}}
|
|
1504
1529
|
className={cn(
|
|
1505
|
-
"absolute bottom-4
|
|
1530
|
+
"absolute inset-x-0 bottom-4 mx-auto w-fit",
|
|
1506
1531
|
"inline-flex items-center gap-1.5 rounded-full border border-og-border bg-og-surface-3/90 px-3 py-1.5",
|
|
1507
1532
|
"text-og-control font-medium text-og-fg shadow-og-md backdrop-blur",
|
|
1508
1533
|
"hover:border-og-border-strong",
|
|
@@ -1677,6 +1702,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
|
|
|
1677
1702
|
onReconnect,
|
|
1678
1703
|
resolveProviderLogo,
|
|
1679
1704
|
toolRegistry,
|
|
1705
|
+
loadRetainedScreenshot,
|
|
1680
1706
|
turnSummary,
|
|
1681
1707
|
insideTurn = false,
|
|
1682
1708
|
nestClusterChips = false,
|
|
@@ -1693,6 +1719,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
|
|
|
1693
1719
|
onReconnect?: ((item: AuthNeededItem) => void | Promise<void>) | undefined;
|
|
1694
1720
|
resolveProviderLogo?: ((providerDomain: string) => string | null | undefined) | undefined;
|
|
1695
1721
|
toolRegistry: ToolRegistry;
|
|
1722
|
+
loadRetainedScreenshot?: RetainedScreenshotLoader | undefined;
|
|
1696
1723
|
turnSummary?: TurnSummaryOptions | undefined;
|
|
1697
1724
|
/** A completed cluster of a still-RUNNING turn (not the live tail) folds
|
|
1698
1725
|
behind a neutral chip — the one place activity without an outcome still
|
|
@@ -1766,6 +1793,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
|
|
|
1766
1793
|
onOpenSession={onOpenSession}
|
|
1767
1794
|
onMemoryClick={onMemoryClick}
|
|
1768
1795
|
toolRegistry={toolRegistry}
|
|
1796
|
+
loadRetainedScreenshot={loadRetainedScreenshot}
|
|
1769
1797
|
bare
|
|
1770
1798
|
/>
|
|
1771
1799
|
);
|
|
@@ -1787,6 +1815,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
|
|
|
1787
1815
|
onOpenSession={onOpenSession}
|
|
1788
1816
|
onMemoryClick={onMemoryClick}
|
|
1789
1817
|
toolRegistry={toolRegistry}
|
|
1818
|
+
loadRetainedScreenshot={loadRetainedScreenshot}
|
|
1790
1819
|
bare
|
|
1791
1820
|
/>
|
|
1792
1821
|
</TurnSummary>
|
|
@@ -1812,6 +1841,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
|
|
|
1812
1841
|
onOpenSession={onOpenSession}
|
|
1813
1842
|
onMemoryClick={onMemoryClick}
|
|
1814
1843
|
toolRegistry={toolRegistry}
|
|
1844
|
+
loadRetainedScreenshot={loadRetainedScreenshot}
|
|
1815
1845
|
bare
|
|
1816
1846
|
/>
|
|
1817
1847
|
</TurnRailFrame>
|
|
@@ -1838,6 +1868,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
|
|
|
1838
1868
|
onReconnect,
|
|
1839
1869
|
resolveProviderLogo,
|
|
1840
1870
|
toolRegistry,
|
|
1871
|
+
loadRetainedScreenshot,
|
|
1841
1872
|
turnSummary,
|
|
1842
1873
|
]}
|
|
1843
1874
|
>
|
|
@@ -1849,6 +1880,7 @@ const TimelineGroupView = memo(function TimelineGroupView({
|
|
|
1849
1880
|
onReconnect={onReconnect}
|
|
1850
1881
|
resolveProviderLogo={resolveProviderLogo}
|
|
1851
1882
|
toolRegistry={toolRegistry}
|
|
1883
|
+
loadRetainedScreenshot={loadRetainedScreenshot}
|
|
1852
1884
|
turnSummary={turnSummary}
|
|
1853
1885
|
insideTurn
|
|
1854
1886
|
nestClusterChips={nestClusters}
|
|
@@ -2184,12 +2216,12 @@ function CompactionRow({ item }: { item: ContextCompactionItem }) {
|
|
|
2184
2216
|
: null;
|
|
2185
2217
|
const title =
|
|
2186
2218
|
item.phase === "started"
|
|
2187
|
-
? "Compacting conversation
|
|
2219
|
+
? "Compacting conversation history…"
|
|
2188
2220
|
: item.phase === "compacted"
|
|
2189
2221
|
? before && after
|
|
2190
|
-
? `Conversation
|
|
2191
|
-
: "Conversation
|
|
2192
|
-
: "Couldn’t compact conversation
|
|
2222
|
+
? `Conversation history compacted · ~${before} → ~${after} estimated history tokens`
|
|
2223
|
+
: "Conversation history compacted"
|
|
2224
|
+
: "Couldn’t compact conversation history";
|
|
2193
2225
|
const subtitle =
|
|
2194
2226
|
item.phase === "compacted"
|
|
2195
2227
|
? "Chat history above is unchanged"
|
|
@@ -2247,7 +2279,7 @@ function MessageFooterTime({ occurredAt }: { occurredAt: string }) {
|
|
|
2247
2279
|
className={cn(
|
|
2248
2280
|
"shrink-0 tabular-nums text-og-xs text-og-fg-subtle",
|
|
2249
2281
|
"opacity-0 transition-opacity duration-150",
|
|
2250
|
-
"group-hover/copy:opacity-100 group-focus-within/copy:opacity-100 pointer-coarse:opacity-
|
|
2282
|
+
"group-hover/copy:opacity-100 group-focus-within/copy:opacity-100 pointer-coarse:opacity-100",
|
|
2251
2283
|
)}
|
|
2252
2284
|
>
|
|
2253
2285
|
{formatClockTime(occurredAt)}
|
|
@@ -2428,7 +2460,7 @@ function WorkerCompletionRow({
|
|
|
2428
2460
|
onClick={() => onOpenSession(item.childSessionId)}
|
|
2429
2461
|
className={cn(
|
|
2430
2462
|
"-my-0.5 -mr-1 inline-flex shrink-0 items-center gap-1 rounded-og-sm px-2 py-1 text-og-sm font-medium text-og-fg-muted pointer-coarse:py-2",
|
|
2431
|
-
"outline-
|
|
2463
|
+
"outline-hidden transition-colors duration-150 hover:bg-og-surface-2 hover:text-og-fg",
|
|
2432
2464
|
"focus-visible:ring-2 focus-visible:ring-og-accent",
|
|
2433
2465
|
)}
|
|
2434
2466
|
>
|
|
@@ -2444,7 +2476,7 @@ function WorkerCompletionRow({
|
|
|
2444
2476
|
type="button"
|
|
2445
2477
|
className={cn(
|
|
2446
2478
|
"group/wc -mx-1 inline-flex w-fit items-center gap-1 rounded-og-sm px-1 py-0.5 text-og-xs font-medium text-og-fg-subtle",
|
|
2447
|
-
"outline-
|
|
2479
|
+
"outline-hidden transition-colors duration-150 hover:text-og-fg-muted focus-visible:ring-2 focus-visible:ring-og-accent",
|
|
2448
2480
|
)}
|
|
2449
2481
|
>
|
|
2450
2482
|
<ChevronRightIcon className="size-3 transition-transform duration-150 ease-og-in-out group-data-[state=open]/wc:rotate-90" />
|
|
@@ -2693,7 +2725,8 @@ function AuthNeededRow({
|
|
|
2693
2725
|
const enter = useEntranceAnimation();
|
|
2694
2726
|
const [busy, setBusy] = useState(false);
|
|
2695
2727
|
const [failed, setFailed] = useState(false);
|
|
2696
|
-
const provider =
|
|
2728
|
+
const provider =
|
|
2729
|
+
item.serverId === "codex_apps" ? "Codex Apps" : providerLabel(item.providerDomain);
|
|
2697
2730
|
const unavailable =
|
|
2698
2731
|
item.reason === "personal_authority_unavailable" ||
|
|
2699
2732
|
item.reason === "unsupported_auth" ||
|
|
@@ -100,10 +100,10 @@ export function ModelPicker({
|
|
|
100
100
|
disabled={disabled === true}
|
|
101
101
|
aria-label={label}
|
|
102
102
|
className={cn(
|
|
103
|
-
"h-8 max-w-[180px] cursor-pointer appearance-none truncate rounded-og-md bg-transparent",
|
|
103
|
+
"og-model-picker-native h-8 max-w-[180px] cursor-pointer appearance-none truncate rounded-og-md bg-transparent pointer-coarse:h-11",
|
|
104
104
|
"py-0 pl-2 pr-6 text-[13px] text-og-fg-muted",
|
|
105
105
|
"transition-colors duration-150 hover:bg-og-surface-2 hover:text-og-fg",
|
|
106
|
-
"focus:outline-
|
|
106
|
+
"focus:outline-hidden focus-visible:outline-hidden",
|
|
107
107
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
108
108
|
)}
|
|
109
109
|
>
|
|
@@ -12,14 +12,13 @@ import { DropdownMenu } from "radix-ui";
|
|
|
12
12
|
import {
|
|
13
13
|
useEffect,
|
|
14
14
|
useMemo,
|
|
15
|
-
useRef,
|
|
16
15
|
useState,
|
|
17
16
|
type CSSProperties,
|
|
18
17
|
type ReactNode,
|
|
19
18
|
type SVGProps,
|
|
20
19
|
} from "react";
|
|
21
20
|
import { cn } from "../lib/cn";
|
|
22
|
-
import { usePortalTokenStyle } from "../lib/use-portal-token-style";
|
|
21
|
+
import { usePortalTokenSource, usePortalTokenStyle } from "../lib/use-portal-token-style";
|
|
23
22
|
import {
|
|
24
23
|
coerceReasoningEffortForModel,
|
|
25
24
|
effortOptionsForModel,
|
|
@@ -243,7 +242,7 @@ export function PickerNavRow(props: {
|
|
|
243
242
|
onClick={props.onClick}
|
|
244
243
|
data-testid={props.testId}
|
|
245
244
|
className={cn(
|
|
246
|
-
"flex w-full cursor-pointer items-center gap-2 rounded-og-sm px-[var(--og-model-picker-row-padding-x)] py-[var(--og-model-picker-row-padding-y)] text-left text-og-fg outline-
|
|
245
|
+
"flex w-full cursor-pointer items-center gap-2 rounded-og-sm px-[var(--og-model-picker-row-padding-x)] py-[var(--og-model-picker-row-padding-y)] text-left text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40",
|
|
247
246
|
props.disabled && "cursor-not-allowed opacity-50",
|
|
248
247
|
)}
|
|
249
248
|
>
|
|
@@ -278,7 +277,7 @@ export function PickerBackHeader(props: {
|
|
|
278
277
|
type="button"
|
|
279
278
|
onClick={props.onBack}
|
|
280
279
|
data-testid="model-picker-back"
|
|
281
|
-
className="flex min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-og-sm px-1.5 py-1.5 text-left text-og-fg outline-
|
|
280
|
+
className="flex min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-og-sm px-1.5 py-1.5 text-left text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40"
|
|
282
281
|
>
|
|
283
282
|
<ChevronLeftIcon className="size-3.5 shrink-0 text-og-fg-subtle" />
|
|
284
283
|
{props.icon}
|
|
@@ -455,7 +454,7 @@ export function ModelPolicyPickerMenu(
|
|
|
455
454
|
);
|
|
456
455
|
}}
|
|
457
456
|
className={cn(
|
|
458
|
-
"flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-og-sm text-og-fg-subtle outline-
|
|
457
|
+
"flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-og-sm text-og-fg-subtle outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
459
458
|
activeModel && props.latencyMode === "fast" && "text-og-fg",
|
|
460
459
|
)}
|
|
461
460
|
>
|
|
@@ -487,7 +486,7 @@ export function ModelPolicyPickerMenu(
|
|
|
487
486
|
disabled={!focusModel.selectable}
|
|
488
487
|
onClick={() => selectEffort(focusModel, effort)}
|
|
489
488
|
className={cn(
|
|
490
|
-
"flex h-[var(--og-model-picker-effort-height)] w-full cursor-pointer items-center rounded-og-sm px-[var(--og-model-picker-row-padding-x)] text-left text-og-menu text-og-fg outline-
|
|
489
|
+
"flex h-[var(--og-model-picker-effort-height)] w-full cursor-pointer items-center rounded-og-sm px-[var(--og-model-picker-row-padding-x)] text-left text-og-menu text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
491
490
|
selected && "bg-og-surface-2",
|
|
492
491
|
)}
|
|
493
492
|
>
|
|
@@ -542,8 +541,8 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
|
|
|
542
541
|
if (props.open === undefined) setUncontrolledOpen(next);
|
|
543
542
|
props.onOpenChange?.(next);
|
|
544
543
|
};
|
|
545
|
-
const
|
|
546
|
-
const portalStyle = usePortalTokenStyle(
|
|
544
|
+
const trigger = usePortalTokenSource<HTMLButtonElement>();
|
|
545
|
+
const portalStyle = usePortalTokenStyle(trigger.source);
|
|
547
546
|
const messages = useMemo(
|
|
548
547
|
() => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),
|
|
549
548
|
[props.messages],
|
|
@@ -556,7 +555,7 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
|
|
|
556
555
|
return (
|
|
557
556
|
<span
|
|
558
557
|
className={cn(
|
|
559
|
-
"inline-flex h-8 w-40 shrink-0 animate-pulse rounded-full bg-og-surface-2",
|
|
558
|
+
"og-root inline-flex h-8 w-40 shrink-0 animate-pulse rounded-full bg-og-surface-2",
|
|
560
559
|
props.className,
|
|
561
560
|
)}
|
|
562
561
|
aria-label={messages.loading}
|
|
@@ -568,12 +567,12 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
|
|
|
568
567
|
<DropdownMenu.Root open={open} onOpenChange={setOpen}>
|
|
569
568
|
<DropdownMenu.Trigger asChild>
|
|
570
569
|
<button
|
|
571
|
-
ref={
|
|
570
|
+
ref={trigger.ref}
|
|
572
571
|
type="button"
|
|
573
572
|
disabled={props.disabled}
|
|
574
573
|
aria-label={messages.label}
|
|
575
574
|
className={cn(
|
|
576
|
-
"og-root inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-og-control text-og-fg-muted outline-
|
|
575
|
+
"og-root og-model-policy-trigger inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-og-control text-og-fg-muted outline-hidden transition-colors hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-11 max-sm:max-w-[7.5rem] max-sm:px-2",
|
|
577
576
|
props.className,
|
|
578
577
|
)}
|
|
579
578
|
>
|
|
@@ -584,13 +583,15 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
|
|
|
584
583
|
}
|
|
585
584
|
className="text-og-fg"
|
|
586
585
|
/>
|
|
587
|
-
<span className="min-w-0 truncate font-medium text-og-fg max-sm:hidden">
|
|
586
|
+
<span className="og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden">
|
|
588
587
|
{selected?.label ?? props.model}
|
|
589
588
|
</span>
|
|
590
|
-
<span className="min-w-0 truncate font-medium text-og-fg sm:hidden">
|
|
589
|
+
<span className="og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden">
|
|
591
590
|
{selected?.shortLabel ?? selected?.label ?? props.model}
|
|
592
591
|
</span>
|
|
593
|
-
<span className="max-sm:hidden">
|
|
592
|
+
<span className="og-model-policy-effort max-sm:hidden">
|
|
593
|
+
{labelReasoningEffort(props.effort)}
|
|
594
|
+
</span>
|
|
594
595
|
{props.latencyMode === "fast" ? (
|
|
595
596
|
<ZapIcon
|
|
596
597
|
className="size-3.5 shrink-0 fill-current stroke-current text-og-fg"
|
|
@@ -609,7 +610,7 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
|
|
|
609
610
|
collisionPadding={12}
|
|
610
611
|
onCloseAutoFocus={(event) => event.preventDefault()}
|
|
611
612
|
className={cn(
|
|
612
|
-
"og-root z-50 flex max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] w-[var(--og-model-picker-menu-width)] max-w-[calc(100vw-16px)] flex-col overflow-hidden rounded-og-lg border border-og-border bg-og-surface-1 p-[var(--og-model-picker-menu-padding)] text-og-fg shadow-og-lg",
|
|
613
|
+
"og-root og-model-policy-menu z-50 flex max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] w-[var(--og-model-picker-menu-width)] max-w-[calc(100vw-16px)] flex-col overflow-hidden rounded-og-lg border border-og-border bg-og-surface-1 p-[var(--og-model-picker-menu-padding)] text-og-fg shadow-og-lg",
|
|
613
614
|
props.contentClassName,
|
|
614
615
|
)}
|
|
615
616
|
style={{ ...portalStyle, ...props.contentStyle }}
|
|
@@ -32,7 +32,6 @@ import {
|
|
|
32
32
|
useCallback,
|
|
33
33
|
useId,
|
|
34
34
|
useMemo,
|
|
35
|
-
useRef,
|
|
36
35
|
useState,
|
|
37
36
|
type KeyboardEvent as ReactKeyboardEvent,
|
|
38
37
|
} from "react";
|
|
@@ -40,7 +39,11 @@ import {
|
|
|
40
39
|
import { DropdownMenu } from "radix-ui";
|
|
41
40
|
import type { ComposerState } from "../hooks/use-composer";
|
|
42
41
|
import type { QueueMutationKind, UseTurnQueueResult } from "../hooks/use-turn-queue";
|
|
43
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
type PortalTokenStyle,
|
|
44
|
+
usePortalTokenSource,
|
|
45
|
+
usePortalTokenStyle,
|
|
46
|
+
} from "../lib/use-portal-token-style";
|
|
44
47
|
import { requestQueueDraftEdit } from "./queue-draft-policy";
|
|
45
48
|
import { QueueErrorAlert, QueueStoppingStatus } from "./queue-surface-state";
|
|
46
49
|
|
|
@@ -80,8 +83,9 @@ export function QueueSurface({
|
|
|
80
83
|
const [replaceDraftFor, setReplaceDraftFor] = useState<string | null>(null);
|
|
81
84
|
const [announcement, setAnnouncement] = useState("");
|
|
82
85
|
const [draggedTurnId, setDraggedTurnId] = useState<string | null>(null);
|
|
83
|
-
const
|
|
84
|
-
const
|
|
86
|
+
const surface = usePortalTokenSource<HTMLDivElement>();
|
|
87
|
+
const surfaceRef = surface.currentRef;
|
|
88
|
+
const portalTokenStyle = usePortalTokenStyle(surface.source);
|
|
85
89
|
const [keyboardDrag, setKeyboardDrag] = useState<{
|
|
86
90
|
turnId: string;
|
|
87
91
|
projectedIndex: number;
|
|
@@ -129,7 +133,7 @@ export function QueueSurface({
|
|
|
129
133
|
);
|
|
130
134
|
if (moved) focusQueueTurn(surfaceRef.current, turnId);
|
|
131
135
|
},
|
|
132
|
-
[queue],
|
|
136
|
+
[queue, surfaceRef],
|
|
133
137
|
);
|
|
134
138
|
|
|
135
139
|
const onDragEnd = useCallback(
|
|
@@ -245,7 +249,7 @@ export function QueueSurface({
|
|
|
245
249
|
|
|
246
250
|
return (
|
|
247
251
|
<div
|
|
248
|
-
ref={
|
|
252
|
+
ref={surface.ref}
|
|
249
253
|
className="og-root mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6"
|
|
250
254
|
data-testid="queue-surface"
|
|
251
255
|
>
|
|
@@ -253,7 +257,7 @@ export function QueueSurface({
|
|
|
253
257
|
{queue.stoppingPreviousAttempt ? <QueueStoppingStatus queue={queue} dividerAfter /> : null}
|
|
254
258
|
<button
|
|
255
259
|
type="button"
|
|
256
|
-
className="flex w-full min-w-0 flex-wrap items-center gap-2 px-3 py-2 text-left outline-
|
|
260
|
+
className="flex w-full min-w-0 flex-wrap items-center gap-2 px-3 py-2 text-left outline-hidden transition-colors hover:bg-surface-2/60 focus-visible:bg-surface-2/60 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]"
|
|
257
261
|
onClick={() => setOpen((value) => !value)}
|
|
258
262
|
aria-description={!open && totalCount > 0 ? collapsedPreview.summary : undefined}
|
|
259
263
|
aria-expanded={open}
|
|
@@ -800,7 +804,7 @@ function QueuePrompt({
|
|
|
800
804
|
aria-controls={fullContentId}
|
|
801
805
|
aria-expanded={expanded}
|
|
802
806
|
aria-label={`${expanded ? "Hide" : "Show"} full content for queued prompt ${index + 1}`}
|
|
803
|
-
className="mt-1 inline-flex min-h-7 min-w-0 max-w-full items-center gap-1 whitespace-normal rounded-md text-left text-og-xs font-medium text-fg outline-
|
|
807
|
+
className="mt-1 inline-flex min-h-7 min-w-0 max-w-full items-center gap-1 whitespace-normal rounded-md text-left text-og-xs font-medium text-fg outline-hidden focus-visible:ring-2 focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]"
|
|
804
808
|
data-testid={`queue-prompt-disclosure-${index + 1}`}
|
|
805
809
|
onClick={() => {
|
|
806
810
|
const next = !expanded;
|
|
@@ -963,7 +967,7 @@ function SortableQueueRow({
|
|
|
963
967
|
onClick={onSteer}
|
|
964
968
|
aria-label={`Steer queued prompt ${index + 1}`}
|
|
965
969
|
title="Steer — interrupt the current turn and send this message now"
|
|
966
|
-
className="inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-og-control font-medium text-fg outline-
|
|
970
|
+
className="inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-og-control font-medium text-fg outline-hidden transition-[background-color] hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:min-h-[44px] pointer-coarse:min-w-[44px]"
|
|
967
971
|
>
|
|
968
972
|
{pending === "steer" ? (
|
|
969
973
|
<Loader2Icon className="size-3.5 animate-spin" />
|
|
@@ -978,7 +982,7 @@ function SortableQueueRow({
|
|
|
978
982
|
onClick={onDelete}
|
|
979
983
|
aria-label={`Delete queued prompt ${index + 1}`}
|
|
980
984
|
title="Delete this queued prompt"
|
|
981
|
-
className="inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-
|
|
985
|
+
className="inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-hidden transition-colors hover:bg-surface-2 hover:text-status-failed focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:size-[44px]"
|
|
982
986
|
>
|
|
983
987
|
{pending === "delete" ? (
|
|
984
988
|
<Loader2Icon className="size-3.5 animate-spin" />
|
|
@@ -992,7 +996,7 @@ function SortableQueueRow({
|
|
|
992
996
|
type="button"
|
|
993
997
|
disabled={pending !== null}
|
|
994
998
|
aria-label={`More actions for queued prompt ${index + 1}`}
|
|
995
|
-
className="inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-
|
|
999
|
+
className="inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-hidden transition-colors hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50 pointer-coarse:size-[44px]"
|
|
996
1000
|
>
|
|
997
1001
|
{pending && pending !== "steer" && pending !== "delete" ? (
|
|
998
1002
|
<Loader2Icon className="size-3.5 animate-spin" />
|
|
@@ -1012,7 +1016,7 @@ function SortableQueueRow({
|
|
|
1012
1016
|
{onEdit ? (
|
|
1013
1017
|
<>
|
|
1014
1018
|
<DropdownMenu.Item
|
|
1015
|
-
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-
|
|
1019
|
+
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-hidden focus:bg-surface-2 pointer-coarse:min-h-[44px]"
|
|
1016
1020
|
onSelect={onEdit}
|
|
1017
1021
|
>
|
|
1018
1022
|
<PencilIcon className="size-3.5" /> Edit in composer
|
|
@@ -1021,28 +1025,28 @@ function SortableQueueRow({
|
|
|
1021
1025
|
</>
|
|
1022
1026
|
) : null}
|
|
1023
1027
|
<DropdownMenu.Item
|
|
1024
|
-
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-
|
|
1028
|
+
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-hidden focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]"
|
|
1025
1029
|
disabled={index === 0}
|
|
1026
1030
|
onSelect={() => onMove(0)}
|
|
1027
1031
|
>
|
|
1028
1032
|
<ArrowUpToLineIcon className="size-3.5" /> Move to top
|
|
1029
1033
|
</DropdownMenu.Item>
|
|
1030
1034
|
<DropdownMenu.Item
|
|
1031
|
-
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-
|
|
1035
|
+
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-hidden focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]"
|
|
1032
1036
|
disabled={index === 0}
|
|
1033
1037
|
onSelect={() => onMove(index - 1)}
|
|
1034
1038
|
>
|
|
1035
1039
|
Move up
|
|
1036
1040
|
</DropdownMenu.Item>
|
|
1037
1041
|
<DropdownMenu.Item
|
|
1038
|
-
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-
|
|
1042
|
+
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-hidden focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]"
|
|
1039
1043
|
disabled={index === count - 1}
|
|
1040
1044
|
onSelect={() => onMove(index + 1)}
|
|
1041
1045
|
>
|
|
1042
1046
|
Move down
|
|
1043
1047
|
</DropdownMenu.Item>
|
|
1044
1048
|
<DropdownMenu.Item
|
|
1045
|
-
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-
|
|
1049
|
+
className="flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-hidden focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]"
|
|
1046
1050
|
disabled={index === count - 1}
|
|
1047
1051
|
onSelect={() => onMove(count - 1)}
|
|
1048
1052
|
>
|
|
@@ -70,7 +70,7 @@ export function QueueErrorAlert({
|
|
|
70
70
|
role="region"
|
|
71
71
|
aria-label="Queue error details"
|
|
72
72
|
tabIndex={0}
|
|
73
|
-
className="max-h-[min(5rem,20dvh)] min-w-0 max-w-full flex-[1_1_5rem] overflow-auto overscroll-contain whitespace-pre-wrap rounded-sm outline-
|
|
73
|
+
className="max-h-[min(5rem,20dvh)] min-w-0 max-w-full flex-[1_1_5rem] overflow-auto overscroll-contain whitespace-pre-wrap rounded-sm outline-hidden [overflow-wrap:anywhere] [unicode-bidi:plaintext] focus-visible:ring-2 focus-visible:ring-ring/40"
|
|
74
74
|
data-testid="queue-error-message"
|
|
75
75
|
dir="auto"
|
|
76
76
|
>
|
|
@@ -84,7 +84,7 @@ export function QueueErrorAlert({
|
|
|
84
84
|
}}
|
|
85
85
|
aria-label="Dismiss queue error and retry"
|
|
86
86
|
title="Retry loading the queue"
|
|
87
|
-
className="ms-auto inline-flex size-7 shrink-0 items-center justify-center self-start rounded-md outline-
|
|
87
|
+
className="ms-auto inline-flex size-7 shrink-0 items-center justify-center self-start rounded-md outline-hidden transition-colors hover:bg-surface-3 focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none pointer-coarse:size-[44px]"
|
|
88
88
|
>
|
|
89
89
|
<RotateCwIcon className="size-3.5" />
|
|
90
90
|
</button>
|