@tangle-network/agent-app 0.45.66 → 0.46.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assistant/index.js +3 -3
- package/dist/chat-react/index.js +2 -2
- package/dist/chunk-2RTYQU4W.js +441 -0
- package/dist/chunk-2RTYQU4W.js.map +1 -0
- package/dist/{chunk-23J72UUA.js → chunk-DINGA2MO.js} +94 -560
- package/dist/chunk-DINGA2MO.js.map +1 -0
- package/dist/{chunk-AWM4H5XR.js → chunk-MBKNKAN2.js} +6 -4
- package/dist/{chunk-AWM4H5XR.js.map → chunk-MBKNKAN2.js.map} +1 -1
- package/dist/chunk-YDOQE47G.js +518 -0
- package/dist/chunk-YDOQE47G.js.map +1 -0
- package/dist/studio/generation.d.ts +14 -23
- package/dist/studio/index.d.ts +1 -0
- package/dist/studio/index.js +27 -15
- package/dist/studio/model-options.d.ts +61 -0
- package/dist/studio-react/composer-option-controls.d.ts +140 -0
- package/dist/studio-react/generation-notice.d.ts +18 -0
- package/dist/studio-react/index.d.ts +5 -9
- package/dist/studio-react/index.js +912 -630
- package/dist/studio-react/index.js.map +1 -1
- package/dist/studio-react/studio-composer.d.ts +34 -0
- package/dist/studio-react/studio.css +51 -0
- package/dist/theme/tokens.css +18 -0
- package/dist/web-react/index.js +11 -11
- package/package.json +1 -1
- package/dist/chunk-23J72UUA.js.map +0 -1
- package/dist/chunk-E2CWFUUP.js +0 -250
- package/dist/chunk-E2CWFUUP.js.map +0 -1
- package/dist/chunk-MLG6XKPV.js +0 -44
- package/dist/chunk-MLG6XKPV.js.map +0 -1
- package/dist/studio-react/avatar-composer.d.ts +0 -8
- package/dist/studio-react/composer-hero.d.ts +0 -10
- package/dist/studio-react/composer-shell.d.ts +0 -18
- package/dist/studio-react/image-composer.d.ts +0 -8
- package/dist/studio-react/speech-composer.d.ts +0 -4
- package/dist/studio-react/transcription-composer.d.ts +0 -12
- package/dist/studio-react/video-composer.d.ts +0 -10
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
CheckGlyph,
|
|
3
|
+
EffortPicker,
|
|
4
|
+
ModelPicker,
|
|
5
|
+
OVERLAY_SHADOW,
|
|
6
|
+
PopoverSurface,
|
|
7
|
+
pickerRootClass,
|
|
8
|
+
usePopover
|
|
9
|
+
} from "./chunk-YDOQE47G.js";
|
|
4
10
|
import {
|
|
5
11
|
ATTACHMENT_ACCEPT,
|
|
6
12
|
ATTACHMENT_MAX_COUNT,
|
|
@@ -18,461 +24,6 @@ import {
|
|
|
18
24
|
snapModelToHarness
|
|
19
25
|
} from "./chunk-TH7L265V.js";
|
|
20
26
|
|
|
21
|
-
// src/web-react/controls.tsx
|
|
22
|
-
import {
|
|
23
|
-
useCallback,
|
|
24
|
-
useEffect,
|
|
25
|
-
useId,
|
|
26
|
-
useLayoutEffect,
|
|
27
|
-
useMemo,
|
|
28
|
-
useRef,
|
|
29
|
-
useState
|
|
30
|
-
} from "react";
|
|
31
|
-
import { createPortal } from "react-dom";
|
|
32
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
33
|
-
function ChevronDown({ className }) {
|
|
34
|
-
return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
|
|
35
|
-
}
|
|
36
|
-
function SearchGlyph({ className }) {
|
|
37
|
-
return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
38
|
-
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
39
|
-
/* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
|
|
40
|
-
] });
|
|
41
|
-
}
|
|
42
|
-
function SparkleGlyph({ className }) {
|
|
43
|
-
return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3M5.6 5.6l2.1 2.1m8.6 8.6 2.1 2.1m0-12.8-2.1 2.1M7.7 16.3l-2.1 2.1" }) });
|
|
44
|
-
}
|
|
45
|
-
function BrainGlyph({ className }) {
|
|
46
|
-
return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
47
|
-
/* @__PURE__ */ jsx("path", { d: "M12 18V5" }),
|
|
48
|
-
/* @__PURE__ */ jsx("path", { d: "M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4" }),
|
|
49
|
-
/* @__PURE__ */ jsx("path", { d: "M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5" }),
|
|
50
|
-
/* @__PURE__ */ jsx("path", { d: "M17.997 5.125a4 4 0 0 1 2.526 5.77" }),
|
|
51
|
-
/* @__PURE__ */ jsx("path", { d: "M18 18a4 4 0 0 0 2-7.464" }),
|
|
52
|
-
/* @__PURE__ */ jsx("path", { d: "M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517" }),
|
|
53
|
-
/* @__PURE__ */ jsx("path", { d: "M6 18a4 4 0 0 1-2-7.464" }),
|
|
54
|
-
/* @__PURE__ */ jsx("path", { d: "M6.003 5.125a4 4 0 0 0-2.526 5.77" })
|
|
55
|
-
] });
|
|
56
|
-
}
|
|
57
|
-
function CheckGlyph({ className }) {
|
|
58
|
-
return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
|
|
59
|
-
}
|
|
60
|
-
function usePopover(open, setOpen) {
|
|
61
|
-
const containerRef = useRef(null);
|
|
62
|
-
const triggerRef = useRef(null);
|
|
63
|
-
const panelRef = useRef(null);
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
if (!open) return;
|
|
66
|
-
function onMouseDown(e) {
|
|
67
|
-
const target = e.target;
|
|
68
|
-
if (containerRef.current?.contains(target)) return;
|
|
69
|
-
const panel = panelRef.current;
|
|
70
|
-
if (panel?.contains(target)) return;
|
|
71
|
-
const ownPath = panel?.getAttribute(POPOVER_SURFACE_ATTR);
|
|
72
|
-
const hitPath = target instanceof Element ? target.closest(`[${POPOVER_SURFACE_ATTR}]`)?.getAttribute(POPOVER_SURFACE_ATTR) : null;
|
|
73
|
-
if (ownPath && hitPath && (hitPath === ownPath || hitPath.startsWith(`${ownPath}${POPOVER_PATH_SEPARATOR}`))) return;
|
|
74
|
-
setOpen(false);
|
|
75
|
-
}
|
|
76
|
-
function onKeyDown(e) {
|
|
77
|
-
if (e.key === "Escape") {
|
|
78
|
-
setOpen(false);
|
|
79
|
-
triggerRef.current?.focus();
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
document.addEventListener("mousedown", onMouseDown);
|
|
83
|
-
document.addEventListener("keydown", onKeyDown);
|
|
84
|
-
return () => {
|
|
85
|
-
document.removeEventListener("mousedown", onMouseDown);
|
|
86
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
87
|
-
};
|
|
88
|
-
}, [open, setOpen]);
|
|
89
|
-
return {
|
|
90
|
-
containerRef,
|
|
91
|
-
triggerRef,
|
|
92
|
-
panelRef,
|
|
93
|
-
triggerProps: {
|
|
94
|
-
ref: triggerRef,
|
|
95
|
-
"aria-haspopup": true,
|
|
96
|
-
"aria-expanded": open
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
var POPOVER_GAP = 8;
|
|
101
|
-
var POPOVER_VIEWPORT_MARGIN = 16;
|
|
102
|
-
var POPOVER_MIN_HEIGHT = 120;
|
|
103
|
-
var POPOVER_SURFACE_ATTR = "data-agent-app-popover";
|
|
104
|
-
var POPOVER_PATH_SEPARATOR = "/";
|
|
105
|
-
var useBrowserLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
|
|
106
|
-
function PopoverSurface({
|
|
107
|
-
open,
|
|
108
|
-
triggerRef,
|
|
109
|
-
panelRef,
|
|
110
|
-
className,
|
|
111
|
-
role,
|
|
112
|
-
id,
|
|
113
|
-
matchTriggerWidth,
|
|
114
|
-
children
|
|
115
|
-
}) {
|
|
116
|
-
const surfaceId = useId();
|
|
117
|
-
const [style, setStyle] = useState(() => ({
|
|
118
|
-
position: "fixed",
|
|
119
|
-
top: 0,
|
|
120
|
-
left: 0,
|
|
121
|
-
visibility: "hidden"
|
|
122
|
-
}));
|
|
123
|
-
const place = useCallback(() => {
|
|
124
|
-
const trigger = triggerRef.current;
|
|
125
|
-
const panel = panelRef.current;
|
|
126
|
-
if (!trigger || !panel) return;
|
|
127
|
-
const anchor = trigger.getBoundingClientRect();
|
|
128
|
-
const viewportWidth = window.innerWidth;
|
|
129
|
-
const viewportHeight = window.innerHeight;
|
|
130
|
-
const contentHeight = panel.scrollHeight;
|
|
131
|
-
const panelWidth = panel.offsetWidth;
|
|
132
|
-
const roomAbove = anchor.top - POPOVER_GAP - POPOVER_VIEWPORT_MARGIN;
|
|
133
|
-
const roomBelow = viewportHeight - anchor.bottom - POPOVER_GAP - POPOVER_VIEWPORT_MARGIN;
|
|
134
|
-
const above = contentHeight <= roomAbove || roomAbove >= roomBelow;
|
|
135
|
-
const maxHeight = Math.max(POPOVER_MIN_HEIGHT, above ? roomAbove : roomBelow);
|
|
136
|
-
const height = Math.min(contentHeight, maxHeight);
|
|
137
|
-
const top = above ? Math.max(POPOVER_VIEWPORT_MARGIN, anchor.top - POPOVER_GAP - height) : anchor.bottom + POPOVER_GAP;
|
|
138
|
-
const rightBound = Math.max(POPOVER_VIEWPORT_MARGIN, viewportWidth - panelWidth - POPOVER_VIEWPORT_MARGIN);
|
|
139
|
-
const left = Math.min(Math.max(POPOVER_VIEWPORT_MARGIN, anchor.left), rightBound);
|
|
140
|
-
setStyle({
|
|
141
|
-
position: "fixed",
|
|
142
|
-
top,
|
|
143
|
-
left,
|
|
144
|
-
maxHeight,
|
|
145
|
-
visibility: "visible",
|
|
146
|
-
...matchTriggerWidth ? { minWidth: anchor.width } : {}
|
|
147
|
-
});
|
|
148
|
-
}, [matchTriggerWidth, panelRef, triggerRef]);
|
|
149
|
-
useBrowserLayoutEffect(() => {
|
|
150
|
-
if (!open) {
|
|
151
|
-
setStyle({ position: "fixed", top: 0, left: 0, visibility: "hidden" });
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
place();
|
|
155
|
-
}, [open, place]);
|
|
156
|
-
useEffect(() => {
|
|
157
|
-
if (!open) return;
|
|
158
|
-
const onViewportChange = () => place();
|
|
159
|
-
window.addEventListener("scroll", onViewportChange, true);
|
|
160
|
-
window.addEventListener("resize", onViewportChange);
|
|
161
|
-
return () => {
|
|
162
|
-
window.removeEventListener("scroll", onViewportChange, true);
|
|
163
|
-
window.removeEventListener("resize", onViewportChange);
|
|
164
|
-
};
|
|
165
|
-
}, [open, place]);
|
|
166
|
-
if (!open || typeof document === "undefined") return null;
|
|
167
|
-
const ownerPath = triggerRef.current?.closest?.(`[${POPOVER_SURFACE_ATTR}]`)?.getAttribute(POPOVER_SURFACE_ATTR);
|
|
168
|
-
const path = ownerPath ? `${ownerPath}${POPOVER_PATH_SEPARATOR}${surfaceId}` : surfaceId;
|
|
169
|
-
return createPortal(
|
|
170
|
-
/* @__PURE__ */ jsx(
|
|
171
|
-
"div",
|
|
172
|
-
{
|
|
173
|
-
ref: panelRef,
|
|
174
|
-
id,
|
|
175
|
-
role,
|
|
176
|
-
style,
|
|
177
|
-
...{ [POPOVER_SURFACE_ATTR]: path },
|
|
178
|
-
className: `z-[1000] ${className ?? ""}`,
|
|
179
|
-
children
|
|
180
|
-
}
|
|
181
|
-
),
|
|
182
|
-
document.body
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
var POPOVER_OPTION_FOCUS = "focus-visible:[outline-offset:-2px]";
|
|
186
|
-
var OVERLAY_SHADOW = "shadow-[var(--shadow-overlay)]";
|
|
187
|
-
function pickerRootClass(fullWidth) {
|
|
188
|
-
return `relative ${fullWidth ? "flex w-full" : "inline-flex"}`;
|
|
189
|
-
}
|
|
190
|
-
function usePending() {
|
|
191
|
-
const [pending, setPending] = useState(false);
|
|
192
|
-
const inFlight = useRef(false);
|
|
193
|
-
const mounted = useRef(true);
|
|
194
|
-
useEffect(() => {
|
|
195
|
-
mounted.current = true;
|
|
196
|
-
return () => {
|
|
197
|
-
mounted.current = false;
|
|
198
|
-
};
|
|
199
|
-
}, []);
|
|
200
|
-
const run = (action) => {
|
|
201
|
-
if (inFlight.current) return;
|
|
202
|
-
let result;
|
|
203
|
-
try {
|
|
204
|
-
result = action();
|
|
205
|
-
} catch {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
if (!(result instanceof Promise)) return;
|
|
209
|
-
inFlight.current = true;
|
|
210
|
-
setPending(true);
|
|
211
|
-
void result.finally(() => {
|
|
212
|
-
inFlight.current = false;
|
|
213
|
-
if (mounted.current) setPending(false);
|
|
214
|
-
});
|
|
215
|
-
};
|
|
216
|
-
return { pending, run };
|
|
217
|
-
}
|
|
218
|
-
function formatPrice(p) {
|
|
219
|
-
if (!p) return void 0;
|
|
220
|
-
const n = Number(p);
|
|
221
|
-
if (isNaN(n) || n === 0) return void 0;
|
|
222
|
-
const perM = n * 1e6;
|
|
223
|
-
return perM >= 1 ? `$${perM.toFixed(0)}/M` : `$${perM.toFixed(2)}/M`;
|
|
224
|
-
}
|
|
225
|
-
function formatContext(len) {
|
|
226
|
-
if (!len) return void 0;
|
|
227
|
-
if (len >= 1e6) return `${(len / 1e6).toFixed(1)}M ctx`;
|
|
228
|
-
if (len >= 1e3) return `${Math.round(len / 1e3)}K ctx`;
|
|
229
|
-
return `${len} ctx`;
|
|
230
|
-
}
|
|
231
|
-
function SectionHeader({ children }) {
|
|
232
|
-
return /* @__PURE__ */ jsx("div", { className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children });
|
|
233
|
-
}
|
|
234
|
-
function ModelRow({
|
|
235
|
-
model,
|
|
236
|
-
selected,
|
|
237
|
-
onSelect,
|
|
238
|
-
renderProviderBadge
|
|
239
|
-
}) {
|
|
240
|
-
const price = formatPrice(model.pricing?.prompt);
|
|
241
|
-
const ctx = formatContext(model.contextLength);
|
|
242
|
-
return /* @__PURE__ */ jsxs(
|
|
243
|
-
"button",
|
|
244
|
-
{
|
|
245
|
-
type: "button",
|
|
246
|
-
onClick: onSelect,
|
|
247
|
-
className: `flex w-full items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm transition ${POPOVER_OPTION_FOCUS} ${selected ? "bg-primary/10 font-medium" : "hover:bg-accent"}`,
|
|
248
|
-
children: [
|
|
249
|
-
renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */ jsx(ProviderLogo, { provider: model.provider, size: 16 }),
|
|
250
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: model.name }),
|
|
251
|
-
!model.supportsTools && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded bg-secondary px-1.5 py-0.5 text-xs font-medium text-muted-foreground", children: "no tools" }),
|
|
252
|
-
/* @__PURE__ */ jsxs("span", { className: "ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground", children: [
|
|
253
|
-
ctx && /* @__PURE__ */ jsx("span", { children: ctx }),
|
|
254
|
-
price && /* @__PURE__ */ jsx("span", { children: price })
|
|
255
|
-
] })
|
|
256
|
-
]
|
|
257
|
-
}
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
function ModelPicker({ value, onChange, models, loading, renderProviderBadge, recommendedLabel = "Recommended", priorityGroup }) {
|
|
261
|
-
const [open, setOpen] = useState(false);
|
|
262
|
-
const [query, setQuery] = useState("");
|
|
263
|
-
const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
|
|
264
|
-
const inputRef = useRef(null);
|
|
265
|
-
const panelId = useId();
|
|
266
|
-
useEffect(() => {
|
|
267
|
-
if (open) inputRef.current?.focus();
|
|
268
|
-
}, [open]);
|
|
269
|
-
const selected = models.find((m) => m.id === value);
|
|
270
|
-
const filtered = useMemo(() => {
|
|
271
|
-
const q = query.trim().toLowerCase();
|
|
272
|
-
if (!q) return null;
|
|
273
|
-
return models.filter(
|
|
274
|
-
(m) => m.id.toLowerCase().includes(q) || m.name.toLowerCase().includes(q) || (m.description?.toLowerCase() ?? "").includes(q) || m.provider.toLowerCase().includes(q)
|
|
275
|
-
);
|
|
276
|
-
}, [models, query]);
|
|
277
|
-
const sections = useMemo(() => {
|
|
278
|
-
const isPriority = priorityGroup ? (m) => priorityGroup.match(m) : () => false;
|
|
279
|
-
const priority = priorityGroup ? models.filter(isPriority) : [];
|
|
280
|
-
const recommended = models.filter((m) => m.featured && !isPriority(m));
|
|
281
|
-
const byProvider = [];
|
|
282
|
-
for (const m of models) {
|
|
283
|
-
if (m.featured || isPriority(m)) continue;
|
|
284
|
-
const last = byProvider[byProvider.length - 1];
|
|
285
|
-
if (last && last.provider === m.provider) last.items.push(m);
|
|
286
|
-
else byProvider.push({ provider: m.provider, items: [m] });
|
|
287
|
-
}
|
|
288
|
-
return { priority, recommended, byProvider };
|
|
289
|
-
}, [models, priorityGroup]);
|
|
290
|
-
const select = (id) => {
|
|
291
|
-
onChange(id);
|
|
292
|
-
setOpen(false);
|
|
293
|
-
setQuery("");
|
|
294
|
-
};
|
|
295
|
-
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative inline-flex", children: [
|
|
296
|
-
/* @__PURE__ */ jsxs(
|
|
297
|
-
"button",
|
|
298
|
-
{
|
|
299
|
-
type: "button",
|
|
300
|
-
...triggerProps,
|
|
301
|
-
"aria-controls": open ? panelId : void 0,
|
|
302
|
-
onClick: () => setOpen(!open),
|
|
303
|
-
className: "inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent",
|
|
304
|
-
children: [
|
|
305
|
-
selected ? renderProviderBadge ? renderProviderBadge(selected.provider) : /* @__PURE__ */ jsx(ProviderLogo, { provider: selected.provider, size: 16 }) : /* @__PURE__ */ jsx(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
306
|
-
/* @__PURE__ */ jsx("span", { className: "max-w-[160px] truncate", children: selected?.name ?? value }),
|
|
307
|
-
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
308
|
-
]
|
|
309
|
-
}
|
|
310
|
-
),
|
|
311
|
-
/* @__PURE__ */ jsxs(
|
|
312
|
-
PopoverSurface,
|
|
313
|
-
{
|
|
314
|
-
open,
|
|
315
|
-
id: panelId,
|
|
316
|
-
triggerRef,
|
|
317
|
-
panelRef,
|
|
318
|
-
className: `flex w-[420px] max-w-[calc(100vw-2rem)] flex-col overflow-hidden rounded-xl border border-card-edge bg-popover ${OVERLAY_SHADOW}`,
|
|
319
|
-
children: [
|
|
320
|
-
/* @__PURE__ */ jsx("div", { className: "shrink-0 border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-strong bg-background px-3 py-2", children: [
|
|
321
|
-
/* @__PURE__ */ jsx(SearchGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
322
|
-
/* @__PURE__ */ jsx(
|
|
323
|
-
"input",
|
|
324
|
-
{
|
|
325
|
-
ref: inputRef,
|
|
326
|
-
type: "text",
|
|
327
|
-
value: query,
|
|
328
|
-
onChange: (e) => setQuery(e.target.value),
|
|
329
|
-
placeholder: "Search models...",
|
|
330
|
-
className: "flex-1 bg-transparent text-sm placeholder:text-muted-foreground"
|
|
331
|
-
}
|
|
332
|
-
)
|
|
333
|
-
] }) }),
|
|
334
|
-
/* @__PURE__ */ jsxs("div", { className: "max-h-[400px] min-h-0 overflow-y-auto p-1 pb-2", children: [
|
|
335
|
-
loading && /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading models..." }),
|
|
336
|
-
!loading && filtered && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
337
|
-
filtered.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models match your search" }),
|
|
338
|
-
filtered.map((m) => /* @__PURE__ */ jsx(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
339
|
-
] }),
|
|
340
|
-
!loading && !filtered && models.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models available" }),
|
|
341
|
-
!loading && !filtered && models.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
342
|
-
priorityGroup && sections.priority.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
343
|
-
/* @__PURE__ */ jsx(SectionHeader, { children: priorityGroup.label }),
|
|
344
|
-
sections.priority.map((m) => /* @__PURE__ */ jsx(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
345
|
-
] }),
|
|
346
|
-
sections.recommended.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
347
|
-
/* @__PURE__ */ jsx(SectionHeader, { children: recommendedLabel }),
|
|
348
|
-
sections.recommended.map((m) => /* @__PURE__ */ jsx(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
349
|
-
] }),
|
|
350
|
-
sections.byProvider.map((g) => /* @__PURE__ */ jsxs("div", { children: [
|
|
351
|
-
/* @__PURE__ */ jsx(SectionHeader, { children: g.provider }),
|
|
352
|
-
g.items.map((m) => /* @__PURE__ */ jsx(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
353
|
-
] }, g.provider))
|
|
354
|
-
] })
|
|
355
|
-
] })
|
|
356
|
-
]
|
|
357
|
-
}
|
|
358
|
-
)
|
|
359
|
-
] });
|
|
360
|
-
}
|
|
361
|
-
var KNOWN_EFFORT_LABELS = {
|
|
362
|
-
off: "Off",
|
|
363
|
-
low: "Quick",
|
|
364
|
-
medium: "Standard",
|
|
365
|
-
high: "Extended",
|
|
366
|
-
xhigh: "Extra",
|
|
367
|
-
ultracode: "Ultra"
|
|
368
|
-
};
|
|
369
|
-
var DEFAULT_EFFORT_LEVELS = [
|
|
370
|
-
{ id: "off", label: KNOWN_EFFORT_LABELS.off },
|
|
371
|
-
{ id: "low", label: KNOWN_EFFORT_LABELS.low },
|
|
372
|
-
{ id: "medium", label: KNOWN_EFFORT_LABELS.medium },
|
|
373
|
-
{ id: "high", label: KNOWN_EFFORT_LABELS.high }
|
|
374
|
-
];
|
|
375
|
-
function effortLevelLabel(id) {
|
|
376
|
-
const known = KNOWN_EFFORT_LABELS[id];
|
|
377
|
-
if (known) return known;
|
|
378
|
-
const words = id.replace(/[-_]+/g, " ").trim();
|
|
379
|
-
return words ? words.charAt(0).toUpperCase() + words.slice(1) : id;
|
|
380
|
-
}
|
|
381
|
-
function effortLevelsFromIds(ids) {
|
|
382
|
-
return ids.map((id) => ({ id, label: effortLevelLabel(id) }));
|
|
383
|
-
}
|
|
384
|
-
function reconcileEffortLevels(value, levels = DEFAULT_EFFORT_LEVELS) {
|
|
385
|
-
if (!value || levels.some((l) => l.id === value)) return levels;
|
|
386
|
-
return [{ id: value, label: effortLevelLabel(value) }, ...levels];
|
|
387
|
-
}
|
|
388
|
-
var EFFORT_METER_SEGMENTS = 4;
|
|
389
|
-
var EFFORT_METER_FILL_OPACITY = [0.25, 0.5, 0.75, 1];
|
|
390
|
-
var EFFORT_METER_GHOST_OPACITY = 0.15;
|
|
391
|
-
var OFF_LEVEL_IDS = /* @__PURE__ */ new Set(["off", "none"]);
|
|
392
|
-
var UNPLACEABLE_LEVEL_IDS = /* @__PURE__ */ new Set(["auto"]);
|
|
393
|
-
function effortMeterFill(levelId, levels = DEFAULT_EFFORT_LEVELS) {
|
|
394
|
-
if (OFF_LEVEL_IDS.has(levelId) || UNPLACEABLE_LEVEL_IDS.has(levelId)) return 0;
|
|
395
|
-
const active = levels.filter((l) => !OFF_LEVEL_IDS.has(l.id) && !UNPLACEABLE_LEVEL_IDS.has(l.id));
|
|
396
|
-
const index = active.findIndex((l) => l.id === levelId);
|
|
397
|
-
if (index < 0 || active.length === 0) return 0;
|
|
398
|
-
return Math.max(1, Math.floor((index + 1) * EFFORT_METER_SEGMENTS / active.length));
|
|
399
|
-
}
|
|
400
|
-
function EffortMeter({ fill, className }) {
|
|
401
|
-
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: `inline-flex items-center gap-[2px] ${className ?? ""}`, children: Array.from({ length: EFFORT_METER_SEGMENTS }, (_, i) => /* @__PURE__ */ jsx(
|
|
402
|
-
"span",
|
|
403
|
-
{
|
|
404
|
-
className: "h-3 w-[3px] rounded-full bg-current",
|
|
405
|
-
style: { opacity: i < fill ? EFFORT_METER_FILL_OPACITY[i] : EFFORT_METER_GHOST_OPACITY }
|
|
406
|
-
},
|
|
407
|
-
i
|
|
408
|
-
)) });
|
|
409
|
-
}
|
|
410
|
-
function EffortPicker({ value, onChange, levels = DEFAULT_EFFORT_LEVELS, label = "Thinking", fullWidth = false }) {
|
|
411
|
-
const [open, setOpen] = useState(false);
|
|
412
|
-
const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
|
|
413
|
-
const panelId = useId();
|
|
414
|
-
const rendered = reconcileEffortLevels(value, levels);
|
|
415
|
-
const isDeclared = (id) => levels.some((l) => l.id === id) && !UNPLACEABLE_LEVEL_IDS.has(id);
|
|
416
|
-
const selected = rendered.find((l) => l.id === value);
|
|
417
|
-
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: pickerRootClass(fullWidth), children: [
|
|
418
|
-
/* @__PURE__ */ jsxs(
|
|
419
|
-
"button",
|
|
420
|
-
{
|
|
421
|
-
type: "button",
|
|
422
|
-
...triggerProps,
|
|
423
|
-
"aria-controls": open ? panelId : void 0,
|
|
424
|
-
onClick: () => setOpen(!open),
|
|
425
|
-
title: label ? `${label} \u2014 how hard the agent reasons before answering` : "Reasoning effort",
|
|
426
|
-
className: `inline-flex min-h-[36px] shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent ${fullWidth ? "w-full" : ""}`,
|
|
427
|
-
children: [
|
|
428
|
-
/* @__PURE__ */ jsx(BrainGlyph, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
429
|
-
/* @__PURE__ */ jsxs("span", { className: fullWidth ? "flex-1 truncate text-left" : void 0, children: [
|
|
430
|
-
label ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
431
|
-
label,
|
|
432
|
-
": "
|
|
433
|
-
] }) : null,
|
|
434
|
-
selected ? selected.label : "\u2014"
|
|
435
|
-
] }),
|
|
436
|
-
selected && isDeclared(selected.id) && /* @__PURE__ */ jsx(EffortMeter, { fill: effortMeterFill(selected.id, levels), className: "shrink-0 text-foreground" }),
|
|
437
|
-
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })
|
|
438
|
-
]
|
|
439
|
-
}
|
|
440
|
-
),
|
|
441
|
-
/* @__PURE__ */ jsx(
|
|
442
|
-
PopoverSurface,
|
|
443
|
-
{
|
|
444
|
-
open,
|
|
445
|
-
id: panelId,
|
|
446
|
-
role: "menu",
|
|
447
|
-
triggerRef,
|
|
448
|
-
panelRef,
|
|
449
|
-
matchTriggerWidth: fullWidth,
|
|
450
|
-
className: `w-44 overflow-y-auto rounded-xl border border-card-edge bg-popover p-1 ${OVERLAY_SHADOW}`,
|
|
451
|
-
children: rendered.map((l) => /* @__PURE__ */ jsxs(
|
|
452
|
-
"button",
|
|
453
|
-
{
|
|
454
|
-
type: "button",
|
|
455
|
-
role: "menuitemradio",
|
|
456
|
-
"aria-checked": l.id === value,
|
|
457
|
-
onClick: () => {
|
|
458
|
-
onChange(l.id);
|
|
459
|
-
setOpen(false);
|
|
460
|
-
},
|
|
461
|
-
className: `flex min-h-[40px] w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition ${POPOVER_OPTION_FOCUS} ${l.id === value ? "bg-primary/10 font-medium" : "hover:bg-accent"}`,
|
|
462
|
-
children: [
|
|
463
|
-
/* @__PURE__ */ jsx(BrainGlyph, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
464
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: l.label }),
|
|
465
|
-
isDeclared(l.id) && /* @__PURE__ */ jsx(EffortMeter, { fill: effortMeterFill(l.id, levels), className: "ml-auto text-foreground" }),
|
|
466
|
-
l.id === value && /* @__PURE__ */ jsx(CheckGlyph, { className: `${isDeclared(l.id) ? "" : "ml-auto "}h-3.5 w-3.5 shrink-0 text-primary` })
|
|
467
|
-
]
|
|
468
|
-
},
|
|
469
|
-
l.id
|
|
470
|
-
))
|
|
471
|
-
}
|
|
472
|
-
)
|
|
473
|
-
] });
|
|
474
|
-
}
|
|
475
|
-
|
|
476
27
|
// src/web-react/composer-file-accept.ts
|
|
477
28
|
function isAcceptedFileType(file, accept) {
|
|
478
29
|
if (!accept || accept.trim().length === 0) return true;
|
|
@@ -569,7 +120,7 @@ function renamePastedImages(files, startIndex, stagedNames = []) {
|
|
|
569
120
|
}
|
|
570
121
|
|
|
571
122
|
// src/web-react/use-composer-attachments.ts
|
|
572
|
-
import { useCallback
|
|
123
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
573
124
|
function newId() {
|
|
574
125
|
const cryptoObject = globalThis.crypto;
|
|
575
126
|
if (typeof cryptoObject?.randomUUID === "function") return cryptoObject.randomUUID();
|
|
@@ -605,12 +156,12 @@ async function parseUploadError(res) {
|
|
|
605
156
|
}
|
|
606
157
|
var NO_UPLOAD_TARGET_MESSAGE = "No upload destination configured (pass uploadUrl or buildUploadRequest)";
|
|
607
158
|
function useComposerAttachments(options) {
|
|
608
|
-
const optionsRef =
|
|
159
|
+
const optionsRef = useRef(options);
|
|
609
160
|
optionsRef.current = options;
|
|
610
|
-
const [staged, setStagedState] =
|
|
611
|
-
const stagedRef =
|
|
612
|
-
const controllersRef =
|
|
613
|
-
const setStaged =
|
|
161
|
+
const [staged, setStagedState] = useState([]);
|
|
162
|
+
const stagedRef = useRef([]);
|
|
163
|
+
const controllersRef = useRef(/* @__PURE__ */ new Map());
|
|
164
|
+
const setStaged = useCallback(
|
|
614
165
|
(updater) => {
|
|
615
166
|
const next = typeof updater === "function" ? updater(stagedRef.current) : updater;
|
|
616
167
|
stagedRef.current = next;
|
|
@@ -618,7 +169,7 @@ function useComposerAttachments(options) {
|
|
|
618
169
|
},
|
|
619
170
|
[]
|
|
620
171
|
);
|
|
621
|
-
const upload =
|
|
172
|
+
const upload = useCallback(
|
|
622
173
|
async (id, file, name) => {
|
|
623
174
|
const opts = optionsRef.current;
|
|
624
175
|
setStaged(
|
|
@@ -681,7 +232,7 @@ function useComposerAttachments(options) {
|
|
|
681
232
|
},
|
|
682
233
|
[setStaged]
|
|
683
234
|
);
|
|
684
|
-
const addFiles =
|
|
235
|
+
const addFiles = useCallback(
|
|
685
236
|
async (files) => {
|
|
686
237
|
const opts = optionsRef.current;
|
|
687
238
|
const enabled2 = opts.enabled ?? true;
|
|
@@ -761,7 +312,7 @@ function useComposerAttachments(options) {
|
|
|
761
312
|
},
|
|
762
313
|
[setStaged, upload]
|
|
763
314
|
);
|
|
764
|
-
const retry =
|
|
315
|
+
const retry = useCallback(
|
|
765
316
|
(id) => {
|
|
766
317
|
const entry = stagedRef.current.find((s) => s.id === id);
|
|
767
318
|
if (!entry) return;
|
|
@@ -769,7 +320,7 @@ function useComposerAttachments(options) {
|
|
|
769
320
|
},
|
|
770
321
|
[upload]
|
|
771
322
|
);
|
|
772
|
-
const removeAttachment =
|
|
323
|
+
const removeAttachment = useCallback(
|
|
773
324
|
(id) => {
|
|
774
325
|
controllersRef.current.get(id)?.abort();
|
|
775
326
|
controllersRef.current.delete(id);
|
|
@@ -779,7 +330,7 @@ function useComposerAttachments(options) {
|
|
|
779
330
|
},
|
|
780
331
|
[setStaged]
|
|
781
332
|
);
|
|
782
|
-
const clear =
|
|
333
|
+
const clear = useCallback(() => {
|
|
783
334
|
for (const controller of controllersRef.current.values()) controller.abort();
|
|
784
335
|
controllersRef.current.clear();
|
|
785
336
|
for (const entry of stagedRef.current) {
|
|
@@ -787,7 +338,7 @@ function useComposerAttachments(options) {
|
|
|
787
338
|
}
|
|
788
339
|
setStaged([]);
|
|
789
340
|
}, [setStaged]);
|
|
790
|
-
|
|
341
|
+
useEffect(
|
|
791
342
|
() => () => {
|
|
792
343
|
for (const controller of controllersRef.current.values()) controller.abort();
|
|
793
344
|
controllersRef.current.clear();
|
|
@@ -797,7 +348,7 @@ function useComposerAttachments(options) {
|
|
|
797
348
|
},
|
|
798
349
|
[]
|
|
799
350
|
);
|
|
800
|
-
const composerFiles =
|
|
351
|
+
const composerFiles = useMemo(
|
|
801
352
|
() => staged.map((s) => ({
|
|
802
353
|
id: s.id,
|
|
803
354
|
name: s.name,
|
|
@@ -809,15 +360,15 @@ function useComposerAttachments(options) {
|
|
|
809
360
|
})),
|
|
810
361
|
[staged]
|
|
811
362
|
);
|
|
812
|
-
const references =
|
|
363
|
+
const references = useMemo(
|
|
813
364
|
() => staged.filter((s) => s.status === "ready" && !!s.reference).map((s) => s.reference),
|
|
814
365
|
[staged]
|
|
815
366
|
);
|
|
816
|
-
const hasPending =
|
|
367
|
+
const hasPending = useMemo(
|
|
817
368
|
() => staged.some((s) => s.status === "pending" || s.status === "uploading"),
|
|
818
369
|
[staged]
|
|
819
370
|
);
|
|
820
|
-
const hasError =
|
|
371
|
+
const hasError = useMemo(() => staged.some((s) => s.status === "error"), [staged]);
|
|
821
372
|
const enabled = options.enabled ?? true;
|
|
822
373
|
const blockReason = !enabled ? "Attachments are disabled" : hasPending ? "Attachments are still uploading" : hasError ? "Remove failed attachments to send" : null;
|
|
823
374
|
return {
|
|
@@ -834,7 +385,7 @@ function useComposerAttachments(options) {
|
|
|
834
385
|
}
|
|
835
386
|
|
|
836
387
|
// src/web-react/harness-glyphs.tsx
|
|
837
|
-
import { jsx
|
|
388
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
838
389
|
var BRAND_PATHS = {
|
|
839
390
|
opencode: [
|
|
840
391
|
"M16 6H8v12h8V6zm4 16H4V2h16v20z"
|
|
@@ -867,27 +418,27 @@ var BRAND_PATHS = {
|
|
|
867
418
|
]
|
|
868
419
|
};
|
|
869
420
|
function BotGlyph({ className }) {
|
|
870
|
-
return /* @__PURE__ */
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
875
|
-
/* @__PURE__ */
|
|
876
|
-
/* @__PURE__ */
|
|
421
|
+
return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
422
|
+
/* @__PURE__ */ jsx("path", { d: "M12 8V4H8" }),
|
|
423
|
+
/* @__PURE__ */ jsx("rect", { width: "16", height: "12", x: "4", y: "8", rx: "2" }),
|
|
424
|
+
/* @__PURE__ */ jsx("path", { d: "M2 14h2" }),
|
|
425
|
+
/* @__PURE__ */ jsx("path", { d: "M20 14h2" }),
|
|
426
|
+
/* @__PURE__ */ jsx("path", { d: "M15 13v2" }),
|
|
427
|
+
/* @__PURE__ */ jsx("path", { d: "M9 13v2" })
|
|
877
428
|
] });
|
|
878
429
|
}
|
|
879
430
|
function PlugGlyph({ className }) {
|
|
880
|
-
return /* @__PURE__ */
|
|
881
|
-
/* @__PURE__ */
|
|
882
|
-
/* @__PURE__ */
|
|
883
|
-
/* @__PURE__ */
|
|
884
|
-
/* @__PURE__ */
|
|
431
|
+
return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
432
|
+
/* @__PURE__ */ jsx("path", { d: "M12 22v-5" }),
|
|
433
|
+
/* @__PURE__ */ jsx("path", { d: "M15 8V2" }),
|
|
434
|
+
/* @__PURE__ */ jsx("path", { d: "M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z" }),
|
|
435
|
+
/* @__PURE__ */ jsx("path", { d: "M9 8V2" })
|
|
885
436
|
] });
|
|
886
437
|
}
|
|
887
438
|
function TerminalGlyph({ className }) {
|
|
888
|
-
return /* @__PURE__ */
|
|
889
|
-
/* @__PURE__ */
|
|
890
|
-
/* @__PURE__ */
|
|
439
|
+
return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
440
|
+
/* @__PURE__ */ jsx("path", { d: "M12 19h8" }),
|
|
441
|
+
/* @__PURE__ */ jsx("path", { d: "m4 17 6-6-6-6" })
|
|
891
442
|
] });
|
|
892
443
|
}
|
|
893
444
|
var FALLBACK_GLYPHS = {
|
|
@@ -898,7 +449,7 @@ var FALLBACK_GLYPHS = {
|
|
|
898
449
|
function HarnessGlyph({ harness, className }) {
|
|
899
450
|
const brand = BRAND_PATHS[harness];
|
|
900
451
|
if (brand) {
|
|
901
|
-
return /* @__PURE__ */
|
|
452
|
+
return /* @__PURE__ */ jsx(
|
|
902
453
|
"svg",
|
|
903
454
|
{
|
|
904
455
|
className,
|
|
@@ -909,18 +460,18 @@ function HarnessGlyph({ harness, className }) {
|
|
|
909
460
|
role: "img",
|
|
910
461
|
"aria-label": harness,
|
|
911
462
|
"data-glyph": harness,
|
|
912
|
-
children: brand.map((d) => /* @__PURE__ */
|
|
463
|
+
children: brand.map((d) => /* @__PURE__ */ jsx("path", { d }, d.slice(0, 32)))
|
|
913
464
|
}
|
|
914
465
|
);
|
|
915
466
|
}
|
|
916
467
|
const Fallback = FALLBACK_GLYPHS[harness] ?? BotGlyph;
|
|
917
468
|
const kind = Fallback === BotGlyph ? "bot" : Fallback === PlugGlyph ? "plug" : "terminal";
|
|
918
|
-
return /* @__PURE__ */
|
|
469
|
+
return /* @__PURE__ */ jsx("span", { role: "img", "aria-label": harness, "data-glyph": kind, className: "inline-flex", children: /* @__PURE__ */ jsx(Fallback, { className }) });
|
|
919
470
|
}
|
|
920
471
|
|
|
921
472
|
// src/web-react/agent-session-controls.tsx
|
|
922
|
-
import { useId
|
|
923
|
-
import { Fragment
|
|
473
|
+
import { useId, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
474
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
924
475
|
var HARNESS_LABELS = {
|
|
925
476
|
opencode: "OpenCode (any model)",
|
|
926
477
|
"claude-code": "Claude Code (Anthropic)",
|
|
@@ -939,19 +490,19 @@ var HARNESS_LABELS = {
|
|
|
939
490
|
function harnessLabel(h) {
|
|
940
491
|
return HARNESS_LABELS[h] ?? h;
|
|
941
492
|
}
|
|
942
|
-
function
|
|
943
|
-
return /* @__PURE__ */
|
|
493
|
+
function ChevronDown({ className }) {
|
|
494
|
+
return /* @__PURE__ */ jsx2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }) });
|
|
944
495
|
}
|
|
945
496
|
function LockGlyph({ className }) {
|
|
946
|
-
return /* @__PURE__ */
|
|
947
|
-
/* @__PURE__ */
|
|
948
|
-
/* @__PURE__ */
|
|
497
|
+
return /* @__PURE__ */ jsxs2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
498
|
+
/* @__PURE__ */ jsx2("rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2" }),
|
|
499
|
+
/* @__PURE__ */ jsx2("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
949
500
|
] });
|
|
950
501
|
}
|
|
951
502
|
function GearGlyph({ className }) {
|
|
952
|
-
return /* @__PURE__ */
|
|
953
|
-
/* @__PURE__ */
|
|
954
|
-
/* @__PURE__ */
|
|
503
|
+
return /* @__PURE__ */ jsxs2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
504
|
+
/* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "3" }),
|
|
505
|
+
/* @__PURE__ */ jsx2("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" })
|
|
955
506
|
] });
|
|
956
507
|
}
|
|
957
508
|
var FOCUS_RING = "";
|
|
@@ -962,18 +513,18 @@ function HarnessPicker({
|
|
|
962
513
|
fullWidth = false,
|
|
963
514
|
lockReason
|
|
964
515
|
}) {
|
|
965
|
-
const [open, setOpen] =
|
|
966
|
-
const [hintOpen, setHintOpen] =
|
|
516
|
+
const [open, setOpen] = useState2(false);
|
|
517
|
+
const [hintOpen, setHintOpen] = useState2(false);
|
|
967
518
|
const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
|
|
968
|
-
const hintPanelRef =
|
|
969
|
-
const panelId =
|
|
970
|
-
const reasonId =
|
|
519
|
+
const hintPanelRef = useRef2(null);
|
|
520
|
+
const panelId = useId();
|
|
521
|
+
const reasonId = useId();
|
|
971
522
|
const locked = lockReason !== void 0;
|
|
972
523
|
const options = available ?? Object.keys(HARNESS_LABELS);
|
|
973
524
|
const showHint = () => setHintOpen(true);
|
|
974
525
|
const hideHint = () => setHintOpen(false);
|
|
975
|
-
return /* @__PURE__ */
|
|
976
|
-
/* @__PURE__ */
|
|
526
|
+
return /* @__PURE__ */ jsxs2("div", { ref: containerRef, className: pickerRootClass(fullWidth), children: [
|
|
527
|
+
/* @__PURE__ */ jsxs2(
|
|
977
528
|
"button",
|
|
978
529
|
{
|
|
979
530
|
type: "button",
|
|
@@ -991,17 +542,17 @@ function HarnessPicker({
|
|
|
991
542
|
title: "Agent backend",
|
|
992
543
|
className: `inline-flex min-h-[36px] w-full items-center justify-between gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition ${locked ? "cursor-default" : "hover:bg-accent"} ${FOCUS_RING}`,
|
|
993
544
|
children: [
|
|
994
|
-
/* @__PURE__ */
|
|
995
|
-
/* @__PURE__ */
|
|
996
|
-
/* @__PURE__ */
|
|
545
|
+
/* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
546
|
+
/* @__PURE__ */ jsx2(HarnessGlyph, { harness: value, className: "h-4 w-4 shrink-0 text-foreground" }),
|
|
547
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: harnessLabel(value) })
|
|
997
548
|
] }),
|
|
998
|
-
locked ? /* @__PURE__ */
|
|
549
|
+
locked ? /* @__PURE__ */ jsx2(LockGlyph, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })
|
|
999
550
|
]
|
|
1000
551
|
}
|
|
1001
552
|
),
|
|
1002
|
-
locked && /* @__PURE__ */
|
|
1003
|
-
/* @__PURE__ */
|
|
1004
|
-
/* @__PURE__ */
|
|
553
|
+
locked && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
554
|
+
/* @__PURE__ */ jsx2("span", { id: reasonId, className: "sr-only", children: lockReason }),
|
|
555
|
+
/* @__PURE__ */ jsx2(
|
|
1005
556
|
PopoverSurface,
|
|
1006
557
|
{
|
|
1007
558
|
open: hintOpen,
|
|
@@ -1010,11 +561,11 @@ function HarnessPicker({
|
|
|
1010
561
|
panelRef: hintPanelRef,
|
|
1011
562
|
matchTriggerWidth: fullWidth,
|
|
1012
563
|
className: `max-w-[248px] rounded-lg border border-card-edge bg-popover px-2.5 py-1.5 text-xs leading-snug text-muted-foreground ${OVERLAY_SHADOW}`,
|
|
1013
|
-
children: /* @__PURE__ */
|
|
564
|
+
children: /* @__PURE__ */ jsx2("span", { "aria-hidden": true, children: lockReason })
|
|
1014
565
|
}
|
|
1015
566
|
)
|
|
1016
567
|
] }),
|
|
1017
|
-
/* @__PURE__ */
|
|
568
|
+
/* @__PURE__ */ jsx2(
|
|
1018
569
|
PopoverSurface,
|
|
1019
570
|
{
|
|
1020
571
|
open: !locked && open,
|
|
@@ -1024,7 +575,7 @@ function HarnessPicker({
|
|
|
1024
575
|
panelRef,
|
|
1025
576
|
matchTriggerWidth: true,
|
|
1026
577
|
className: `max-h-64 min-w-[248px] overflow-y-auto rounded-xl border border-card-edge bg-popover p-1 ${OVERLAY_SHADOW}`,
|
|
1027
|
-
children: options.map((h) => /* @__PURE__ */
|
|
578
|
+
children: options.map((h) => /* @__PURE__ */ jsxs2(
|
|
1028
579
|
"button",
|
|
1029
580
|
{
|
|
1030
581
|
type: "button",
|
|
@@ -1036,9 +587,9 @@ function HarnessPicker({
|
|
|
1036
587
|
},
|
|
1037
588
|
className: `flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-left text-sm transition ${FOCUS_RING} ${h === value ? "bg-primary/10 font-medium" : "hover:bg-accent"}`,
|
|
1038
589
|
children: [
|
|
1039
|
-
/* @__PURE__ */
|
|
1040
|
-
/* @__PURE__ */
|
|
1041
|
-
h === value && /* @__PURE__ */
|
|
590
|
+
/* @__PURE__ */ jsx2(HarnessGlyph, { harness: h, className: "h-4 w-4 shrink-0 text-foreground" }),
|
|
591
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: harnessLabel(h) }),
|
|
592
|
+
h === value && /* @__PURE__ */ jsx2(CheckGlyph, { className: "ml-auto h-3.5 w-3.5 shrink-0 text-primary" })
|
|
1042
593
|
]
|
|
1043
594
|
},
|
|
1044
595
|
h
|
|
@@ -1049,7 +600,7 @@ function HarnessPicker({
|
|
|
1049
600
|
}
|
|
1050
601
|
function useCoherentHandlers(props) {
|
|
1051
602
|
const { model, models, harness, onModelChange, onHarnessChange, harnessLockReason } = props;
|
|
1052
|
-
const canonicalIds =
|
|
603
|
+
const canonicalIds = useMemo2(() => models.map((m) => m.id), [models]);
|
|
1053
604
|
const harnessLocked = harnessLockReason !== void 0;
|
|
1054
605
|
const onModel = (next) => {
|
|
1055
606
|
onModelChange(next);
|
|
@@ -1081,12 +632,12 @@ function AgentSessionControls(props) {
|
|
|
1081
632
|
className
|
|
1082
633
|
} = props;
|
|
1083
634
|
const { onModel, onHarness } = useCoherentHandlers(props);
|
|
1084
|
-
const [open, setOpen] =
|
|
635
|
+
const [open, setOpen] = useState2(false);
|
|
1085
636
|
const { containerRef: popoverRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
|
|
1086
|
-
const panelId =
|
|
637
|
+
const panelId = useId();
|
|
1087
638
|
const selectedModel = models.find((m) => m.id === model);
|
|
1088
639
|
const showEffort = selectedModel?.supportsReasoning ?? true;
|
|
1089
|
-
const modelPicker = /* @__PURE__ */
|
|
640
|
+
const modelPicker = /* @__PURE__ */ jsx2(
|
|
1090
641
|
ModelPicker,
|
|
1091
642
|
{
|
|
1092
643
|
value: model,
|
|
@@ -1097,17 +648,17 @@ function AgentSessionControls(props) {
|
|
|
1097
648
|
}
|
|
1098
649
|
);
|
|
1099
650
|
if (layout === "inline") {
|
|
1100
|
-
return /* @__PURE__ */
|
|
651
|
+
return /* @__PURE__ */ jsxs2("div", { className: `flex items-center gap-1.5 ${className ?? ""}`, children: [
|
|
1101
652
|
modelPicker,
|
|
1102
|
-
showHarness && /* @__PURE__ */
|
|
1103
|
-
showEffort && /* @__PURE__ */
|
|
653
|
+
showHarness && /* @__PURE__ */ jsx2(HarnessPicker, { value: harness, onChange: onHarness, available: availableHarnesses, lockReason: harnessLockReason }),
|
|
654
|
+
showEffort && /* @__PURE__ */ jsx2(EffortPicker, { value: effort, onChange: onEffortChange, levels: effortLevels })
|
|
1104
655
|
] });
|
|
1105
656
|
}
|
|
1106
657
|
const hasAdvanced = showHarness || showEffort;
|
|
1107
|
-
return /* @__PURE__ */
|
|
658
|
+
return /* @__PURE__ */ jsxs2("div", { className: `flex items-center gap-1.5 ${className ?? ""}`, children: [
|
|
1108
659
|
modelPicker,
|
|
1109
|
-
hasAdvanced && /* @__PURE__ */
|
|
1110
|
-
/* @__PURE__ */
|
|
660
|
+
hasAdvanced && /* @__PURE__ */ jsxs2("div", { ref: popoverRef, className: "relative inline-flex", children: [
|
|
661
|
+
/* @__PURE__ */ jsx2(
|
|
1111
662
|
"button",
|
|
1112
663
|
{
|
|
1113
664
|
type: "button",
|
|
@@ -1117,10 +668,10 @@ function AgentSessionControls(props) {
|
|
|
1117
668
|
title: "Model settings \u2014 pick the agent backend and how hard it thinks",
|
|
1118
669
|
className: `flex h-8 w-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground data-[state=open]:bg-muted ${FOCUS_RING}`,
|
|
1119
670
|
"data-state": open ? "open" : "closed",
|
|
1120
|
-
children: /* @__PURE__ */
|
|
671
|
+
children: /* @__PURE__ */ jsx2(GearGlyph, { className: "h-4 w-4" })
|
|
1121
672
|
}
|
|
1122
673
|
),
|
|
1123
|
-
/* @__PURE__ */
|
|
674
|
+
/* @__PURE__ */ jsxs2(
|
|
1124
675
|
PopoverSurface,
|
|
1125
676
|
{
|
|
1126
677
|
open,
|
|
@@ -1129,9 +680,9 @@ function AgentSessionControls(props) {
|
|
|
1129
680
|
panelRef,
|
|
1130
681
|
className: `w-72 space-y-3 overflow-y-auto rounded-xl border border-card-edge bg-popover p-3 ${OVERLAY_SHADOW}`,
|
|
1131
682
|
children: [
|
|
1132
|
-
showHarness && /* @__PURE__ */
|
|
1133
|
-
/* @__PURE__ */
|
|
1134
|
-
/* @__PURE__ */
|
|
683
|
+
showHarness && /* @__PURE__ */ jsxs2("div", { className: "space-y-1.5", children: [
|
|
684
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-foreground", children: "Agent backend" }),
|
|
685
|
+
/* @__PURE__ */ jsx2(
|
|
1135
686
|
HarnessPicker,
|
|
1136
687
|
{
|
|
1137
688
|
value: harness,
|
|
@@ -1141,12 +692,12 @@ function AgentSessionControls(props) {
|
|
|
1141
692
|
lockReason: harnessLockReason
|
|
1142
693
|
}
|
|
1143
694
|
),
|
|
1144
|
-
/* @__PURE__ */
|
|
695
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs leading-snug text-muted-foreground", children: "The engine that runs the agent. Switching it keeps your model choice compatible." })
|
|
1145
696
|
] }),
|
|
1146
|
-
showEffort && /* @__PURE__ */
|
|
1147
|
-
/* @__PURE__ */
|
|
1148
|
-
/* @__PURE__ */
|
|
1149
|
-
/* @__PURE__ */
|
|
697
|
+
showEffort && /* @__PURE__ */ jsxs2("div", { className: "space-y-1.5", children: [
|
|
698
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-foreground", children: "Thinking" }),
|
|
699
|
+
/* @__PURE__ */ jsx2(EffortPicker, { value: effort, onChange: onEffortChange, levels: effortLevels, label: "", fullWidth: true }),
|
|
700
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs leading-snug text-muted-foreground", children: "How hard the agent thinks before answering. Higher is slower but more thorough." })
|
|
1150
701
|
] })
|
|
1151
702
|
]
|
|
1152
703
|
}
|
|
@@ -1156,23 +707,6 @@ function AgentSessionControls(props) {
|
|
|
1156
707
|
}
|
|
1157
708
|
|
|
1158
709
|
export {
|
|
1159
|
-
ChevronDown,
|
|
1160
|
-
BrainGlyph,
|
|
1161
|
-
usePopover,
|
|
1162
|
-
POPOVER_SURFACE_ATTR,
|
|
1163
|
-
PopoverSurface,
|
|
1164
|
-
POPOVER_OPTION_FOCUS,
|
|
1165
|
-
OVERLAY_SHADOW,
|
|
1166
|
-
usePending,
|
|
1167
|
-
ModelPicker,
|
|
1168
|
-
DEFAULT_EFFORT_LEVELS,
|
|
1169
|
-
effortLevelLabel,
|
|
1170
|
-
effortLevelsFromIds,
|
|
1171
|
-
reconcileEffortLevels,
|
|
1172
|
-
EFFORT_METER_SEGMENTS,
|
|
1173
|
-
effortMeterFill,
|
|
1174
|
-
EffortMeter,
|
|
1175
|
-
EffortPicker,
|
|
1176
710
|
isAcceptedFileType,
|
|
1177
711
|
acceptRejectionReason,
|
|
1178
712
|
filterAcceptedFiles,
|
|
@@ -1181,4 +715,4 @@ export {
|
|
|
1181
715
|
HarnessGlyph,
|
|
1182
716
|
AgentSessionControls
|
|
1183
717
|
};
|
|
1184
|
-
//# sourceMappingURL=chunk-
|
|
718
|
+
//# sourceMappingURL=chunk-DINGA2MO.js.map
|