@opengeni/react 0.13.0 → 0.20.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 +129 -23
- package/dist/chunk-6BXBGJ3B.js +1956 -0
- package/dist/chunk-6BXBGJ3B.js.map +1 -0
- package/dist/chunk-6UT5OC3P.js +2133 -0
- package/dist/chunk-6UT5OC3P.js.map +1 -0
- package/dist/chunk-EBTT3MYN.js +92 -0
- package/dist/chunk-EBTT3MYN.js.map +1 -0
- package/dist/chunk-HHFA4AFX.js +425 -0
- package/dist/chunk-HHFA4AFX.js.map +1 -0
- package/dist/chunk-LAZ2A743.js +2393 -0
- package/dist/chunk-LAZ2A743.js.map +1 -0
- package/dist/chunk-MRSECXRP.js +563 -0
- package/dist/chunk-MRSECXRP.js.map +1 -0
- package/dist/chunk-TK7G6XLT.js +18 -0
- package/dist/chunk-TK7G6XLT.js.map +1 -0
- package/dist/composer-DvUaa5ki.d.ts +585 -0
- package/dist/composer.d.ts +6 -0
- package/dist/composer.js +56 -0
- package/dist/composer.js.map +1 -0
- package/dist/index.d.ts +642 -1080
- package/dist/index.js +7672 -8005
- package/dist/index.js.map +1 -1
- package/dist/machines.d.ts +412 -3
- package/dist/machines.js +25 -1
- package/dist/noto-sans-arabic-loader-IA2T4X2A.js +21 -0
- package/dist/noto-sans-arabic-loader-IA2T4X2A.js.map +1 -0
- package/dist/noto-sans-jp-loader.generated-HFGLYBR3.js +292 -0
- package/dist/noto-sans-jp-loader.generated-HFGLYBR3.js.map +1 -0
- package/dist/queue-surface-implementation-NQMV2ML3.js +890 -0
- package/dist/queue-surface-implementation-NQMV2ML3.js.map +1 -0
- package/dist/session-Gd4iVPYw.d.ts +425 -0
- package/dist/session-context-DIFFlXKc.d.ts +52 -0
- package/dist/session.d.ts +4 -0
- package/dist/session.js +50 -0
- package/dist/session.js.map +1 -0
- package/dist/use-composer-BCfm4mzX.d.ts +112 -0
- package/package.json +23 -4
- package/src/approvals.ts +5 -3
- package/src/client.ts +50 -1
- package/src/components/approval-surface.tsx +198 -0
- package/src/components/chat-composer.tsx +104 -751
- package/src/components/code-editor.tsx +104 -26
- package/src/components/command-palette.tsx +8 -2
- package/src/components/composer-transcription-control.tsx +211 -0
- package/src/components/composer.tsx +1536 -0
- package/src/components/desktop-viewer.tsx +3 -3
- package/src/components/enrollment-consent.tsx +2 -2
- package/src/components/file-browser.tsx +367 -29
- package/src/components/human-input-form.tsx +417 -0
- package/src/components/machine-card.tsx +82 -16
- package/src/components/machine-health-pill.tsx +68 -0
- package/src/components/machine-metrics.tsx +10 -24
- package/src/components/machines/health.ts +146 -0
- package/src/components/machines/machine-detail.tsx +220 -0
- package/src/components/machines/metric-history-chart.tsx +298 -0
- package/src/components/machines/metric-sparkline.tsx +76 -0
- package/src/components/machines/series.ts +113 -0
- package/src/components/machines-dashboard.tsx +16 -4
- package/src/components/message-timeline.tsx +15 -7
- package/src/components/model-picker.tsx +12 -3
- package/src/components/pierre-diff.tsx +32 -6
- package/src/components/queue-surface-implementation.tsx +1041 -0
- package/src/components/queue-surface-state.tsx +94 -0
- package/src/components/queue-surface.tsx +60 -0
- package/src/components/sandbox-files.tsx +230 -21
- package/src/components/sandbox-terminal.tsx +8 -2
- package/src/components/sandbox-workspace.tsx +489 -135
- package/src/components/session-status.tsx +0 -6
- package/src/components/workbench-changes.tsx +145 -50
- package/src/components/workspace-dock.tsx +329 -68
- package/src/composer.ts +60 -0
- package/src/hooks/internal.ts +115 -34
- package/src/hooks/use-composer.ts +635 -74
- package/src/hooks/use-human-input.ts +131 -0
- package/src/hooks/use-machine-chip.ts +2 -2
- package/src/hooks/use-machines.ts +27 -11
- package/src/hooks/use-sandbox-files.ts +310 -62
- package/src/hooks/use-sandbox-git.ts +154 -40
- package/src/hooks/use-sandbox-terminal.ts +28 -6
- package/src/hooks/use-session-capabilities.ts +38 -9
- package/src/hooks/use-session-control.ts +43 -15
- package/src/hooks/use-session-events.ts +523 -48
- package/src/hooks/use-session-lineage.ts +15 -6
- package/src/hooks/use-session.ts +10 -2
- package/src/hooks/use-slash-commands.ts +38 -38
- package/src/hooks/use-transcription.ts +757 -0
- package/src/hooks/use-turn-queue.ts +273 -77
- package/src/hooks/use-windowed-sections.ts +2 -2
- package/src/hooks/use-workspace-capture.ts +146 -40
- package/src/hooks/use-workspace-edit.ts +50 -14
- package/src/hooks/use-workspace-sessions.ts +3 -0
- package/src/human-input.ts +72 -0
- package/src/index.ts +88 -12
- package/src/lib/noto-sans-arabic-loader.ts +21 -0
- package/src/lib/noto-sans-jp-loader.generated.ts +295 -0
- package/src/lib/use-portal-token-style.ts +51 -0
- package/src/lib/use-unicode-fonts.ts +57 -0
- package/src/machines.ts +16 -0
- package/src/provider.tsx +163 -41
- package/src/session-context.ts +135 -0
- package/src/session.ts +79 -0
- package/src/timeline/parsers.ts +78 -6
- package/src/timeline/projection.ts +36 -6
- package/src/timeline/tool-renderers.tsx +41 -0
- package/src/timeline/turn-summary.tsx +2 -2
- package/src/timeline/types.ts +16 -8
- package/styles/index.css +78 -0
- package/styles/index.d.ts +2 -0
- package/styles/tokens.css +11 -6
- package/styles/tokens.d.ts +2 -0
- package/dist/chunk-NFYVQWIB.js +0 -1377
- package/dist/chunk-NFYVQWIB.js.map +0 -1
- package/dist/machines-CnlMb7E-.d.ts +0 -329
|
@@ -0,0 +1,890 @@
|
|
|
1
|
+
import {
|
|
2
|
+
QueueErrorAlert,
|
|
3
|
+
QueueStoppingStatus
|
|
4
|
+
} from "./chunk-EBTT3MYN.js";
|
|
5
|
+
|
|
6
|
+
// src/components/queue-surface-implementation.tsx
|
|
7
|
+
import {
|
|
8
|
+
DndContext,
|
|
9
|
+
DragOverlay,
|
|
10
|
+
PointerSensor,
|
|
11
|
+
closestCenter,
|
|
12
|
+
useSensor,
|
|
13
|
+
useSensors
|
|
14
|
+
} from "@dnd-kit/core";
|
|
15
|
+
import {
|
|
16
|
+
SortableContext,
|
|
17
|
+
arrayMove,
|
|
18
|
+
useSortable,
|
|
19
|
+
verticalListSortingStrategy
|
|
20
|
+
} from "@dnd-kit/sortable";
|
|
21
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
22
|
+
import {
|
|
23
|
+
ArrowDownToLineIcon,
|
|
24
|
+
ArrowUpToLineIcon,
|
|
25
|
+
ChevronDownIcon,
|
|
26
|
+
EllipsisIcon,
|
|
27
|
+
GripVerticalIcon,
|
|
28
|
+
Loader2Icon,
|
|
29
|
+
PencilIcon,
|
|
30
|
+
Trash2Icon,
|
|
31
|
+
ZapIcon
|
|
32
|
+
} from "lucide-react";
|
|
33
|
+
import {
|
|
34
|
+
useCallback,
|
|
35
|
+
useId,
|
|
36
|
+
useMemo,
|
|
37
|
+
useRef,
|
|
38
|
+
useState
|
|
39
|
+
} from "react";
|
|
40
|
+
import { DropdownMenu } from "radix-ui";
|
|
41
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
42
|
+
function queueComposerCheckoutEnabled(composer, readOnly) {
|
|
43
|
+
return !readOnly && composer !== void 0 && composer.draftPersistence !== "disabled";
|
|
44
|
+
}
|
|
45
|
+
function QueueSurface({
|
|
46
|
+
queue,
|
|
47
|
+
composer,
|
|
48
|
+
readOnly = false,
|
|
49
|
+
onRequestComposerFocus
|
|
50
|
+
}) {
|
|
51
|
+
const [open, setOpen] = useState(false);
|
|
52
|
+
const [replaceDraftFor, setReplaceDraftFor] = useState(null);
|
|
53
|
+
const [announcement, setAnnouncement] = useState("");
|
|
54
|
+
const [draggedTurnId, setDraggedTurnId] = useState(null);
|
|
55
|
+
const surfaceRef = useRef(null);
|
|
56
|
+
const [keyboardDrag, setKeyboardDrag] = useState(null);
|
|
57
|
+
const count = queue.queue.length;
|
|
58
|
+
const canEditInComposer = queueComposerCheckoutEnabled(composer, readOnly);
|
|
59
|
+
const collapsedPreview = useMemo(
|
|
60
|
+
() => queuePromptPreview(queue.queue[0]?.prompt ?? "", QUEUE_COLLAPSED_PREVIEW_CHARACTERS),
|
|
61
|
+
[queue.queue]
|
|
62
|
+
);
|
|
63
|
+
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }));
|
|
64
|
+
const displayedQueue = useMemo(() => {
|
|
65
|
+
if (!keyboardDrag) return queue.queue;
|
|
66
|
+
const oldIndex = queue.queue.findIndex((turn) => turn.id === keyboardDrag.turnId);
|
|
67
|
+
if (oldIndex < 0) return queue.queue;
|
|
68
|
+
return arrayMove(queue.queue, oldIndex, keyboardDrag.projectedIndex);
|
|
69
|
+
}, [keyboardDrag, queue.queue]);
|
|
70
|
+
const ids = useMemo(() => displayedQueue.map((turn) => turn.id), [displayedQueue]);
|
|
71
|
+
const moveToIndex = useCallback(
|
|
72
|
+
async (turnId, nextIndex) => {
|
|
73
|
+
const oldIndex = queue.queue.findIndex((turn) => turn.id === turnId);
|
|
74
|
+
if (oldIndex < 0) return;
|
|
75
|
+
const boundedIndex = Math.max(0, Math.min(nextIndex, queue.queue.length - 1));
|
|
76
|
+
if (oldIndex === boundedIndex) return;
|
|
77
|
+
const ordered = arrayMove(queue.queue, oldIndex, boundedIndex);
|
|
78
|
+
const beforeTurnId = ordered[boundedIndex + 1]?.id ?? null;
|
|
79
|
+
const moved = await queue.moveTurn(turnId, beforeTurnId);
|
|
80
|
+
setAnnouncement(
|
|
81
|
+
moved ? `Queued prompt moved to position ${boundedIndex + 1}.` : "The queue changed before that prompt could be moved. Refreshed server order."
|
|
82
|
+
);
|
|
83
|
+
if (moved) focusQueueTurn(surfaceRef.current, turnId);
|
|
84
|
+
},
|
|
85
|
+
[queue]
|
|
86
|
+
);
|
|
87
|
+
const onDragEnd = useCallback(
|
|
88
|
+
(event) => {
|
|
89
|
+
setDraggedTurnId(null);
|
|
90
|
+
const activeId = String(event.active.id);
|
|
91
|
+
const overId = event.over ? String(event.over.id) : null;
|
|
92
|
+
if (!overId || activeId === overId) {
|
|
93
|
+
setAnnouncement("Queued prompt returned to its original position.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const nextIndex = queue.queue.findIndex((turn) => turn.id === overId);
|
|
97
|
+
if (nextIndex >= 0) void moveToIndex(activeId, nextIndex);
|
|
98
|
+
},
|
|
99
|
+
[moveToIndex, queue.queue]
|
|
100
|
+
);
|
|
101
|
+
const onDragStart = useCallback(
|
|
102
|
+
(event) => {
|
|
103
|
+
setKeyboardDrag(null);
|
|
104
|
+
const turnId = String(event.active.id);
|
|
105
|
+
const position = queue.queue.findIndex((turn) => turn.id === turnId) + 1;
|
|
106
|
+
setDraggedTurnId(turnId);
|
|
107
|
+
setAnnouncement(`Dragging queued prompt ${position} of ${queue.queue.length}.`);
|
|
108
|
+
},
|
|
109
|
+
[queue.queue]
|
|
110
|
+
);
|
|
111
|
+
const onHandleKeyDown = useCallback(
|
|
112
|
+
(event, turnId) => {
|
|
113
|
+
const canonicalIndex = queue.queue.findIndex((turn) => turn.id === turnId);
|
|
114
|
+
if (canonicalIndex < 0) return;
|
|
115
|
+
if (!keyboardDrag) {
|
|
116
|
+
if (event.key !== " ") return;
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
setKeyboardDrag({ turnId, projectedIndex: canonicalIndex });
|
|
119
|
+
setAnnouncement(
|
|
120
|
+
`Lifted queued prompt ${canonicalIndex + 1} of ${count}. Use arrow keys to move it, then press Space to drop.`
|
|
121
|
+
);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (keyboardDrag.turnId !== turnId) return;
|
|
125
|
+
if (event.key === "Escape") {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
setKeyboardDrag(null);
|
|
128
|
+
setAnnouncement("Queue reorder cancelled.");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (event.key === " ") {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
const targetIndex = keyboardDrag.projectedIndex;
|
|
134
|
+
setAnnouncement(`Moving queued prompt to position ${targetIndex + 1}.`);
|
|
135
|
+
void moveToIndex(turnId, targetIndex).finally(() => setKeyboardDrag(null));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const direction = event.key === "ArrowUp" ? -1 : event.key === "ArrowDown" ? 1 : 0;
|
|
139
|
+
const edge = event.key === "Home" ? 0 : event.key === "End" ? count - 1 : null;
|
|
140
|
+
if (direction === 0 && edge === null) return;
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
const projectedIndex = Math.max(
|
|
143
|
+
0,
|
|
144
|
+
Math.min(edge ?? keyboardDrag.projectedIndex + direction, count - 1)
|
|
145
|
+
);
|
|
146
|
+
setKeyboardDrag({ turnId, projectedIndex });
|
|
147
|
+
setAnnouncement(`Queued prompt projected to position ${projectedIndex + 1} of ${count}.`);
|
|
148
|
+
},
|
|
149
|
+
[count, keyboardDrag, moveToIndex, queue.queue]
|
|
150
|
+
);
|
|
151
|
+
const edit = useCallback(
|
|
152
|
+
async (turn, replaceDraft) => {
|
|
153
|
+
if (!composer || !canEditInComposer) return;
|
|
154
|
+
const restored = await queue.editTurn(turn.id, {
|
|
155
|
+
expectedDraftRevision: composer.draftRevision,
|
|
156
|
+
replaceDraft
|
|
157
|
+
});
|
|
158
|
+
if (!restored) return;
|
|
159
|
+
composer.applyDraft(restored);
|
|
160
|
+
setReplaceDraftFor(null);
|
|
161
|
+
setAnnouncement("Queued prompt moved back to the composer for editing.");
|
|
162
|
+
window.requestAnimationFrame(() => {
|
|
163
|
+
if (onRequestComposerFocus) {
|
|
164
|
+
onRequestComposerFocus();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const input = document.querySelector(
|
|
168
|
+
'textarea[aria-label="Message the agent"]'
|
|
169
|
+
);
|
|
170
|
+
input?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
171
|
+
input?.focus();
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
[canEditInComposer, composer, onRequestComposerFocus, queue]
|
|
175
|
+
);
|
|
176
|
+
const requestEdit = useCallback(
|
|
177
|
+
(turn) => {
|
|
178
|
+
if (!composer || !canEditInComposer) return;
|
|
179
|
+
const draftDirty = composer.value.length > 0 || composer.restoredResources.length > 0 || (composer.draft?.tools.length ?? 0) > 0 || composer.draft?.sourceTurnId !== null && composer.draft?.sourceTurnId !== void 0;
|
|
180
|
+
if (draftDirty) {
|
|
181
|
+
setReplaceDraftFor(turn.id);
|
|
182
|
+
} else {
|
|
183
|
+
void edit(turn, false);
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
[canEditInComposer, composer, edit]
|
|
187
|
+
);
|
|
188
|
+
if (count === 0 && !queue.stoppingPreviousAttempt && !queue.error && !queue.mutationError)
|
|
189
|
+
return null;
|
|
190
|
+
return /* @__PURE__ */ jsxs(
|
|
191
|
+
"div",
|
|
192
|
+
{
|
|
193
|
+
ref: surfaceRef,
|
|
194
|
+
className: "mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6",
|
|
195
|
+
"data-testid": "queue-surface",
|
|
196
|
+
children: [
|
|
197
|
+
/* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-lg border border-border bg-surface/80 shadow-sm", children: [
|
|
198
|
+
queue.stoppingPreviousAttempt ? /* @__PURE__ */ jsx(QueueStoppingStatus, { queue, dividerAfter: true }) : null,
|
|
199
|
+
/* @__PURE__ */ jsxs(
|
|
200
|
+
"button",
|
|
201
|
+
{
|
|
202
|
+
type: "button",
|
|
203
|
+
className: "flex w-full min-w-0 flex-wrap items-center gap-2 px-3 py-2 text-left outline-none 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]",
|
|
204
|
+
onClick: () => setOpen((value) => !value),
|
|
205
|
+
"aria-description": !open && count > 0 ? collapsedPreview.summary : void 0,
|
|
206
|
+
"aria-expanded": open,
|
|
207
|
+
"aria-label": `${count} queued prompt${count === 1 ? "" : "s"}${readOnly ? " Read-only" : ""}`,
|
|
208
|
+
children: [
|
|
209
|
+
/* @__PURE__ */ jsx(
|
|
210
|
+
ChevronDownIcon,
|
|
211
|
+
{
|
|
212
|
+
"aria-hidden": "true",
|
|
213
|
+
className: `size-3.5 shrink-0 text-fg-subtle transition-transform ${open ? "rotate-180" : ""}`
|
|
214
|
+
}
|
|
215
|
+
),
|
|
216
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-fg", children: [
|
|
217
|
+
count,
|
|
218
|
+
" queued prompt",
|
|
219
|
+
count === 1 ? "" : "s"
|
|
220
|
+
] }),
|
|
221
|
+
readOnly ? /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded border border-border px-1.5 py-0.5 text-2xs text-fg-subtle", children: "Read-only" }) : null,
|
|
222
|
+
!open && count > 0 ? /* @__PURE__ */ jsx(
|
|
223
|
+
"span",
|
|
224
|
+
{
|
|
225
|
+
"aria-hidden": "true",
|
|
226
|
+
className: `max-w-full truncate text-fg-muted ${collapsedPreview.collapsedVisual === collapsedPreview.summary ? "min-w-0 flex-1 text-xs" : "shrink-0 text-[10px]"}`,
|
|
227
|
+
"data-testid": "queue-collapsed-preview",
|
|
228
|
+
dir: "auto",
|
|
229
|
+
children: collapsedPreview.collapsedVisual
|
|
230
|
+
}
|
|
231
|
+
) : null,
|
|
232
|
+
queue.loading ? /* @__PURE__ */ jsx(Loader2Icon, { className: "ml-auto size-3.5 animate-spin" }) : null
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
),
|
|
236
|
+
open && count > 0 && readOnly ? /* @__PURE__ */ jsx(
|
|
237
|
+
"ol",
|
|
238
|
+
{
|
|
239
|
+
className: "max-h-[min(30rem,60dvh)] divide-y divide-border overflow-y-auto overscroll-contain border-t border-border",
|
|
240
|
+
"aria-label": "Queued prompts",
|
|
241
|
+
"data-testid": "queue-list",
|
|
242
|
+
children: queue.queue.map((turn, index) => /* @__PURE__ */ jsx(
|
|
243
|
+
ReadOnlyQueueRow,
|
|
244
|
+
{
|
|
245
|
+
turn,
|
|
246
|
+
index,
|
|
247
|
+
onDisclosureChange: (expanded) => setAnnouncement(
|
|
248
|
+
`Full content for queued prompt ${index + 1} ${expanded ? "shown" : "hidden"}.`
|
|
249
|
+
)
|
|
250
|
+
},
|
|
251
|
+
turn.id
|
|
252
|
+
))
|
|
253
|
+
}
|
|
254
|
+
) : null,
|
|
255
|
+
open && count > 0 && !readOnly ? /* @__PURE__ */ jsxs(
|
|
256
|
+
DndContext,
|
|
257
|
+
{
|
|
258
|
+
sensors,
|
|
259
|
+
collisionDetection: closestCenter,
|
|
260
|
+
modifiers: [verticalOnly],
|
|
261
|
+
onDragStart,
|
|
262
|
+
onDragCancel: () => {
|
|
263
|
+
setDraggedTurnId(null);
|
|
264
|
+
setAnnouncement("Queue reorder cancelled.");
|
|
265
|
+
},
|
|
266
|
+
onDragEnd,
|
|
267
|
+
children: [
|
|
268
|
+
/* @__PURE__ */ jsx(SortableContext, { items: ids, strategy: verticalListSortingStrategy, children: /* @__PURE__ */ jsx(
|
|
269
|
+
"ol",
|
|
270
|
+
{
|
|
271
|
+
className: "max-h-[min(30rem,60dvh)] divide-y divide-border overflow-y-auto overscroll-contain border-t border-border",
|
|
272
|
+
"aria-label": "Queued prompts",
|
|
273
|
+
"data-testid": "queue-list",
|
|
274
|
+
children: displayedQueue.map((turn, index) => /* @__PURE__ */ jsx(
|
|
275
|
+
SortableQueueRow,
|
|
276
|
+
{
|
|
277
|
+
turn,
|
|
278
|
+
index,
|
|
279
|
+
count,
|
|
280
|
+
pending: queue.mutationFor(turn.id),
|
|
281
|
+
confirmingReplace: replaceDraftFor === turn.id,
|
|
282
|
+
keyboardDragging: keyboardDrag?.turnId === turn.id,
|
|
283
|
+
onHandleKeyDown: (event) => onHandleKeyDown(event, turn.id),
|
|
284
|
+
onMove: (nextIndex) => void moveToIndex(turn.id, nextIndex),
|
|
285
|
+
onEdit: canEditInComposer ? () => requestEdit(turn) : void 0,
|
|
286
|
+
onConfirmReplace: () => void edit(turn, true),
|
|
287
|
+
onCancelReplace: () => setReplaceDraftFor(null),
|
|
288
|
+
onSteer: () => {
|
|
289
|
+
void queue.steerTurn(turn.id).then((steered) => {
|
|
290
|
+
setAnnouncement(
|
|
291
|
+
steered ? "Queued prompt is now the next direction." : "That prompt changed before it could be steered."
|
|
292
|
+
);
|
|
293
|
+
if (steered) {
|
|
294
|
+
focusAfterQueueRemoval(surfaceRef.current, index, onRequestComposerFocus);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
},
|
|
298
|
+
onDelete: () => {
|
|
299
|
+
void queue.removeTurn(turn.id).then((removed) => {
|
|
300
|
+
setAnnouncement(
|
|
301
|
+
removed ? "Queued prompt deleted." : "That prompt changed before it could be deleted."
|
|
302
|
+
);
|
|
303
|
+
if (removed) {
|
|
304
|
+
focusAfterQueueRemoval(surfaceRef.current, index, onRequestComposerFocus);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
},
|
|
308
|
+
onDisclosureChange: (expanded) => setAnnouncement(
|
|
309
|
+
`Full content for queued prompt ${index + 1} ${expanded ? "shown" : "hidden"}.`
|
|
310
|
+
)
|
|
311
|
+
},
|
|
312
|
+
turn.id
|
|
313
|
+
))
|
|
314
|
+
}
|
|
315
|
+
) }),
|
|
316
|
+
/* @__PURE__ */ jsx(DragOverlay, { modifiers: [verticalOnly], children: draggedTurnId ? /* @__PURE__ */ jsx(
|
|
317
|
+
"div",
|
|
318
|
+
{
|
|
319
|
+
className: "max-h-20 w-[min(36rem,calc(100vw-2rem))] max-w-[calc(100vw-2rem)] overflow-hidden rounded-md border border-brand/40 bg-surface px-3 py-2 text-xs text-fg shadow-lg",
|
|
320
|
+
"data-testid": "queue-drag-overlay",
|
|
321
|
+
children: /* @__PURE__ */ jsx(
|
|
322
|
+
"p",
|
|
323
|
+
{
|
|
324
|
+
"aria-hidden": "true",
|
|
325
|
+
className: "line-clamp-3 break-all whitespace-pre-wrap [unicode-bidi:plaintext]",
|
|
326
|
+
dir: "auto",
|
|
327
|
+
children: queuePromptPreview(
|
|
328
|
+
queue.queue.find((turn) => turn.id === draggedTurnId)?.prompt ?? "",
|
|
329
|
+
QUEUE_ROW_PREVIEW_CHARACTERS
|
|
330
|
+
).summary
|
|
331
|
+
}
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
) : null })
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
) : null,
|
|
338
|
+
queue.error || queue.mutationError ? /* @__PURE__ */ jsx(QueueErrorAlert, { queue, dividerBefore: true }) : null
|
|
339
|
+
] }),
|
|
340
|
+
/* @__PURE__ */ jsx("p", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: announcement })
|
|
341
|
+
]
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
var QUEUE_ROW_PREVIEW_CHARACTERS = 360;
|
|
346
|
+
var QUEUE_COLLAPSED_PREVIEW_CHARACTERS = 180;
|
|
347
|
+
var QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS = 32;
|
|
348
|
+
var QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS = 32;
|
|
349
|
+
var QUEUE_VISIBLE_END_IDENTITY_CHARACTERS = 18;
|
|
350
|
+
var QUEUE_PREVIEW_SEPARATOR = " \u2026 ";
|
|
351
|
+
var queuePreviewSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
352
|
+
var queuePromptNonRenderingCodePoint = /[\p{White_Space}\p{Control}\p{Default_Ignorable_Code_Point}]/u;
|
|
353
|
+
function queuePromptPreview(prompt, maxCharacters) {
|
|
354
|
+
const wholePromptProbe = samplePromptStart(prompt, maxCharacters + 1);
|
|
355
|
+
if (!wholePromptProbe.truncated && wholePromptProbe.characters <= maxCharacters) {
|
|
356
|
+
const summary2 = replaceLoneSurrogates(wholePromptProbe.value);
|
|
357
|
+
return hasVisiblePromptContent(summary2) ? {
|
|
358
|
+
summary: summary2,
|
|
359
|
+
collapsedVisual: summary2,
|
|
360
|
+
visibleStart: summary2,
|
|
361
|
+
visibleIdentity: null,
|
|
362
|
+
visibleIdentityLabel: null,
|
|
363
|
+
isFallback: false
|
|
364
|
+
} : fallbackPromptPreview(prompt.length, wholePromptProbe.value, wholePromptProbe.value);
|
|
365
|
+
}
|
|
366
|
+
const suffixCharacters = Math.min(Math.floor(maxCharacters / 3), 120);
|
|
367
|
+
const prefixCharacters = maxCharacters - codePointLength(QUEUE_PREVIEW_SEPARATOR) - suffixCharacters;
|
|
368
|
+
const prefixSample = samplePromptStart(
|
|
369
|
+
prompt,
|
|
370
|
+
prefixCharacters + QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS
|
|
371
|
+
);
|
|
372
|
+
const suffixSample = samplePromptEnd(
|
|
373
|
+
prompt,
|
|
374
|
+
suffixCharacters + QUEUE_PREVIEW_GRAPHEME_CONTEXT_CHARACTERS
|
|
375
|
+
);
|
|
376
|
+
const prefixSegments = segmentPromptSample(prefixSample.value);
|
|
377
|
+
const suffixSegments = segmentPromptSample(suffixSample.value);
|
|
378
|
+
if (prefixSample.truncated) prefixSegments.pop();
|
|
379
|
+
if (suffixSample.truncated) {
|
|
380
|
+
let ambiguousSegment = suffixSegments.shift();
|
|
381
|
+
while (ambiguousSegment?.endsWith("\u200D") && suffixSegments.length > 0) {
|
|
382
|
+
ambiguousSegment = suffixSegments.shift();
|
|
383
|
+
}
|
|
384
|
+
while (suffixSegments[0] && startsWithRegionalIndicator(suffixSegments[0])) {
|
|
385
|
+
suffixSegments.shift();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const prefix = takeWholeGraphemesFromStart(prefixSegments, prefixCharacters);
|
|
389
|
+
const suffix = takeWholeGraphemesFromEnd(suffixSegments, suffixCharacters);
|
|
390
|
+
const reference = boundedPromptSampleReference(
|
|
391
|
+
prompt.length,
|
|
392
|
+
prefixSample.value,
|
|
393
|
+
suffixSample.value
|
|
394
|
+
);
|
|
395
|
+
if (!hasVisiblePromptContent(prefix) && !hasVisiblePromptContent(suffix)) {
|
|
396
|
+
return fallbackPromptPreview(prompt.length, prefixSample.value, suffixSample.value);
|
|
397
|
+
}
|
|
398
|
+
const safeSuffix = hasVisiblePromptContent(suffix) ? suffix : promptPreviewFallbackLabel(reference);
|
|
399
|
+
const summary = `${prefix}${QUEUE_PREVIEW_SEPARATOR}${safeSuffix}`;
|
|
400
|
+
if (!hasVisiblePromptContent(prefix)) {
|
|
401
|
+
return {
|
|
402
|
+
summary,
|
|
403
|
+
collapsedVisual: summary,
|
|
404
|
+
visibleStart: safeSuffix,
|
|
405
|
+
visibleIdentity: null,
|
|
406
|
+
visibleIdentityLabel: null,
|
|
407
|
+
isFallback: false
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
const endIdentity = takeWholeGraphemesFromEnd(
|
|
411
|
+
suffixSegments,
|
|
412
|
+
QUEUE_VISIBLE_END_IDENTITY_CHARACTERS
|
|
413
|
+
);
|
|
414
|
+
return {
|
|
415
|
+
summary,
|
|
416
|
+
collapsedVisual: summary,
|
|
417
|
+
visibleStart: prefix,
|
|
418
|
+
visibleIdentity: hasVisiblePromptContent(endIdentity) ? endIdentity : `ref ${reference}`,
|
|
419
|
+
visibleIdentityLabel: hasVisiblePromptContent(endIdentity) ? "End" : "Safe boundary",
|
|
420
|
+
isFallback: false
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function fallbackPromptPreview(promptLength, startSample, endSample) {
|
|
424
|
+
const reference = boundedPromptSampleReference(promptLength, startSample, endSample);
|
|
425
|
+
const summary = promptPreviewFallbackLabel(reference);
|
|
426
|
+
return {
|
|
427
|
+
summary,
|
|
428
|
+
collapsedVisual: `Omitted \xB7 ${reference}`,
|
|
429
|
+
// The complete fallback remains the canonical accessible summary. Narrow
|
|
430
|
+
// collapsed/row layouts paint the bounded reference in a compact truthful
|
|
431
|
+
// form so ellipsis cannot hide the only identifying portion.
|
|
432
|
+
visibleStart: `Omitted \xB7 ${reference}`,
|
|
433
|
+
visibleIdentity: null,
|
|
434
|
+
visibleIdentityLabel: null,
|
|
435
|
+
isFallback: true
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
function promptPreviewFallbackLabel(reference) {
|
|
439
|
+
return `Content omitted at safe boundary \xB7 ref ${reference}`;
|
|
440
|
+
}
|
|
441
|
+
function boundedPromptSampleReference(promptLength, startSample, endSample) {
|
|
442
|
+
const head = samplePromptStart(startSample, QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS).value;
|
|
443
|
+
const tail = samplePromptEnd(endSample, QUEUE_PREVIEW_REFERENCE_SAMPLE_CHARACTERS).value;
|
|
444
|
+
let hash = 2166136261;
|
|
445
|
+
for (const value of [String(promptLength), head, tail]) {
|
|
446
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
447
|
+
hash ^= value.charCodeAt(index);
|
|
448
|
+
hash = Math.imul(hash, 16777619);
|
|
449
|
+
}
|
|
450
|
+
hash ^= 65535;
|
|
451
|
+
hash = Math.imul(hash, 16777619);
|
|
452
|
+
}
|
|
453
|
+
return (hash >>> 0).toString(16).padStart(8, "0").toUpperCase();
|
|
454
|
+
}
|
|
455
|
+
function hasVisiblePromptContent(value) {
|
|
456
|
+
for (const character of value) {
|
|
457
|
+
if (!queuePromptNonRenderingCodePoint.test(character)) return true;
|
|
458
|
+
}
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
function samplePromptStart(prompt, maxCharacters) {
|
|
462
|
+
let end = 0;
|
|
463
|
+
let characters = 0;
|
|
464
|
+
while (end < prompt.length && characters < maxCharacters) {
|
|
465
|
+
const first = prompt.charCodeAt(end);
|
|
466
|
+
end += isHighSurrogate(first) && end + 1 < prompt.length && isLowSurrogate(prompt.charCodeAt(end + 1)) ? 2 : 1;
|
|
467
|
+
characters += 1;
|
|
468
|
+
}
|
|
469
|
+
return { value: prompt.slice(0, end), characters, truncated: end < prompt.length };
|
|
470
|
+
}
|
|
471
|
+
function samplePromptEnd(prompt, maxCharacters) {
|
|
472
|
+
let start = prompt.length;
|
|
473
|
+
let characters = 0;
|
|
474
|
+
while (start > 0 && characters < maxCharacters) {
|
|
475
|
+
start -= 1;
|
|
476
|
+
if (isLowSurrogate(prompt.charCodeAt(start)) && start > 0 && isHighSurrogate(prompt.charCodeAt(start - 1))) {
|
|
477
|
+
start -= 1;
|
|
478
|
+
}
|
|
479
|
+
characters += 1;
|
|
480
|
+
}
|
|
481
|
+
return { value: prompt.slice(start), characters, truncated: start > 0 };
|
|
482
|
+
}
|
|
483
|
+
function segmentPromptSample(sample) {
|
|
484
|
+
return Array.from(
|
|
485
|
+
queuePreviewSegmenter.segment(replaceLoneSurrogates(sample)),
|
|
486
|
+
({ segment }) => segment
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
function replaceLoneSurrogates(value) {
|
|
490
|
+
let sanitized = "";
|
|
491
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
492
|
+
const current = value.charCodeAt(index);
|
|
493
|
+
if (isHighSurrogate(current) && index + 1 < value.length && isLowSurrogate(value.charCodeAt(index + 1))) {
|
|
494
|
+
sanitized += value.slice(index, index + 2);
|
|
495
|
+
index += 1;
|
|
496
|
+
} else if (isHighSurrogate(current) || isLowSurrogate(current)) {
|
|
497
|
+
sanitized += "\uFFFD";
|
|
498
|
+
} else {
|
|
499
|
+
sanitized += value[index];
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return sanitized;
|
|
503
|
+
}
|
|
504
|
+
function takeWholeGraphemesFromStart(segments, maxCharacters) {
|
|
505
|
+
const selected = [];
|
|
506
|
+
let characters = 0;
|
|
507
|
+
for (const segment of segments) {
|
|
508
|
+
const segmentCharacters = codePointLength(segment);
|
|
509
|
+
if (characters + segmentCharacters > maxCharacters) break;
|
|
510
|
+
selected.push(segment);
|
|
511
|
+
characters += segmentCharacters;
|
|
512
|
+
}
|
|
513
|
+
while (selected.at(-1)?.trim().length === 0) selected.pop();
|
|
514
|
+
return selected.join("");
|
|
515
|
+
}
|
|
516
|
+
function takeWholeGraphemesFromEnd(segments, maxCharacters) {
|
|
517
|
+
const selected = [];
|
|
518
|
+
let characters = 0;
|
|
519
|
+
for (let index = segments.length - 1; index >= 0; index -= 1) {
|
|
520
|
+
const segment = segments[index];
|
|
521
|
+
if (!segment) continue;
|
|
522
|
+
const segmentCharacters = codePointLength(segment);
|
|
523
|
+
if (characters + segmentCharacters > maxCharacters) break;
|
|
524
|
+
selected.unshift(segment);
|
|
525
|
+
characters += segmentCharacters;
|
|
526
|
+
}
|
|
527
|
+
while (selected[0]?.trim().length === 0) selected.shift();
|
|
528
|
+
while (selected.at(-1)?.trim().length === 0) selected.pop();
|
|
529
|
+
return selected.join("");
|
|
530
|
+
}
|
|
531
|
+
function codePointLength(value) {
|
|
532
|
+
let characters = 0;
|
|
533
|
+
for (const _character of value) characters += 1;
|
|
534
|
+
return characters;
|
|
535
|
+
}
|
|
536
|
+
function startsWithRegionalIndicator(value) {
|
|
537
|
+
const codePoint = value.codePointAt(0);
|
|
538
|
+
return codePoint !== void 0 && codePoint >= 127462 && codePoint <= 127487;
|
|
539
|
+
}
|
|
540
|
+
function isHighSurrogate(codeUnit) {
|
|
541
|
+
return codeUnit >= 55296 && codeUnit <= 56319;
|
|
542
|
+
}
|
|
543
|
+
function isLowSurrogate(codeUnit) {
|
|
544
|
+
return codeUnit >= 56320 && codeUnit <= 57343;
|
|
545
|
+
}
|
|
546
|
+
function QueuePrompt({
|
|
547
|
+
prompt,
|
|
548
|
+
index,
|
|
549
|
+
onDisclosureChange
|
|
550
|
+
}) {
|
|
551
|
+
const [expanded, setExpanded] = useState(false);
|
|
552
|
+
const fullContentId = useId();
|
|
553
|
+
const preview = useMemo(() => queuePromptPreview(prompt, QUEUE_ROW_PREVIEW_CHARACTERS), [prompt]);
|
|
554
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full min-w-0 max-w-full", children: [
|
|
555
|
+
/* @__PURE__ */ jsx(
|
|
556
|
+
"div",
|
|
557
|
+
{
|
|
558
|
+
"aria-label": `Queued prompt ${index + 1} summary: ${preview.summary}`,
|
|
559
|
+
className: "max-w-full overflow-hidden text-xs leading-5 text-fg",
|
|
560
|
+
"data-testid": `queue-prompt-preview-${index + 1}`,
|
|
561
|
+
dir: "auto",
|
|
562
|
+
role: "note",
|
|
563
|
+
children: /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "flex min-w-0 max-w-full items-baseline gap-2 sm:block", children: [
|
|
564
|
+
/* @__PURE__ */ jsx(
|
|
565
|
+
"span",
|
|
566
|
+
{
|
|
567
|
+
className: `${preview.isFallback ? "" : "line-clamp-1 sm:line-clamp-2"} min-w-0 flex-1 whitespace-pre-wrap break-all [unicode-bidi:plaintext]`,
|
|
568
|
+
"data-testid": `queue-prompt-start-${index + 1}`,
|
|
569
|
+
dir: "auto",
|
|
570
|
+
children: preview.visibleStart
|
|
571
|
+
}
|
|
572
|
+
),
|
|
573
|
+
preview.visibleIdentity && preview.visibleIdentityLabel ? /* @__PURE__ */ jsxs(
|
|
574
|
+
"span",
|
|
575
|
+
{
|
|
576
|
+
className: "flex min-w-0 max-w-[70%] shrink-0 items-center gap-1 text-2xs leading-4 text-fg-muted sm:mt-0.5 sm:max-w-full",
|
|
577
|
+
"data-testid": `queue-prompt-identity-row-${index + 1}`,
|
|
578
|
+
children: [
|
|
579
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 font-medium text-fg-subtle", children: preview.visibleIdentityLabel }),
|
|
580
|
+
/* @__PURE__ */ jsx(
|
|
581
|
+
"span",
|
|
582
|
+
{
|
|
583
|
+
className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap font-mono [unicode-bidi:plaintext]",
|
|
584
|
+
"data-testid": `queue-prompt-identity-${index + 1}`,
|
|
585
|
+
dir: "auto",
|
|
586
|
+
children: preview.visibleIdentity
|
|
587
|
+
}
|
|
588
|
+
)
|
|
589
|
+
]
|
|
590
|
+
}
|
|
591
|
+
) : null
|
|
592
|
+
] })
|
|
593
|
+
}
|
|
594
|
+
),
|
|
595
|
+
/* @__PURE__ */ jsxs(
|
|
596
|
+
"button",
|
|
597
|
+
{
|
|
598
|
+
type: "button",
|
|
599
|
+
"aria-controls": fullContentId,
|
|
600
|
+
"aria-expanded": expanded,
|
|
601
|
+
"aria-label": `${expanded ? "Hide" : "Show"} full content for queued prompt ${index + 1}`,
|
|
602
|
+
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-2xs font-medium text-fg-muted outline-none transition-colors hover:text-fg focus-visible:ring-2 focus-visible:ring-ring/40 pointer-coarse:min-h-[44px]",
|
|
603
|
+
"data-testid": `queue-prompt-disclosure-${index + 1}`,
|
|
604
|
+
onClick: () => {
|
|
605
|
+
const next = !expanded;
|
|
606
|
+
setExpanded(next);
|
|
607
|
+
onDisclosureChange(next);
|
|
608
|
+
},
|
|
609
|
+
children: [
|
|
610
|
+
/* @__PURE__ */ jsx(
|
|
611
|
+
ChevronDownIcon,
|
|
612
|
+
{
|
|
613
|
+
"aria-hidden": "true",
|
|
614
|
+
className: `size-3 shrink-0 transition-transform ${expanded ? "rotate-180" : ""}`
|
|
615
|
+
}
|
|
616
|
+
),
|
|
617
|
+
expanded ? "Hide full prompt" : "View full prompt"
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
),
|
|
621
|
+
expanded ? /* @__PURE__ */ jsx(
|
|
622
|
+
"pre",
|
|
623
|
+
{
|
|
624
|
+
id: fullContentId,
|
|
625
|
+
role: "region",
|
|
626
|
+
"aria-label": `Full content for queued prompt ${index + 1}`,
|
|
627
|
+
className: "mt-1.5 max-h-64 w-full min-w-0 max-w-full overflow-auto overscroll-contain rounded-md border border-border bg-surface-2/60 p-2 whitespace-pre-wrap break-all font-mono text-xs leading-5 text-fg [unicode-bidi:plaintext]",
|
|
628
|
+
"data-testid": `queue-prompt-full-${index + 1}`,
|
|
629
|
+
dir: "auto",
|
|
630
|
+
tabIndex: 0,
|
|
631
|
+
children: prompt
|
|
632
|
+
}
|
|
633
|
+
) : null
|
|
634
|
+
] });
|
|
635
|
+
}
|
|
636
|
+
function ReadOnlyQueueRow({
|
|
637
|
+
turn,
|
|
638
|
+
index,
|
|
639
|
+
onDisclosureChange
|
|
640
|
+
}) {
|
|
641
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex min-w-0 items-start gap-2 bg-surface px-3 py-2", children: [
|
|
642
|
+
/* @__PURE__ */ jsx("span", { className: "mt-1 shrink-0 font-mono text-2xs text-fg-subtle", children: index + 1 }),
|
|
643
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
644
|
+
/* @__PURE__ */ jsx(QueuePrompt, { prompt: turn.prompt, index, onDisclosureChange }),
|
|
645
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-2xs text-fg-subtle", children: [
|
|
646
|
+
turn.resources.length > 0 ? /* @__PURE__ */ jsxs("span", { className: "shrink-0", children: [
|
|
647
|
+
turn.resources.length,
|
|
648
|
+
" resource",
|
|
649
|
+
turn.resources.length === 1 ? "" : "s"
|
|
650
|
+
] }) : null,
|
|
651
|
+
turn.tools.length > 0 ? /* @__PURE__ */ jsxs("span", { className: "shrink-0", children: [
|
|
652
|
+
turn.tools.length,
|
|
653
|
+
" tool",
|
|
654
|
+
turn.tools.length === 1 ? "" : "s"
|
|
655
|
+
] }) : null,
|
|
656
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: turn.model }),
|
|
657
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0", children: turn.reasoningEffort })
|
|
658
|
+
] })
|
|
659
|
+
] })
|
|
660
|
+
] });
|
|
661
|
+
}
|
|
662
|
+
function SortableQueueRow({
|
|
663
|
+
turn,
|
|
664
|
+
index,
|
|
665
|
+
count,
|
|
666
|
+
pending,
|
|
667
|
+
confirmingReplace,
|
|
668
|
+
keyboardDragging,
|
|
669
|
+
onHandleKeyDown,
|
|
670
|
+
onMove,
|
|
671
|
+
onEdit,
|
|
672
|
+
onConfirmReplace,
|
|
673
|
+
onCancelReplace,
|
|
674
|
+
onSteer,
|
|
675
|
+
onDelete,
|
|
676
|
+
onDisclosureChange
|
|
677
|
+
}) {
|
|
678
|
+
const sortable = useSortable({
|
|
679
|
+
id: turn.id,
|
|
680
|
+
disabled: pending !== null || keyboardDragging
|
|
681
|
+
});
|
|
682
|
+
return /* @__PURE__ */ jsxs(
|
|
683
|
+
"li",
|
|
684
|
+
{
|
|
685
|
+
"data-queue-turn-id": turn.id,
|
|
686
|
+
ref: sortable.setNodeRef,
|
|
687
|
+
style: {
|
|
688
|
+
transform: CSS.Transform.toString(sortable.transform),
|
|
689
|
+
transition: sortable.transition
|
|
690
|
+
},
|
|
691
|
+
className: `bg-surface ${sortable.isDragging || keyboardDragging ? "relative z-10 shadow-lg ring-1 ring-brand/40" : ""}`,
|
|
692
|
+
children: [
|
|
693
|
+
/* @__PURE__ */ jsxs("div", { className: "grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-start gap-x-1.5 px-2 py-1.5 sm:grid-cols-[auto_auto_minmax(0,1fr)_auto] sm:gap-x-2 sm:px-3 sm:py-2", children: [
|
|
694
|
+
/* @__PURE__ */ jsx(
|
|
695
|
+
"button",
|
|
696
|
+
{
|
|
697
|
+
"data-queue-handle": true,
|
|
698
|
+
ref: sortable.setActivatorNodeRef,
|
|
699
|
+
type: "button",
|
|
700
|
+
...sortable.attributes,
|
|
701
|
+
...sortable.listeners,
|
|
702
|
+
onKeyDown: onHandleKeyDown,
|
|
703
|
+
disabled: pending !== null,
|
|
704
|
+
className: "col-start-1 row-start-1 mt-0.5 inline-flex size-7 shrink-0 touch-none items-center justify-center rounded-md text-fg-subtle hover:bg-surface-2 hover:text-fg focus-visible:ring-2 focus-visible:ring-ring/40 pointer-coarse:size-[44px]",
|
|
705
|
+
"aria-label": `Reorder queued prompt ${index + 1}`,
|
|
706
|
+
title: "Drag to reorder. Press Space, arrows, then Space to drop.",
|
|
707
|
+
children: /* @__PURE__ */ jsx(GripVerticalIcon, { className: "size-3.5" })
|
|
708
|
+
}
|
|
709
|
+
),
|
|
710
|
+
/* @__PURE__ */ jsx("span", { className: "col-start-2 row-start-1 mt-1 shrink-0 font-mono text-2xs text-fg-subtle", children: index + 1 }),
|
|
711
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-full row-start-2 min-w-0 sm:col-span-1 sm:col-start-3 sm:row-start-1", children: [
|
|
712
|
+
/* @__PURE__ */ jsx(QueuePrompt, { prompt: turn.prompt, index, onDisclosureChange }),
|
|
713
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap text-2xs text-fg-subtle", children: [
|
|
714
|
+
turn.resources.length > 0 ? /* @__PURE__ */ jsxs("span", { className: "shrink-0", children: [
|
|
715
|
+
turn.resources.length,
|
|
716
|
+
" resource",
|
|
717
|
+
turn.resources.length === 1 ? "" : "s"
|
|
718
|
+
] }) : null,
|
|
719
|
+
turn.tools.length > 0 ? /* @__PURE__ */ jsxs("span", { className: "shrink-0", children: [
|
|
720
|
+
turn.tools.length,
|
|
721
|
+
" tool",
|
|
722
|
+
turn.tools.length === 1 ? "" : "s"
|
|
723
|
+
] }) : null,
|
|
724
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: turn.model }),
|
|
725
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0", children: turn.reasoningEffort })
|
|
726
|
+
] })
|
|
727
|
+
] }),
|
|
728
|
+
/* @__PURE__ */ jsxs("div", { className: "col-span-full row-start-3 flex min-w-0 items-start justify-end gap-1.5 sm:col-span-1 sm:col-start-4 sm:row-start-1 sm:gap-2", children: [
|
|
729
|
+
/* @__PURE__ */ jsxs(
|
|
730
|
+
"button",
|
|
731
|
+
{
|
|
732
|
+
type: "button",
|
|
733
|
+
disabled: pending !== null,
|
|
734
|
+
onClick: onSteer,
|
|
735
|
+
"aria-label": `Steer queued prompt ${index + 1}`,
|
|
736
|
+
title: "Make this the next direction",
|
|
737
|
+
className: "inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-xs font-medium outline-none transition-colors 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]",
|
|
738
|
+
children: [
|
|
739
|
+
pending === "steer" ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsx(ZapIcon, { className: "size-3.5" }),
|
|
740
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Steer" })
|
|
741
|
+
]
|
|
742
|
+
}
|
|
743
|
+
),
|
|
744
|
+
/* @__PURE__ */ jsx(
|
|
745
|
+
"button",
|
|
746
|
+
{
|
|
747
|
+
type: "button",
|
|
748
|
+
disabled: pending !== null,
|
|
749
|
+
onClick: onDelete,
|
|
750
|
+
"aria-label": `Delete queued prompt ${index + 1}`,
|
|
751
|
+
title: "Delete this queued prompt",
|
|
752
|
+
className: "inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-none 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]",
|
|
753
|
+
children: pending === "delete" ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsx(Trash2Icon, { className: "size-3.5" })
|
|
754
|
+
}
|
|
755
|
+
),
|
|
756
|
+
/* @__PURE__ */ jsxs(DropdownMenu.Root, { children: [
|
|
757
|
+
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
758
|
+
"button",
|
|
759
|
+
{
|
|
760
|
+
type: "button",
|
|
761
|
+
disabled: pending !== null,
|
|
762
|
+
"aria-label": `More actions for queued prompt ${index + 1}`,
|
|
763
|
+
className: "inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-none 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]",
|
|
764
|
+
children: pending && pending !== "steer" && pending !== "delete" ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsx(EllipsisIcon, { className: "size-3.5" })
|
|
765
|
+
}
|
|
766
|
+
) }),
|
|
767
|
+
/* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsxs(
|
|
768
|
+
DropdownMenu.Content,
|
|
769
|
+
{
|
|
770
|
+
align: "end",
|
|
771
|
+
sideOffset: 4,
|
|
772
|
+
className: "z-50 w-48 max-w-[calc(100vw-16px)] rounded-md border border-border bg-surface p-1 text-xs text-fg shadow-lg",
|
|
773
|
+
"data-testid": `queue-actions-menu-${index + 1}`,
|
|
774
|
+
children: [
|
|
775
|
+
onEdit ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
776
|
+
/* @__PURE__ */ jsxs(
|
|
777
|
+
DropdownMenu.Item,
|
|
778
|
+
{
|
|
779
|
+
className: "flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 pointer-coarse:min-h-[44px]",
|
|
780
|
+
onSelect: onEdit,
|
|
781
|
+
children: [
|
|
782
|
+
/* @__PURE__ */ jsx(PencilIcon, { className: "size-3.5" }),
|
|
783
|
+
" Edit in composer"
|
|
784
|
+
]
|
|
785
|
+
}
|
|
786
|
+
),
|
|
787
|
+
/* @__PURE__ */ jsx(DropdownMenu.Separator, { className: "my-1 h-px bg-border" })
|
|
788
|
+
] }) : null,
|
|
789
|
+
/* @__PURE__ */ jsxs(
|
|
790
|
+
DropdownMenu.Item,
|
|
791
|
+
{
|
|
792
|
+
className: "flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]",
|
|
793
|
+
disabled: index === 0,
|
|
794
|
+
onSelect: () => onMove(0),
|
|
795
|
+
children: [
|
|
796
|
+
/* @__PURE__ */ jsx(ArrowUpToLineIcon, { className: "size-3.5" }),
|
|
797
|
+
" Move to top"
|
|
798
|
+
]
|
|
799
|
+
}
|
|
800
|
+
),
|
|
801
|
+
/* @__PURE__ */ jsx(
|
|
802
|
+
DropdownMenu.Item,
|
|
803
|
+
{
|
|
804
|
+
className: "flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]",
|
|
805
|
+
disabled: index === 0,
|
|
806
|
+
onSelect: () => onMove(index - 1),
|
|
807
|
+
children: "Move up"
|
|
808
|
+
}
|
|
809
|
+
),
|
|
810
|
+
/* @__PURE__ */ jsx(
|
|
811
|
+
DropdownMenu.Item,
|
|
812
|
+
{
|
|
813
|
+
className: "flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]",
|
|
814
|
+
disabled: index === count - 1,
|
|
815
|
+
onSelect: () => onMove(index + 1),
|
|
816
|
+
children: "Move down"
|
|
817
|
+
}
|
|
818
|
+
),
|
|
819
|
+
/* @__PURE__ */ jsxs(
|
|
820
|
+
DropdownMenu.Item,
|
|
821
|
+
{
|
|
822
|
+
className: "flex min-w-0 cursor-default items-center gap-2 whitespace-normal break-words rounded-sm px-2 py-1.5 outline-none focus:bg-surface-2 data-[disabled]:opacity-50 pointer-coarse:min-h-[44px]",
|
|
823
|
+
disabled: index === count - 1,
|
|
824
|
+
onSelect: () => onMove(count - 1),
|
|
825
|
+
children: [
|
|
826
|
+
/* @__PURE__ */ jsx(ArrowDownToLineIcon, { className: "size-3.5" }),
|
|
827
|
+
" Move to bottom"
|
|
828
|
+
]
|
|
829
|
+
}
|
|
830
|
+
)
|
|
831
|
+
]
|
|
832
|
+
}
|
|
833
|
+
) })
|
|
834
|
+
] })
|
|
835
|
+
] })
|
|
836
|
+
] }),
|
|
837
|
+
confirmingReplace ? /* @__PURE__ */ jsxs("div", { className: "mx-3 mb-2 rounded-md border border-status-waiting/30 bg-status-waiting/10 p-2 text-xs text-fg", children: [
|
|
838
|
+
/* @__PURE__ */ jsx("p", { children: "Your composer already has a draft. Replace it with this queued prompt?" }),
|
|
839
|
+
/* @__PURE__ */ jsx("p", { className: "mt-0.5 text-fg-muted", children: "The current draft will be permanently discarded; this queued prompt is preserved until you confirm." }),
|
|
840
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-end gap-1.5", children: [
|
|
841
|
+
/* @__PURE__ */ jsx(
|
|
842
|
+
"button",
|
|
843
|
+
{
|
|
844
|
+
type: "button",
|
|
845
|
+
className: "rounded-md px-2 py-1 font-medium hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring/40",
|
|
846
|
+
onClick: onCancelReplace,
|
|
847
|
+
children: "Keep current draft"
|
|
848
|
+
}
|
|
849
|
+
),
|
|
850
|
+
/* @__PURE__ */ jsx(
|
|
851
|
+
"button",
|
|
852
|
+
{
|
|
853
|
+
type: "button",
|
|
854
|
+
className: "rounded-md bg-brand px-2 py-1 font-medium text-white hover:bg-brand/90 focus-visible:ring-2 focus-visible:ring-ring/40",
|
|
855
|
+
onClick: onConfirmReplace,
|
|
856
|
+
children: "Replace and edit"
|
|
857
|
+
}
|
|
858
|
+
)
|
|
859
|
+
] })
|
|
860
|
+
] }) : null
|
|
861
|
+
]
|
|
862
|
+
}
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
var verticalOnly = ({ transform }) => ({ ...transform, x: 0 });
|
|
866
|
+
function focusQueueTurn(surface, turnId) {
|
|
867
|
+
window.requestAnimationFrame(() => {
|
|
868
|
+
surface?.querySelector(`[data-queue-turn-id="${turnId}"] [data-queue-handle]`)?.focus();
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
function focusAfterQueueRemoval(surface, previousIndex, onRequestComposerFocus) {
|
|
872
|
+
window.requestAnimationFrame(() => {
|
|
873
|
+
const handles = surface?.querySelectorAll("[data-queue-handle]") ?? [];
|
|
874
|
+
const nearest = handles[Math.min(previousIndex, Math.max(0, handles.length - 1))];
|
|
875
|
+
if (nearest) {
|
|
876
|
+
nearest.focus();
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
if (onRequestComposerFocus) {
|
|
880
|
+
onRequestComposerFocus();
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
document.querySelector('textarea[aria-label="Message the agent"]')?.focus();
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
export {
|
|
887
|
+
QueueSurface,
|
|
888
|
+
queueComposerCheckoutEnabled
|
|
889
|
+
};
|
|
890
|
+
//# sourceMappingURL=queue-surface-implementation-NQMV2ML3.js.map
|