@workerdeck/ui 0.12.0 → 0.15.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 +19 -0
- package/build/{SessionPanel-NQ8ksCfj.mjs → SessionPanel-DI1NO4l8.mjs} +223 -163
- package/build/SessionPanel-DI1NO4l8.mjs.map +1 -0
- package/build/{SessionPanel-Dy9lQrOV.d.mts → SessionPanel-J2U8v88q.d.mts} +86 -8
- package/build/index.d.mts +118 -7
- package/build/index.mjs +355 -169
- package/build/index.mjs.map +1 -1
- package/build/workspace.d.mts +13 -1
- package/build/workspace.mjs +7 -2
- package/build/workspace.mjs.map +1 -1
- package/package.json +4 -4
- package/src/components/agent/Composer.tsx +112 -37
- package/src/components/agent/EngineIcon.tsx +97 -0
- package/src/components/agent/Loader.tsx +4 -1
- package/src/components/agent/Message.tsx +12 -5
- package/src/components/agent/QuestionPrompt.tsx +1 -1
- package/src/components/agent/SessionBrowser.tsx +266 -138
- package/src/components/agent/SessionPanel.tsx +149 -48
- package/src/components/agent/SessionWorkspace.tsx +17 -0
- package/src/components/agent/StatusBar.tsx +58 -12
- package/src/components/agent/Transcript.tsx +2 -3
- package/src/components/agent/line-prompt.tsx +2 -2
- package/src/components/agent/transcript-variant.tsx +14 -0
- package/src/components/ui/Badge.tsx +6 -1
- package/src/components/ui/Empty.tsx +56 -0
- package/src/components/ui/Menu.tsx +1 -1
- package/src/components/ui/Select.tsx +1 -1
- package/src/components/ui/Splitter.tsx +14 -0
- package/src/components/ui/Tooltip.tsx +1 -1
- package/src/index.ts +11 -1
- package/src/styles/theme.css +77 -15
- package/build/SessionPanel-NQ8ksCfj.mjs.map +0 -1
package/build/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as Tip, A as
|
|
1
|
+
import { $ as Tip, A as SkillsDialog, B as commandTrigger, C as isMutatingTool, Ct as Button, D as permissionModeChoices, E as PermissionModeSelect, F as skillPrompt, G as plainTextToSegments, H as mentionTrigger, I as TranscriptDensityProvider, J as Splitter, K as segmentsToPlainText, L as TranscriptVariantProvider, M as HostFilesDialog, N as ContextDialog, O as permissionModeMeta, P as Composer, Q as copyText, R as useTranscriptDensity, S as Response, St as badgeVariants, T as PERMISSION_MODES, Tt as cn, U as usePromptAreaState, V as hashtagTrigger, W as PromptArea, X as Spinner, Y as CodeBlock, Z as CopyButton, _ as SessionInfoDialog, _t as SelectItemText, a as SessionEmptyState, at as DialogContent, b as parseUserQuestions, bt as Input, c as Message, ct as DialogTrigger, d as FileCard, dt as MenuItem, et as TooltipContent, f as Conversation, ft as MenuSeparator, g as STATUS_META, gt as SelectItem, h as StatusBar, ht as SelectContent, i as ToolCallCard, it as DialogClose, j as McpDialog, k as ModelSelect, l as MessageContent, lt as Menu, m as ConversationScrollButton, mt as Select, n as UsageDialog, nt as Dialog, o as Reasoning, ot as DialogHeader, p as ConversationContent, pt as MenuTrigger, q as ProgressRing, r as Transcript, rt as DialogBody, s as PromptTokenText, st as DialogRow, t as SessionPanel, tt as TooltipProvider, u as Loader, ut as MenuContent, v as QUESTION_BEHAVIORS, vt as SelectTrigger, w as toolIcon, wt as buttonVariants, x as PermissionPrompt, xt as Badge, y as QuestionPrompt, yt as SelectValue, z as useTranscriptVariant } from "./SessionPanel-DI1NO4l8.mjs";
|
|
2
2
|
import { a as formatDuration, c as formatRelativeTime, d as rateLimitWindowSeconds, f as toolInputPreview, i as formatCountdown, l as formatTokens, n as formatBytes, o as formatRateLimitWindow, r as formatCost, s as formatRateLimitWindowLong, t as formatAgoPrecise, u as friendlyModel } from "./format-DqR56Y8l.mjs";
|
|
3
3
|
import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
-
import {
|
|
5
|
-
import { Pencil, Search, Trash2, X } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { BellRing, CircleAlert, CircleSlash, Layers, Moon, PauseCircle, Pencil, Search, SearchX, Trash2, X } from "lucide-react";
|
|
6
6
|
import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
|
|
7
7
|
import { Toaster as Toaster$1, toast } from "sonner";
|
|
8
8
|
import { STATE_LABELS, STATE_ORDER, adaptersOf, clearFilters, filterRows, groupRows, hasFacetFilter, sessionLabel, subsetSummary } from "@workerdeck/protocol";
|
|
@@ -77,6 +77,57 @@ function Toaster() {
|
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
//#endregion
|
|
80
|
+
//#region src/components/ui/Empty.tsx
|
|
81
|
+
/**
|
|
82
|
+
* A view with nothing in it: icon, title, description, and at most one action.
|
|
83
|
+
*
|
|
84
|
+
* Centered and given room, because an empty view is the first thing a new
|
|
85
|
+
* install shows and a flush-left sentence in the top corner reads like a bug
|
|
86
|
+
* report. It lives here rather than in one client because every panel that can
|
|
87
|
+
* be empty should be empty the same way — the extension's views and the
|
|
88
|
+
* dashboard's four sidebars are the same shape of thing.
|
|
89
|
+
*
|
|
90
|
+
* **At most one action, and never one the view header already offers.** Creating
|
|
91
|
+
* a session and adding a gateway are the `+` in the native title bar, exclusively
|
|
92
|
+
* — so those empty states point at it in words rather than growing a second
|
|
93
|
+
* button that does the same thing two inches lower. A button here is for the way
|
|
94
|
+
* out of a state the header has no answer to: clearing a filter, widening a
|
|
95
|
+
* scope.
|
|
96
|
+
*/
|
|
97
|
+
function Empty({ icon, title, description, action, onAction }) {
|
|
98
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
99
|
+
className: "flex flex-col items-center gap-2 px-5 py-8 text-center",
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ jsx("div", {
|
|
102
|
+
className: "text-fg-4 opacity-60 [&_svg]:size-7",
|
|
103
|
+
children: icon
|
|
104
|
+
}),
|
|
105
|
+
/* @__PURE__ */ jsx("p", {
|
|
106
|
+
className: "text-body-sm font-medium text-fg-2",
|
|
107
|
+
children: title
|
|
108
|
+
}),
|
|
109
|
+
description ? /* @__PURE__ */ jsx("p", {
|
|
110
|
+
className: "max-w-[26ch] text-balance text-label leading-relaxed text-fg-4",
|
|
111
|
+
children: description
|
|
112
|
+
}) : null,
|
|
113
|
+
action && onAction ? /* @__PURE__ */ jsx(Button, {
|
|
114
|
+
variant: "outline",
|
|
115
|
+
size: "sm",
|
|
116
|
+
className: "mt-1",
|
|
117
|
+
onClick: onAction,
|
|
118
|
+
children: action
|
|
119
|
+
}) : null
|
|
120
|
+
]
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/** A key or icon named inline in an empty state's description — "use the + above". */
|
|
124
|
+
function EmptyKey({ children }) {
|
|
125
|
+
return /* @__PURE__ */ jsx("span", {
|
|
126
|
+
className: "rounded border border-border px-1 font-mono text-fg-3",
|
|
127
|
+
children
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
80
131
|
//#region src/components/prompt-area/segment-helpers.ts
|
|
81
132
|
/** Returns `true` when the segment array is empty or contains only whitespace text. */
|
|
82
133
|
function isSegmentsEmpty(segments) {
|
|
@@ -158,7 +209,26 @@ function SessionList({ sessions, activeId, onSelect, onDelete, emptyText = "No s
|
|
|
158
209
|
}
|
|
159
210
|
//#endregion
|
|
160
211
|
//#region src/components/agent/SessionBrowser.tsx
|
|
161
|
-
|
|
212
|
+
/**
|
|
213
|
+
* How a list row is drawn, in one place, so `SidebarRow` in `web` matches this
|
|
214
|
+
* exactly rather than approximating it — the dashboard's other three sidebars
|
|
215
|
+
* are that component, and a sessions list that hovered differently from the
|
|
216
|
+
* gateways list beside it would read as a different product.
|
|
217
|
+
*
|
|
218
|
+
* Two rules are load-bearing:
|
|
219
|
+
*
|
|
220
|
+
* - **Fill means hover, and only hover.** It stays on the row whether or not
|
|
221
|
+
* the row is selected, because a selected row still has to answer the
|
|
222
|
+
* pointer. Selection gets the gutter instead.
|
|
223
|
+
* - **`ml-0` on the selected row is not cosmetic.** It hands the accent border
|
|
224
|
+
* the 4px the margin was holding, so the text does not shift sideways as a
|
|
225
|
+
* row becomes the selected one. The squared left corners are what let the bar
|
|
226
|
+
* sit flush against the sidebar edge.
|
|
227
|
+
*/
|
|
228
|
+
function rowShapeClass(active) {
|
|
229
|
+
return cn("px-2 py-1.5 hover:bg-row-hover", active ? "mr-1 ml-0 rounded-r-md border-l-4 border-l-accent" : "mx-1 rounded-md");
|
|
230
|
+
}
|
|
231
|
+
function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelect, onDelete, onRename, emptyState, showControls = true, className }) {
|
|
162
232
|
const visible = useMemo(() => filterRows(rows, config, scope), [
|
|
163
233
|
rows,
|
|
164
234
|
config,
|
|
@@ -184,10 +254,10 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
184
254
|
className: cn("flex flex-col gap-3", className),
|
|
185
255
|
children: [
|
|
186
256
|
/* @__PURE__ */ jsxs("div", {
|
|
187
|
-
className: "flex flex-
|
|
257
|
+
className: cn("flex flex-col gap-1.5 px-2", !showControls && "hidden"),
|
|
188
258
|
children: [
|
|
189
259
|
/* @__PURE__ */ jsxs("div", {
|
|
190
|
-
className: "relative
|
|
260
|
+
className: "relative",
|
|
191
261
|
children: [/* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-fg-4" }), /* @__PURE__ */ jsx(Input, {
|
|
192
262
|
value: config.search,
|
|
193
263
|
onChange: (e) => set({ search: e.target.value }),
|
|
@@ -196,83 +266,98 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
196
266
|
className: "pl-8"
|
|
197
267
|
})]
|
|
198
268
|
}),
|
|
199
|
-
/* @__PURE__ */ jsx(
|
|
269
|
+
/* @__PURE__ */ jsx(FilterRow, {
|
|
200
270
|
label: "State",
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
value:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
271
|
+
children: /* @__PURE__ */ jsx(FacetSelect, {
|
|
272
|
+
label: "State",
|
|
273
|
+
value: config.states,
|
|
274
|
+
options: STATE_ORDER.map((s) => ({
|
|
275
|
+
value: s,
|
|
276
|
+
label: STATE_LABELS[s]
|
|
277
|
+
})),
|
|
278
|
+
onChange: (states) => set({ states })
|
|
279
|
+
})
|
|
207
280
|
}),
|
|
208
|
-
adapters.length > 1 ? /* @__PURE__ */ jsx(
|
|
281
|
+
adapters.length > 1 ? /* @__PURE__ */ jsx(FilterRow, {
|
|
209
282
|
label: "Engine",
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
value:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
283
|
+
children: /* @__PURE__ */ jsx(FacetSelect, {
|
|
284
|
+
label: "Engine",
|
|
285
|
+
value: config.adapters,
|
|
286
|
+
options: adapters.map((a) => ({
|
|
287
|
+
value: a,
|
|
288
|
+
label: a
|
|
289
|
+
})),
|
|
290
|
+
onChange: (adapters) => set({ adapters })
|
|
291
|
+
})
|
|
216
292
|
}) : null,
|
|
217
|
-
gateways.length > 1 ? /* @__PURE__ */ jsx(
|
|
293
|
+
gateways.length > 1 ? /* @__PURE__ */ jsx(FilterRow, {
|
|
218
294
|
label: "Gateway",
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
value:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
295
|
+
children: /* @__PURE__ */ jsx(FacetSelect, {
|
|
296
|
+
label: "Gateway",
|
|
297
|
+
value: config.gateways,
|
|
298
|
+
options: gateways.map((g) => ({
|
|
299
|
+
value: g.id,
|
|
300
|
+
label: g.name
|
|
301
|
+
})),
|
|
302
|
+
onChange: (gateways) => set({ gateways })
|
|
303
|
+
})
|
|
225
304
|
}) : null,
|
|
226
|
-
/* @__PURE__ */ jsx(
|
|
305
|
+
/* @__PURE__ */ jsx(FilterRow, {
|
|
227
306
|
label: "Group",
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
307
|
+
children: /* @__PURE__ */ jsx(OneOfSelect, {
|
|
308
|
+
label: "Group",
|
|
309
|
+
value: config.groupBy,
|
|
310
|
+
options: [
|
|
311
|
+
{
|
|
312
|
+
value: "none",
|
|
313
|
+
label: "No grouping"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
value: "state",
|
|
317
|
+
label: "By state"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
value: "adapter",
|
|
321
|
+
label: "By engine"
|
|
322
|
+
},
|
|
323
|
+
...gateways.length > 1 ? [{
|
|
324
|
+
value: "gateway",
|
|
325
|
+
label: "By gateway"
|
|
326
|
+
}] : []
|
|
327
|
+
],
|
|
328
|
+
onChange: (groupBy) => set({ groupBy })
|
|
329
|
+
})
|
|
248
330
|
}),
|
|
249
|
-
/* @__PURE__ */ jsx(
|
|
331
|
+
/* @__PURE__ */ jsx(FilterRow, {
|
|
250
332
|
label: "Sort",
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
333
|
+
children: /* @__PURE__ */ jsx(OneOfSelect, {
|
|
334
|
+
label: "Sort",
|
|
335
|
+
value: config.sortBy,
|
|
336
|
+
options: [
|
|
337
|
+
{
|
|
338
|
+
value: "recent",
|
|
339
|
+
label: "Recent"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
value: "name",
|
|
343
|
+
label: "Name"
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
value: "state",
|
|
347
|
+
label: "State"
|
|
348
|
+
},
|
|
349
|
+
...gateways.length > 1 ? [{
|
|
350
|
+
value: "gateway",
|
|
351
|
+
label: "Gateway"
|
|
352
|
+
}] : []
|
|
353
|
+
],
|
|
354
|
+
onChange: (sortBy) => set({ sortBy })
|
|
355
|
+
})
|
|
271
356
|
})
|
|
272
357
|
]
|
|
273
358
|
}),
|
|
274
359
|
subset ? /* @__PURE__ */ jsxs("div", {
|
|
275
|
-
className: "flex items-center gap-2 text-label text-fg-4",
|
|
360
|
+
className: "flex items-center gap-2 px-3 text-label text-fg-4",
|
|
276
361
|
children: [/* @__PURE__ */ jsxs("span", { children: [
|
|
277
362
|
subset.shown,
|
|
278
363
|
" of ",
|
|
@@ -285,21 +370,25 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
285
370
|
children: "Show all"
|
|
286
371
|
})]
|
|
287
372
|
}) : null,
|
|
288
|
-
rows.length === 0 ? emptyState ?? /* @__PURE__ */ jsx(Empty, {
|
|
289
|
-
|
|
290
|
-
" "
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
373
|
+
rows.length === 0 ? emptyState ?? /* @__PURE__ */ jsx(Empty, {
|
|
374
|
+
icon: /* @__PURE__ */ jsx(Layers, {}),
|
|
375
|
+
title: "No sessions yet"
|
|
376
|
+
}) : visible.length === 0 ? hasFacetFilter(config) ? /* @__PURE__ */ jsx(Empty, {
|
|
377
|
+
icon: /* @__PURE__ */ jsx(SearchX, {}),
|
|
378
|
+
title: "No matches",
|
|
379
|
+
description: "No session matches the current search and filters.",
|
|
380
|
+
action: "Clear filters",
|
|
381
|
+
onAction: () => onConfigChange(clearFilters(config))
|
|
382
|
+
}) : /* @__PURE__ */ jsx(Empty, {
|
|
383
|
+
icon: /* @__PURE__ */ jsx(Layers, {}),
|
|
384
|
+
title: "Nothing here",
|
|
385
|
+
description: "No session to show."
|
|
386
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
298
387
|
className: "flex flex-col gap-4",
|
|
299
388
|
children: groups.map((group) => /* @__PURE__ */ jsxs("div", {
|
|
300
389
|
className: "flex flex-col gap-1",
|
|
301
390
|
children: [config.groupBy !== "none" && group.label ? /* @__PURE__ */ jsxs("div", {
|
|
302
|
-
className: "flex items-baseline gap-2 px-
|
|
391
|
+
className: "flex items-baseline gap-2 px-3 text-label font-medium text-fg-4",
|
|
303
392
|
children: [/* @__PURE__ */ jsx("span", {
|
|
304
393
|
className: "uppercase tracking-wide",
|
|
305
394
|
children: group.label
|
|
@@ -320,100 +409,101 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
320
409
|
]
|
|
321
410
|
});
|
|
322
411
|
}
|
|
323
|
-
function Empty({ children }) {
|
|
324
|
-
return /* @__PURE__ */ jsx("div", {
|
|
325
|
-
className: "px-2.5 py-6 text-center text-body-sm text-fg-4",
|
|
326
|
-
children
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
412
|
function SessionRowItem({ row, active, showGateway, onSelect, onDelete, onRename }) {
|
|
330
413
|
const { info } = row;
|
|
331
|
-
const meta = STATUS_META[info.status];
|
|
332
414
|
const [editing, setEditing] = useState(false);
|
|
415
|
+
const folder = info.cwd.split("/").filter(Boolean).pop() ?? info.cwd;
|
|
416
|
+
const details = [
|
|
417
|
+
showGateway ? row.hostName : void 0,
|
|
418
|
+
friendlyModel(info.model),
|
|
419
|
+
folder,
|
|
420
|
+
info.profile ? `@${info.profile}` : void 0,
|
|
421
|
+
formatCost(info.totalCostUsd)
|
|
422
|
+
].filter(Boolean);
|
|
333
423
|
return /* @__PURE__ */ jsxs("div", {
|
|
334
424
|
"data-slot": "session-row",
|
|
335
425
|
"data-active": active || void 0,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
onCancel: () => setEditing(false)
|
|
350
|
-
}) : /* @__PURE__ */ jsx("button", {
|
|
351
|
-
type: "button",
|
|
352
|
-
onClick: () => onSelect?.(row),
|
|
353
|
-
className: "min-w-0 truncate text-left text-body-sm font-medium text-fg-1 outline-none",
|
|
354
|
-
children: sessionLabel(info)
|
|
355
|
-
}),
|
|
356
|
-
/* @__PURE__ */ jsx(Badge, {
|
|
357
|
-
variant: meta.variant,
|
|
358
|
-
dot: true,
|
|
359
|
-
className: "shrink-0",
|
|
360
|
-
children: meta.label
|
|
361
|
-
}),
|
|
362
|
-
row.unseen > 0 ? /* @__PURE__ */ jsx(Badge, {
|
|
363
|
-
variant: "accent",
|
|
364
|
-
className: "shrink-0",
|
|
365
|
-
title: `${row.unseen} new`,
|
|
366
|
-
children: row.unseen
|
|
367
|
-
}) : null
|
|
368
|
-
]
|
|
369
|
-
}), /* @__PURE__ */ jsxs("button", {
|
|
426
|
+
onClick: () => !editing && onSelect?.(row),
|
|
427
|
+
className: cn("group flex cursor-pointer flex-col gap-0.5 text-left transition-colors", rowShapeClass(active === true)),
|
|
428
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
429
|
+
className: "flex items-center gap-1.5",
|
|
430
|
+
children: [
|
|
431
|
+
editing && onRename ? /* @__PURE__ */ jsx(NameEditor, {
|
|
432
|
+
initial: info.title ?? "",
|
|
433
|
+
onCommit: (title) => {
|
|
434
|
+
setEditing(false);
|
|
435
|
+
onRename(row, title);
|
|
436
|
+
},
|
|
437
|
+
onCancel: () => setEditing(false)
|
|
438
|
+
}) : /* @__PURE__ */ jsx("button", {
|
|
370
439
|
type: "button",
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
440
|
+
className: cn("min-w-0 flex-1 truncate text-left text-body-sm outline-none", active ? "font-medium text-fg-1" : "text-fg-2"),
|
|
441
|
+
children: sessionLabel(info)
|
|
442
|
+
}),
|
|
443
|
+
row.unseen > 0 ? /* @__PURE__ */ jsx("span", {
|
|
444
|
+
title: `${row.unseen} new`,
|
|
445
|
+
className: "shrink-0 rounded-full bg-accent px-1.5 text-label text-accent-fg",
|
|
446
|
+
children: row.unseen
|
|
447
|
+
}) : null,
|
|
448
|
+
/* @__PURE__ */ jsx("span", {
|
|
449
|
+
className: "shrink-0 text-label text-fg-4",
|
|
450
|
+
children: formatRelativeTime(info.lastActivityAt ?? info.createdAt)
|
|
451
|
+
}),
|
|
452
|
+
/* @__PURE__ */ jsx(SessionStatusIcon, { row })
|
|
453
|
+
]
|
|
454
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
455
|
+
className: "flex items-center gap-1 text-label text-fg-4",
|
|
456
|
+
children: [
|
|
457
|
+
/* @__PURE__ */ jsx("button", {
|
|
458
|
+
type: "button",
|
|
459
|
+
tabIndex: -1,
|
|
460
|
+
className: "min-w-0 flex-1 truncate text-left font-mono outline-none",
|
|
461
|
+
children: details.join(" · ")
|
|
462
|
+
}),
|
|
463
|
+
onRename && !editing ? /* @__PURE__ */ jsx(Button, {
|
|
464
|
+
variant: "ghost",
|
|
465
|
+
size: "icon-sm",
|
|
466
|
+
"aria-label": "Rename session",
|
|
467
|
+
className: "size-5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100",
|
|
468
|
+
onClick: (e) => {
|
|
469
|
+
e.stopPropagation();
|
|
470
|
+
setEditing(true);
|
|
471
|
+
},
|
|
472
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "size-3 text-fg-3" })
|
|
473
|
+
}) : null,
|
|
474
|
+
onDelete ? /* @__PURE__ */ jsx(Button, {
|
|
475
|
+
variant: "ghost",
|
|
476
|
+
size: "icon-sm",
|
|
477
|
+
"aria-label": "Close session",
|
|
478
|
+
className: "size-5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100",
|
|
479
|
+
onClick: (e) => {
|
|
480
|
+
e.stopPropagation();
|
|
481
|
+
onDelete(row);
|
|
482
|
+
},
|
|
483
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "size-3 text-fg-3" })
|
|
484
|
+
}) : null
|
|
485
|
+
]
|
|
486
|
+
})]
|
|
414
487
|
});
|
|
415
488
|
}
|
|
416
489
|
/**
|
|
490
|
+
* State as one glyph on the right edge — a ringing bell when it wants a human, a
|
|
491
|
+
* spinner while it works, a moon when it is only sleeping. Replaces the text
|
|
492
|
+
* badge: in a sidebar the word costs more room than it earns, and the states
|
|
493
|
+
* that matter are the two you can recognise without reading.
|
|
494
|
+
*/
|
|
495
|
+
function SessionStatusIcon({ row }) {
|
|
496
|
+
const { info } = row;
|
|
497
|
+
if (info.pendingPermissionCount > 0 || info.status === "awaiting_approval") return /* @__PURE__ */ jsx(BellRing, { className: "size-3.5 shrink-0 animate-pulse text-warning" });
|
|
498
|
+
if (info.status === "running" || info.status === "starting") return /* @__PURE__ */ jsx(Spinner, { className: "size-3.5 shrink-0 text-info" });
|
|
499
|
+
switch (info.status) {
|
|
500
|
+
case "failed": return /* @__PURE__ */ jsx(CircleAlert, { className: "size-3.5 shrink-0 text-danger" });
|
|
501
|
+
case "closed": return /* @__PURE__ */ jsx(CircleSlash, { className: "size-3.5 shrink-0 text-fg-4" });
|
|
502
|
+
case "parked": return /* @__PURE__ */ jsx(PauseCircle, { className: "size-3.5 shrink-0 text-fg-3" });
|
|
503
|
+
default: return /* @__PURE__ */ jsx(Moon, { className: "size-3.5 shrink-0 text-fg-4" });
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
417
507
|
* Inline rename. Enter commits, Escape cancels, blur commits — but only a blur
|
|
418
508
|
* that is still inside this document: switching windows must not silently commit,
|
|
419
509
|
* nor kill the editor in the frame it opened.
|
|
@@ -442,6 +532,24 @@ function NameEditor({ initial, onCommit, onCancel }) {
|
|
|
442
532
|
}
|
|
443
533
|
/** A multi-select facet. Empty = no filter, which is why the trigger reads the
|
|
444
534
|
* facet's name rather than "All": nothing is being excluded. */
|
|
535
|
+
/**
|
|
536
|
+
* One labelled control row. The label column is fixed so every control starts
|
|
537
|
+
* on the same x — the thing that makes a stack of them read as a form rather
|
|
538
|
+
* than as five unrelated widgets.
|
|
539
|
+
*/
|
|
540
|
+
function FilterRow({ label, children }) {
|
|
541
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
542
|
+
className: "flex items-center gap-2",
|
|
543
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
544
|
+
"aria-hidden": true,
|
|
545
|
+
className: "w-14 shrink-0 truncate text-label text-fg-3",
|
|
546
|
+
children: label
|
|
547
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
548
|
+
className: "min-w-0 flex-1",
|
|
549
|
+
children
|
|
550
|
+
})]
|
|
551
|
+
});
|
|
552
|
+
}
|
|
445
553
|
function FacetSelect({ label, value, options, onChange }) {
|
|
446
554
|
return /* @__PURE__ */ jsxs("div", {
|
|
447
555
|
className: "flex items-center gap-1",
|
|
@@ -451,8 +559,8 @@ function FacetSelect({ label, value, options, onChange }) {
|
|
|
451
559
|
onValueChange: (v) => onChange(v),
|
|
452
560
|
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
453
561
|
"aria-label": label,
|
|
454
|
-
className: "min-w-
|
|
455
|
-
children: /* @__PURE__ */ jsx(SelectValue, { children: value.length === 0 ?
|
|
562
|
+
className: "min-w-0 flex-1",
|
|
563
|
+
children: /* @__PURE__ */ jsx(SelectValue, { children: value.length === 0 ? "All" : value.length === 1 ? options.find((o) => o.value === value[0])?.label ?? "All" : `${value.length} selected` })
|
|
456
564
|
}), /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
|
|
457
565
|
value: option.value,
|
|
458
566
|
children: /* @__PURE__ */ jsx(SelectItemText, { children: option.label })
|
|
@@ -472,7 +580,7 @@ function OneOfSelect({ label, value, options, onChange }) {
|
|
|
472
580
|
onValueChange: (v) => onChange(v),
|
|
473
581
|
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
474
582
|
"aria-label": label,
|
|
475
|
-
className: "min-w-
|
|
583
|
+
className: "w-full min-w-0",
|
|
476
584
|
children: /* @__PURE__ */ jsx(SelectValue, { children: options.find((o) => o.value === value)?.label ?? label })
|
|
477
585
|
}), /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
|
|
478
586
|
value: option.value,
|
|
@@ -481,6 +589,84 @@ function OneOfSelect({ label, value, options, onChange }) {
|
|
|
481
589
|
});
|
|
482
590
|
}
|
|
483
591
|
//#endregion
|
|
484
|
-
|
|
592
|
+
//#region src/components/agent/EngineIcon.tsx
|
|
593
|
+
/**
|
|
594
|
+
* The engine's own mark, monochrome.
|
|
595
|
+
*
|
|
596
|
+
* Inlined rather than depended on: the React package these come from
|
|
597
|
+
* (`@lobehub/icons`) pulls antd, `@lobehub/ui` and a second copy of
|
|
598
|
+
* lucide-react — an absurd amount of bundle for a few glyphs in a sidebar.
|
|
599
|
+
* These are paths from `@lobehub/icons-static-svg` (MIT, © LobeHub), already
|
|
600
|
+
* `fill="currentColor"` single-path marks, so they take the row's colour like
|
|
601
|
+
* any other glyph and need no light/dark variants.
|
|
602
|
+
*
|
|
603
|
+
* The marks are trademarks of their owners (Anthropic, OpenAI, Google,
|
|
604
|
+
* DeepSeek, Moonshot), used here only to identify which engine a session runs
|
|
605
|
+
* on.
|
|
606
|
+
*
|
|
607
|
+
* Codex is drawn as OpenAI: the session's engine *is* OpenAI's, and OpenAI's
|
|
608
|
+
* mark is the one a person recognises at 12px.
|
|
609
|
+
*/
|
|
610
|
+
const PATHS = {
|
|
611
|
+
claude: {
|
|
612
|
+
title: "Claude",
|
|
613
|
+
d: "M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"
|
|
614
|
+
},
|
|
615
|
+
codex: {
|
|
616
|
+
title: "OpenAI",
|
|
617
|
+
d: "M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"
|
|
618
|
+
},
|
|
619
|
+
gemini: {
|
|
620
|
+
title: "Gemini",
|
|
621
|
+
d: "M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z"
|
|
622
|
+
},
|
|
623
|
+
deepseek: {
|
|
624
|
+
title: "DeepSeek",
|
|
625
|
+
d: "M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z"
|
|
626
|
+
},
|
|
627
|
+
moonshot: {
|
|
628
|
+
title: "Moonshot",
|
|
629
|
+
d: "M1.052 16.916l9.539 2.552a21.007 21.007 0 00.06 2.033l5.956 1.593a11.997 11.997 0 01-5.586.865l-.18-.016-.044-.004-.084-.009-.094-.01a11.605 11.605 0 01-.157-.02l-.107-.014-.11-.016a11.962 11.962 0 01-.32-.051l-.042-.008-.075-.013-.107-.02-.07-.015-.093-.019-.075-.016-.095-.02-.097-.023-.094-.022-.068-.017-.088-.022-.09-.024-.095-.025-.082-.023-.109-.03-.062-.02-.084-.025-.093-.028-.105-.034-.058-.019-.08-.026-.09-.031-.066-.024a6.293 6.293 0 01-.044-.015l-.068-.025-.101-.037-.057-.022-.08-.03-.087-.035-.088-.035-.079-.032-.095-.04-.063-.028-.063-.027a5.655 5.655 0 01-.041-.018l-.066-.03-.103-.047-.052-.024-.096-.046-.062-.03-.084-.04-.086-.044-.093-.047-.052-.027-.103-.055-.057-.03-.058-.032a6.49 6.49 0 01-.046-.026l-.094-.053-.06-.034-.051-.03-.072-.041-.082-.05-.093-.056-.052-.032-.084-.053-.061-.039-.079-.05-.07-.047-.053-.035a7.785 7.785 0 01-.054-.036l-.044-.03-.044-.03a6.066 6.066 0 01-.04-.028l-.057-.04-.076-.054-.069-.05-.074-.054-.056-.042-.076-.057-.076-.059-.086-.067-.045-.035-.064-.052-.074-.06-.089-.073-.046-.039-.046-.039a7.516 7.516 0 01-.043-.037l-.045-.04-.061-.053-.07-.062-.068-.06-.062-.058-.067-.062-.053-.05-.088-.084a13.28 13.28 0 01-.099-.097l-.029-.028-.041-.042-.069-.07-.05-.051-.05-.053a6.457 6.457 0 01-.168-.179l-.08-.088-.062-.07-.071-.08-.042-.049-.053-.062-.058-.068-.046-.056a7.175 7.175 0 01-.027-.033l-.045-.055-.066-.082-.041-.052-.05-.064-.02-.025a11.99 11.99 0 01-1.44-2.402zm-1.02-5.794l11.353 3.037a20.468 20.468 0 00-.469 2.011l10.817 2.894a12.076 12.076 0 01-1.845 2.005L.657 15.923l-.016-.046-.035-.104a11.965 11.965 0 01-.05-.153l-.007-.023a11.896 11.896 0 01-.207-.741l-.03-.126-.018-.08-.021-.097-.018-.081-.018-.09-.017-.084-.018-.094c-.026-.141-.05-.283-.071-.426l-.017-.118-.011-.083-.013-.102a12.01 12.01 0 01-.019-.161l-.005-.047a12.12 12.12 0 01-.034-2.145zm1.593-5.15l11.948 3.196c-.368.605-.705 1.231-1.01 1.875l11.295 3.022c-.142.82-.368 1.612-.668 2.365l-11.55-3.09L.124 10.26l.015-.1.008-.049.01-.067.015-.087.018-.098c.026-.148.056-.295.088-.442l.028-.124.02-.085.024-.097c.022-.09.045-.18.07-.268l.028-.102.023-.083.03-.1.025-.082.03-.096.026-.082.031-.095a11.896 11.896 0 011.01-2.232zm4.442-4.4L17.352 4.59a20.77 20.77 0 00-1.688 1.721l7.823 2.093c.267.852.442 1.744.513 2.665L2.106 5.213l.045-.065.027-.04.04-.055.046-.065.055-.076.054-.072.064-.086.05-.065.057-.073.055-.07.06-.074.055-.069.065-.077.054-.066.066-.077.053-.06.072-.082.053-.06.067-.074.054-.058.073-.078.058-.06.063-.067.168-.17.1-.098.059-.056.076-.071a12.084 12.084 0 012.272-1.677zM12.017 0h.097l.082.001.069.001.054.002.068.002.046.001.076.003.047.002.06.003.054.002.087.005.105.007.144.011.088.007.044.004.077.008.082.008.047.005.102.012.05.006.108.014.081.01.042.006.065.01.207.032.07.012.065.011.14.026.092.018.11.022.046.01.075.016.041.01L14.7.3l.042.01.065.015.049.012.071.017.096.024.112.03.113.03.113.032.05.015.07.02.078.024.073.023.05.016.05.016.076.025.099.033.102.036.048.017.064.023.093.034.11.041.116.045.1.04.047.02.06.024.041.018.063.026.04.018.057.025.11.048.1.046.074.035.075.036.06.028.092.046.091.045.102.052.053.028.049.026.046.024.06.033.041.022.052.029.088.05.106.06.087.051.057.034.053.032.096.059.088.055.098.062.036.024.064.041.084.056.04.027.062.042.062.043.023.017c.054.037.108.075.161.114l.083.06.065.048.056.043.086.065.082.064.04.03.05.041.086.069.079.065.085.071c.712.6 1.353 1.283 1.909 2.031L7.222.994l.062-.027.065-.028.081-.034.086-.035c.113-.045.227-.09.341-.131l.096-.035.093-.033.084-.03.096-.031c.087-.03.176-.058.264-.085l.091-.027.086-.025.102-.03.085-.023.1-.026L9.04.37l.09-.023.091-.022.095-.022.09-.02.098-.021.091-.02.095-.018.092-.018.1-.018.091-.016.098-.017.092-.014.097-.015.092-.013.102-.013.091-.012.105-.012.09-.01.105-.01c.093-.01.186-.018.28-.024l.106-.008.09-.005.11-.006.093-.004.1-.004.097-.002.099-.002.197-.002z"
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
/**
|
|
633
|
+
* Which mark a session wears.
|
|
634
|
+
*
|
|
635
|
+
* The two first-party engines are named directly. A `provider` session is
|
|
636
|
+
* whatever the host wired up, so its *model* is the only thing that says whose
|
|
637
|
+
* it is — sniffed loosely on purpose (`gemini-2.5-pro`, `deepseek-chat`,
|
|
638
|
+
* `kimi-k2`), and falling through to no mark rather than guessing wrong.
|
|
639
|
+
*/
|
|
640
|
+
function engineMark(engine, model) {
|
|
641
|
+
if (engine === "claude") return "claude";
|
|
642
|
+
if (engine === "codex") return "codex";
|
|
643
|
+
const id = model?.toLowerCase() ?? "";
|
|
644
|
+
if (!id) return void 0;
|
|
645
|
+
if (id.includes("gemini")) return "gemini";
|
|
646
|
+
if (id.includes("deepseek")) return "deepseek";
|
|
647
|
+
if (id.includes("moonshot") || id.includes("kimi")) return "moonshot";
|
|
648
|
+
if (id.includes("claude")) return "claude";
|
|
649
|
+
if (id.startsWith("gpt") || id.startsWith("o1") || id.startsWith("o3") || id.includes("openai")) return "codex";
|
|
650
|
+
}
|
|
651
|
+
function EngineIcon({ engine, model, className }) {
|
|
652
|
+
const mark = PATHS[engineMark(engine, model) ?? ""];
|
|
653
|
+
if (!mark) return /* @__PURE__ */ jsx("span", {
|
|
654
|
+
"aria-hidden": true,
|
|
655
|
+
title: engine,
|
|
656
|
+
className: cn("shrink-0 text-fg-3", className),
|
|
657
|
+
children: "·"
|
|
658
|
+
});
|
|
659
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
660
|
+
viewBox: "0 0 24 24",
|
|
661
|
+
fill: "currentColor",
|
|
662
|
+
fillRule: "evenodd",
|
|
663
|
+
role: "img",
|
|
664
|
+
"aria-label": mark.title,
|
|
665
|
+
className: cn("size-3 shrink-0 text-fg-3", className),
|
|
666
|
+
children: [/* @__PURE__ */ jsx("title", { children: mark.title }), /* @__PURE__ */ jsx("path", { d: mark.d })]
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
//#endregion
|
|
670
|
+
export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, Button, Card, CardContent, CardHeader, CardTitle, CodeBlock, Composer, ContextDialog, Conversation, ConversationContent, ConversationScrollButton, CopyButton, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, Empty, EmptyKey, EngineIcon, FileCard, HostFilesDialog, Input, Loader, McpDialog, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, ModelSelect, PERMISSION_MODES, PermissionModeSelect, PermissionPrompt, ProgressRing, PromptArea, PromptTokenText, QUESTION_BEHAVIORS, QuestionPrompt, Reasoning, Response, STATUS_META, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, SessionEmptyState, SessionInfoDialog, SessionList, SessionListItem, SessionPanel, SessionStatusIcon, SkillsDialog, Spinner, Splitter, StatusBar, Textarea, Tip, Toaster, ToolCallCard, TooltipContent, TooltipProvider, Transcript, TranscriptDensityProvider, TranscriptVariantProvider, UsageDialog, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
|
|
485
671
|
|
|
486
672
|
//# sourceMappingURL=index.mjs.map
|