@workerdeck/ui 0.16.0 → 0.18.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 +7 -0
- package/build/{SessionPanel-B9CHoq8x.d.mts → SessionPanel-CnU_IJ3-.d.mts} +36 -9
- package/build/{SessionPanel-DII9MmQ8.mjs → SessionPanel-DPx8Iz8a.mjs} +1432 -384
- package/build/SessionPanel-DPx8Iz8a.mjs.map +1 -0
- package/build/{format-DfI_je9S.d.mts → format-ljc3lKpA.d.mts} +1 -1
- package/build/format.d.mts +16 -5
- package/build/format.mjs +2 -3
- package/build/index.d.mts +288 -8
- package/build/index.mjs +620 -165
- package/build/index.mjs.map +1 -1
- package/build/{format-DqR56Y8l.mjs → status-BE-zg88x.mjs} +154 -2
- package/build/status-BE-zg88x.mjs.map +1 -0
- package/build/workspace.d.mts +4 -1
- package/build/workspace.mjs +4 -3
- package/build/workspace.mjs.map +1 -1
- package/package.json +8 -6
- package/src/components/agent/ContextRing.tsx +41 -0
- package/src/components/agent/EngineIcon.tsx +40 -0
- package/src/components/agent/ProjectIcon.tsx +119 -0
- package/src/components/agent/SessionBrowser.tsx +191 -17
- package/src/components/agent/SessionPanel.tsx +177 -2
- package/src/components/agent/SessionSteps.tsx +233 -0
- package/src/components/agent/SessionWorkspace.tsx +4 -0
- package/src/components/agent/StatusBar.tsx +4 -2
- package/src/components/agent/SubagentStrip.tsx +134 -0
- package/src/components/agent/ToolCallCard.tsx +72 -5
- package/src/components/agent/Transcript.tsx +212 -23
- package/src/components/agent/tool-result-fetch.tsx +36 -0
- package/src/components/agent/tool-result-image.tsx +209 -0
- package/src/components/agent/transcript-rows.ts +122 -23
- package/src/components/terminal/TerminalTranscript.tsx +154 -2
- package/src/components/terminal/affordances.tsx +34 -0
- package/src/components/terminal/blocks.ts +260 -0
- package/src/components/terminal/height.ts +73 -6
- package/src/components/terminal/image-box.ts +53 -0
- package/src/components/terminal/items.tsx +116 -79
- package/src/components/terminal/result-preview.ts +20 -6
- package/src/components/terminal/scrubber.tsx +172 -26
- package/src/components/terminal/tool-run.ts +177 -0
- package/src/index.ts +20 -1
- package/src/lib/status.ts +16 -3
- package/src/styles/terminal.css +85 -5
- package/src/styles/theme.css +42 -0
- package/build/SessionPanel-DII9MmQ8.mjs.map +0 -1
- package/build/format-DqR56Y8l.mjs.map +0 -1
- package/build/status-Ydzi7n6j.mjs +0 -143
- package/build/status-Ydzi7n6j.mjs.map +0 -1
package/build/index.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { a as
|
|
3
|
-
import { a as statusPresentation, c as windowLabel, i as modelLabel, o as tightestWindow, r as meterSeverity, t as contextSeverity } from "./status-Ydzi7n6j.mjs";
|
|
1
|
+
import { $ as toolIcon, A as PERMISSION_MODES, At as MenuSeparator, B as skillPrompt, Bt as badgeVariants, C as TerminalQuestionPrompt, Ct as DialogContent, D as parseUserQuestions, Dt as Menu, E as QuestionPrompt, Et as DialogTrigger, F as SkillsDialog, Ft as SelectItemText, G as Band, H as TerminalMarkdown, Ht as buttonVariants, I as McpDialog, It as SelectTrigger, J as Row, K as Blank, L as HostFilesDialog, Lt as SelectValue, M as permissionModeChoices, Mt as Select, N as permissionModeMeta, Nt as SelectContent, O as SubagentStrip, Ot as MenuContent, P as ModelSelect, Pt as SelectItem, Q as isMutatingTool, R as ContextDialog, Rt as Input, S as SessionInfoDialog, St as DialogClose, T as QUESTION_BEHAVIORS, Tt as DialogRow, U as TerminalDiff, Ut as cn, V as TerminalSurface, Vt as Button, W as previewPatch, X as WithActions, Y as CopyAction, Z as useAffordances, _ as Conversation, _t as Tip, a as Transcript, at as hashtagTrigger, b as StatusBar, bt as Dialog, c as ToolCallCard, ct as PromptArea, d as Response, dt as ProgressRing, et as TranscriptDensityProvider, f as PromptTokenText, ft as Splitter, g as FileCard, gt as copyText, h as Loader, ht as CopyButton, i as useMinuteClock, it as commandTrigger, j as PermissionModeSelect, jt as MenuTrigger, k as PermissionPrompt, kt as MenuItem, l as SessionEmptyState, lt as plainTextToSegments, m as MessageContent, mt as Spinner, n as UsageDialog, nt as useTranscriptDensity, o as TerminalItemView, ot as mentionTrigger, p as Message, pt as CodeBlock, q as Ink, r as UsageMeters, rt as useTranscriptVariant, s as TerminalTranscript, st as usePromptAreaState, t as SessionPanel, tt as TranscriptVariantProvider, u as Reasoning, ut as segmentsToPlainText, v as ConversationContent, vt as TooltipContent, w as TerminalPermissionPrompt, wt as DialogHeader, x as STATUS_META, xt as DialogBody, y as ConversationScrollButton, yt as TooltipProvider, z as Composer, zt as Badge } from "./SessionPanel-DPx8Iz8a.mjs";
|
|
2
|
+
import { _ as formatRelativeTime, a as modelLabel, b as rateLimitWindowSeconds, d as formatBytes, f as formatCost, g as formatRateLimitWindowLong, h as formatRateLimitWindow, i as meterSeverity, l as windowLabel, m as formatDuration, o as statusPresentation, p as formatCountdown, r as meterColorClass, s as tightestWindow, t as contextSeverity, u as formatAgoPrecise, v as formatTokens, x as toolInputPreview, y as friendlyModel } from "./status-BE-zg88x.mjs";
|
|
4
3
|
import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { BellRing, CircleAlert, CircleSlash, Layers, Moon, PauseCircle, Pencil, Search, SearchX, Trash2, X } from "lucide-react";
|
|
4
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Anchor, ArrowRight, Atom, Beaker, BellRing, Bike, Binary, Blocks, Bot, Box, Brain, Briefcase, Brush, Bug, Building2, Cable, Camera, Car, Cat, Check, ChevronDown, ChevronRight, CircleAlert, CircleSlash, CircuitBoard, Cloud, Code, Coffee, Cog, Compass, Container, Cpu, CreditCard, Database, Diamond, Dog, Dot, Feather, Film, Flame, FlaskConical, Folder, Gamepad2, Gauge, Gem, Ghost, Gift, GitBranch, Globe, GraduationCap, Hammer, Hexagon, House, Image, Key, Landmark, Laptop, Layers, Leaf, Library, Lightbulb, Lock, Mail, Map as Map$1, MessageCircle, Mic, Monitor, Moon, Mountain, Music, Network, Newspaper, Notebook, Orbit, Package, Palette, PauseCircle, PenTool, Pencil, Phone, PiggyBank, Plane, Plug, Puzzle, Radar, Radio, Receipt, Rocket, Ruler, Satellite, Scale, Scissors, Search, SearchX, Server, Shield, Ship, ShoppingCart, Signal, Smartphone, Sparkles, Sprout, Square, Star, Sun, Table, Tag, Target, Telescope, Terminal, TestTube, Trash2, TreePine, Trophy, Truck, Umbrella, Users, Wallet, Wand, Waves, Webhook, Wifi, Wrench, X, Zap } from "lucide-react";
|
|
7
6
|
import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
|
|
8
7
|
import { Toaster as Toaster$1, toast } from "sonner";
|
|
9
|
-
import { STATE_LABELS, STATE_ORDER, adaptersOf, clearFilters, filterRows, groupRows, hasFacetFilter, sessionLabel, subsetSummary } from "@workerdeck/protocol";
|
|
8
|
+
import { STATE_LABELS, STATE_ORDER, adaptersOf, clearFilters, filterRows, groupRows, hasFacetFilter, isAgentRecord, projectLabel, projectSubpath, projectsOf, sessionLabel, subagentLabel, subsetSummary } from "@workerdeck/protocol";
|
|
10
9
|
//#region src/components/ui/Card.tsx
|
|
11
10
|
function Card({ className, ...props }) {
|
|
12
11
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -311,6 +310,436 @@ function SessionList({ sessions, activeId, onSelect, onDelete, emptyText = "No s
|
|
|
311
310
|
});
|
|
312
311
|
}
|
|
313
312
|
//#endregion
|
|
313
|
+
//#region src/components/agent/ContextRing.tsx
|
|
314
|
+
/**
|
|
315
|
+
* How full a session's context window is, sized for a **list row**.
|
|
316
|
+
*
|
|
317
|
+
* The reading the session screen has always drawn, moved somewhere it answers a
|
|
318
|
+
* question the session screen cannot: *which* of these thirty sessions is
|
|
319
|
+
* bloating. That is also why it is a ring and not a number — across a list, a
|
|
320
|
+
* ring is read at a glance and `71%` has to be read one row at a time.
|
|
321
|
+
*
|
|
322
|
+
* **Absent draws nothing, and absent is not zero.** A promptless session, a
|
|
323
|
+
* parked one from before the field existed, or an engine that reports no window
|
|
324
|
+
* has no reading; an empty ring would claim its context is empty rather than
|
|
325
|
+
* unknown. The title carries the exact numbers for anyone who wants them.
|
|
326
|
+
*
|
|
327
|
+
* Shared rather than spelled per client: the dashboard's row and the VS Code
|
|
328
|
+
* sidebar's card both draw it, and two copies would be two sets of thresholds
|
|
329
|
+
* the day one of them is nudged.
|
|
330
|
+
*/
|
|
331
|
+
function ContextRing({ usage, size = 11, className }) {
|
|
332
|
+
if (usage === void 0) return null;
|
|
333
|
+
return /* @__PURE__ */ jsx("span", {
|
|
334
|
+
title: `Context ${usage.percentage.toFixed(0)}% · ${formatTokens(usage.totalTokens)} / ${formatTokens(usage.maxTokens)}`,
|
|
335
|
+
className: cn("shrink-0 leading-none", meterColorClass(usage.percentage), className),
|
|
336
|
+
children: /* @__PURE__ */ jsx(ProgressRing, {
|
|
337
|
+
value: usage.percentage,
|
|
338
|
+
size,
|
|
339
|
+
strokeWidth: 2
|
|
340
|
+
})
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
//#endregion
|
|
344
|
+
//#region src/components/agent/EngineIcon.tsx
|
|
345
|
+
/**
|
|
346
|
+
* The engine's own mark, monochrome.
|
|
347
|
+
*
|
|
348
|
+
* Inlined rather than depended on: the React package these come from
|
|
349
|
+
* (`@lobehub/icons`) pulls antd, `@lobehub/ui` and a second copy of
|
|
350
|
+
* lucide-react — an absurd amount of bundle for a few glyphs in a sidebar.
|
|
351
|
+
* These are paths from `@lobehub/icons-static-svg` (MIT, © LobeHub), already
|
|
352
|
+
* `fill="currentColor"` single-path marks, so they take the row's colour like
|
|
353
|
+
* any other glyph and need no light/dark variants.
|
|
354
|
+
*
|
|
355
|
+
* The marks are trademarks of their owners (Anthropic, OpenAI, Google,
|
|
356
|
+
* DeepSeek, Moonshot), used here only to identify which engine a session runs
|
|
357
|
+
* on.
|
|
358
|
+
*
|
|
359
|
+
* Codex is drawn as OpenAI: the session's engine *is* OpenAI's, and OpenAI's
|
|
360
|
+
* mark is the one a person recognises at 12px.
|
|
361
|
+
*/
|
|
362
|
+
const PATHS = {
|
|
363
|
+
claude: {
|
|
364
|
+
title: "Claude",
|
|
365
|
+
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"
|
|
366
|
+
},
|
|
367
|
+
codex: {
|
|
368
|
+
title: "OpenAI",
|
|
369
|
+
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"
|
|
370
|
+
},
|
|
371
|
+
gemini: {
|
|
372
|
+
title: "Gemini",
|
|
373
|
+
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"
|
|
374
|
+
},
|
|
375
|
+
deepseek: {
|
|
376
|
+
title: "DeepSeek",
|
|
377
|
+
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"
|
|
378
|
+
},
|
|
379
|
+
moonshot: {
|
|
380
|
+
title: "Moonshot",
|
|
381
|
+
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"
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
/**
|
|
385
|
+
* Which mark a session wears.
|
|
386
|
+
*
|
|
387
|
+
* The two first-party engines are named directly. A `provider` session is
|
|
388
|
+
* whatever the host wired up, so its *model* is the only thing that says whose
|
|
389
|
+
* it is — sniffed loosely on purpose (`gemini-2.5-pro`, `deepseek-chat`,
|
|
390
|
+
* `kimi-k2`), and falling through to no mark rather than guessing wrong.
|
|
391
|
+
*/
|
|
392
|
+
function engineMark(engine, model) {
|
|
393
|
+
if (engine === "claude") return "claude";
|
|
394
|
+
if (engine === "codex") return "codex";
|
|
395
|
+
const id = model?.toLowerCase() ?? "";
|
|
396
|
+
if (!id) return void 0;
|
|
397
|
+
if (id.includes("gemini")) return "gemini";
|
|
398
|
+
if (id.includes("deepseek")) return "deepseek";
|
|
399
|
+
if (id.includes("moonshot") || id.includes("kimi")) return "moonshot";
|
|
400
|
+
if (id.includes("claude")) return "claude";
|
|
401
|
+
if (id.startsWith("gpt") || id.startsWith("o1") || id.startsWith("o3") || id.includes("openai")) return "codex";
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Which engines wear their vendor's colour, and **how far it reaches**.
|
|
405
|
+
*
|
|
406
|
+
* `MARK` is the glyph, `TEXT` is the model name beside it. They are the same for
|
|
407
|
+
* Anthropic and deliberately not for OpenAI, because the two brands differ in
|
|
408
|
+
* kind rather than in hue: coral is an accent, and OpenAI's guidelines forbid
|
|
409
|
+
* adding colour to the mark at all, so theirs is pure white/black. At full
|
|
410
|
+
* contrast that is right on a 12px glyph and wrong on an 11px label — a
|
|
411
|
+
* pure-white model name is *brighter than the session title above it*, which
|
|
412
|
+
* inverts the row's whole hierarchy to say something the mark has already said.
|
|
413
|
+
* So OpenAI's name keeps the muted line it always had, which is also the most
|
|
414
|
+
* literal reading of "don't add any colors".
|
|
415
|
+
*
|
|
416
|
+
* Anything absent falls through to muted on both counts.
|
|
417
|
+
*/
|
|
418
|
+
const VENDOR_MARK = {
|
|
419
|
+
claude: "text-vendor-claude",
|
|
420
|
+
codex: "text-vendor-openai"
|
|
421
|
+
};
|
|
422
|
+
const VENDOR_TEXT = { claude: "text-vendor-claude" };
|
|
423
|
+
/** The colour a session's engine mark wears. Pass it to `EngineIcon`'s
|
|
424
|
+
* `className` rather than to a parent: the svg carries its own `text-fg-3`,
|
|
425
|
+
* and only a class on the element itself is merged over it. */
|
|
426
|
+
function vendorMarkClass(engine, model) {
|
|
427
|
+
return VENDOR_MARK[engineMark(engine, model) ?? ""] ?? "text-fg-3";
|
|
428
|
+
}
|
|
429
|
+
/** The colour the model *name* wears beside that mark — muted unless the vendor
|
|
430
|
+
* is one whose accent survives at label size. See `VENDOR_TEXT`.
|
|
431
|
+
*
|
|
432
|
+
* The fallback is `text-fg-3` rather than the metadata line's own `text-fg-4`,
|
|
433
|
+
* so an unbranded model still sits one step above the project and gateway
|
|
434
|
+
* beside it — the order the spec lists them in, held without a colour. */
|
|
435
|
+
function vendorTextClass(engine, model) {
|
|
436
|
+
return VENDOR_TEXT[engineMark(engine, model) ?? ""] ?? "text-fg-3";
|
|
437
|
+
}
|
|
438
|
+
function EngineIcon({ engine, model, className }) {
|
|
439
|
+
const mark = PATHS[engineMark(engine, model) ?? ""];
|
|
440
|
+
if (!mark) return /* @__PURE__ */ jsx("span", {
|
|
441
|
+
"aria-hidden": true,
|
|
442
|
+
title: engine,
|
|
443
|
+
className: cn("shrink-0 text-fg-3", className),
|
|
444
|
+
children: "·"
|
|
445
|
+
});
|
|
446
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
447
|
+
viewBox: "0 0 24 24",
|
|
448
|
+
fill: "currentColor",
|
|
449
|
+
fillRule: "evenodd",
|
|
450
|
+
role: "img",
|
|
451
|
+
"aria-label": mark.title,
|
|
452
|
+
className: cn("size-3 shrink-0 text-fg-3", className),
|
|
453
|
+
children: [/* @__PURE__ */ jsx("title", { children: mark.title }), /* @__PURE__ */ jsx("path", { d: mark.d })]
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
//#endregion
|
|
457
|
+
//#region src/components/agent/ProjectIcon.tsx
|
|
458
|
+
/**
|
|
459
|
+
* A project's icon — the render side of protocol's `ProjectIcon`, for a list
|
|
460
|
+
* row or a group header.
|
|
461
|
+
*
|
|
462
|
+
* **The glyph arm is a curated set, and that is the design rather than a
|
|
463
|
+
* shortcut.** The gateway validates a glyph name by *shape* only (lucide's
|
|
464
|
+
* lowercase-kebab convention) and explicitly declines to grow an icon catalog,
|
|
465
|
+
* so the contract already says a client must fall back on a name it does not
|
|
466
|
+
* know.
|
|
467
|
+
*
|
|
468
|
+
* The alternative was measured rather than argued, against the VS Code
|
|
469
|
+
* sidebar's own bundle: `sidebar.js` is **31 KB** with one glyph, **77 KB**
|
|
470
|
+
* with the 110 below (~418 bytes each), and **927 KB** with a
|
|
471
|
+
* `import * as` over lucide's ~1,600 — which is what it costs, because a
|
|
472
|
+
* namespace import defeats tree-shaking by construction. (`DynamicIcon` is the
|
|
473
|
+
* third option and worse in a different currency: ~1,600 chunk files shipped
|
|
474
|
+
* inside the `.vsix`.) Twelve times the bundle to render a name nobody has
|
|
475
|
+
* declared yet is not a trade worth making; 46 KB to cover the names people
|
|
476
|
+
* actually use is.
|
|
477
|
+
*
|
|
478
|
+
* The set is chosen to cover what people call a project; an unlisted-but-valid
|
|
479
|
+
* name draws {@link Folder}, which is what the row drew before this feature
|
|
480
|
+
* existed. **Grow it freely** — each addition is ~400 bytes and the fallback
|
|
481
|
+
* means a missing one is a shrug, not a hole.
|
|
482
|
+
*
|
|
483
|
+
* **The image arm draws nothing until its bytes arrive**, and takes them as a
|
|
484
|
+
* resolved `src` rather than fetching: the wire carries only an address
|
|
485
|
+
* (media type, size, content hash), and *who* fetches it differs per client —
|
|
486
|
+
* a VS Code webview cannot reach a gateway at all and must be handed a data
|
|
487
|
+
* URL by its extension host, while a browser can fetch and `createObjectURL`.
|
|
488
|
+
* A component that fetched would be wrong on one of them. Absent `src` renders
|
|
489
|
+
* nothing rather than a placeholder box: an icon is decoration beside a name
|
|
490
|
+
* that is already there, and a box that becomes a picture a beat later is more
|
|
491
|
+
* movement than the picture is worth.
|
|
492
|
+
*
|
|
493
|
+
* One thing an image icon cannot do, and a glyph can: **take the row's
|
|
494
|
+
* colour.** An `<img>`-embedded SVG is its own document, so `currentColor` does
|
|
495
|
+
* not reach it and its own `prefers-color-scheme` resolves against the *OS*
|
|
496
|
+
* rather than the host's theme (measured: it does resolve, which is the
|
|
497
|
+
* surprise — so a monochrome mark tuned for both schemes is right on a dark OS
|
|
498
|
+
* in a dark editor and wrong on a light OS in a dark one). A repo that wants a
|
|
499
|
+
* mark that always matches its row should declare a glyph; one that wants its
|
|
500
|
+
* brand should declare the image and accept that it is a picture.
|
|
501
|
+
*/
|
|
502
|
+
const GLYPHS = {
|
|
503
|
+
anchor: Anchor,
|
|
504
|
+
atom: Atom,
|
|
505
|
+
beaker: Beaker,
|
|
506
|
+
bike: Bike,
|
|
507
|
+
binary: Binary,
|
|
508
|
+
blocks: Blocks,
|
|
509
|
+
bot: Bot,
|
|
510
|
+
box: Box,
|
|
511
|
+
brain: Brain,
|
|
512
|
+
briefcase: Briefcase,
|
|
513
|
+
brush: Brush,
|
|
514
|
+
bug: Bug,
|
|
515
|
+
"building-2": Building2,
|
|
516
|
+
cable: Cable,
|
|
517
|
+
camera: Camera,
|
|
518
|
+
car: Car,
|
|
519
|
+
cat: Cat,
|
|
520
|
+
"circuit-board": CircuitBoard,
|
|
521
|
+
cloud: Cloud,
|
|
522
|
+
code: Code,
|
|
523
|
+
coffee: Coffee,
|
|
524
|
+
cog: Cog,
|
|
525
|
+
compass: Compass,
|
|
526
|
+
container: Container,
|
|
527
|
+
cpu: Cpu,
|
|
528
|
+
"credit-card": CreditCard,
|
|
529
|
+
database: Database,
|
|
530
|
+
diamond: Diamond,
|
|
531
|
+
dog: Dog,
|
|
532
|
+
feather: Feather,
|
|
533
|
+
film: Film,
|
|
534
|
+
flame: Flame,
|
|
535
|
+
"flask-conical": FlaskConical,
|
|
536
|
+
folder: Folder,
|
|
537
|
+
"gamepad-2": Gamepad2,
|
|
538
|
+
gauge: Gauge,
|
|
539
|
+
gem: Gem,
|
|
540
|
+
ghost: Ghost,
|
|
541
|
+
gift: Gift,
|
|
542
|
+
"git-branch": GitBranch,
|
|
543
|
+
globe: Globe,
|
|
544
|
+
"graduation-cap": GraduationCap,
|
|
545
|
+
hammer: Hammer,
|
|
546
|
+
hexagon: Hexagon,
|
|
547
|
+
house: House,
|
|
548
|
+
image: Image,
|
|
549
|
+
key: Key,
|
|
550
|
+
landmark: Landmark,
|
|
551
|
+
laptop: Laptop,
|
|
552
|
+
layers: Layers,
|
|
553
|
+
leaf: Leaf,
|
|
554
|
+
library: Library,
|
|
555
|
+
lightbulb: Lightbulb,
|
|
556
|
+
lock: Lock,
|
|
557
|
+
mail: Mail,
|
|
558
|
+
map: Map$1,
|
|
559
|
+
"message-circle": MessageCircle,
|
|
560
|
+
mic: Mic,
|
|
561
|
+
monitor: Monitor,
|
|
562
|
+
moon: Moon,
|
|
563
|
+
mountain: Mountain,
|
|
564
|
+
music: Music,
|
|
565
|
+
network: Network,
|
|
566
|
+
newspaper: Newspaper,
|
|
567
|
+
notebook: Notebook,
|
|
568
|
+
orbit: Orbit,
|
|
569
|
+
package: Package,
|
|
570
|
+
palette: Palette,
|
|
571
|
+
"pen-tool": PenTool,
|
|
572
|
+
phone: Phone,
|
|
573
|
+
"piggy-bank": PiggyBank,
|
|
574
|
+
plane: Plane,
|
|
575
|
+
plug: Plug,
|
|
576
|
+
puzzle: Puzzle,
|
|
577
|
+
radar: Radar,
|
|
578
|
+
radio: Radio,
|
|
579
|
+
receipt: Receipt,
|
|
580
|
+
rocket: Rocket,
|
|
581
|
+
ruler: Ruler,
|
|
582
|
+
satellite: Satellite,
|
|
583
|
+
scale: Scale,
|
|
584
|
+
scissors: Scissors,
|
|
585
|
+
server: Server,
|
|
586
|
+
shield: Shield,
|
|
587
|
+
ship: Ship,
|
|
588
|
+
"shopping-cart": ShoppingCart,
|
|
589
|
+
signal: Signal,
|
|
590
|
+
smartphone: Smartphone,
|
|
591
|
+
sparkles: Sparkles,
|
|
592
|
+
sprout: Sprout,
|
|
593
|
+
square: Square,
|
|
594
|
+
star: Star,
|
|
595
|
+
sun: Sun,
|
|
596
|
+
table: Table,
|
|
597
|
+
tag: Tag,
|
|
598
|
+
target: Target,
|
|
599
|
+
telescope: Telescope,
|
|
600
|
+
terminal: Terminal,
|
|
601
|
+
"test-tube": TestTube,
|
|
602
|
+
"tree-pine": TreePine,
|
|
603
|
+
trophy: Trophy,
|
|
604
|
+
truck: Truck,
|
|
605
|
+
umbrella: Umbrella,
|
|
606
|
+
users: Users,
|
|
607
|
+
wallet: Wallet,
|
|
608
|
+
wand: Wand,
|
|
609
|
+
waves: Waves,
|
|
610
|
+
webhook: Webhook,
|
|
611
|
+
wifi: Wifi,
|
|
612
|
+
wrench: Wrench,
|
|
613
|
+
zap: Zap
|
|
614
|
+
};
|
|
615
|
+
function ProjectIcon({ icon, src, name, className }) {
|
|
616
|
+
if (!icon) return null;
|
|
617
|
+
if (icon.type === "image") {
|
|
618
|
+
if (!src) return null;
|
|
619
|
+
return /* @__PURE__ */ jsx("img", {
|
|
620
|
+
src,
|
|
621
|
+
alt: "",
|
|
622
|
+
"aria-hidden": true,
|
|
623
|
+
title: name,
|
|
624
|
+
className: cn("inline-block size-3 shrink-0 object-contain", className)
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
return /* @__PURE__ */ jsx(GLYPHS[icon.name] ?? Folder, { className: cn("inline-block size-3 shrink-0", className) });
|
|
628
|
+
}
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region src/components/agent/SessionSteps.tsx
|
|
631
|
+
function sessionSteps(info, onSelectSubagent) {
|
|
632
|
+
return (info.subagents ?? []).map((sub) => ({
|
|
633
|
+
key: sub.toolUseId,
|
|
634
|
+
label: subagentLabel(sub),
|
|
635
|
+
noun: "agent",
|
|
636
|
+
kind: isAgentRecord(sub) ? "agent" : "task",
|
|
637
|
+
state: stepState(sub.status),
|
|
638
|
+
detail: sub.toolCount > 0 ? String(sub.toolCount) : void 0,
|
|
639
|
+
title: `${subagentLabel(sub)} · ${sub.toolCount} tool${sub.toolCount === 1 ? "" : "s"}`,
|
|
640
|
+
onSelect: () => onSelectSubagent(sub.toolUseId)
|
|
641
|
+
}));
|
|
642
|
+
}
|
|
643
|
+
function stepState(status) {
|
|
644
|
+
switch (status) {
|
|
645
|
+
case "running": return "running";
|
|
646
|
+
case "failed": return "failed";
|
|
647
|
+
default: return "done";
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
/** How many of these are still going — the live half of the disclosure's count. */
|
|
651
|
+
function runningSteps(steps) {
|
|
652
|
+
return steps.filter((s) => s.state === "running").length;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* The disclosure, which is also the reading: `3 agents` — or `2 of 3 agents`
|
|
656
|
+
* while some have settled, because "how many are still going" is the live
|
|
657
|
+
* question and a bare total answers it wrong the moment one finishes.
|
|
658
|
+
*
|
|
659
|
+
* Sub-agents are an annotation on a working row rather than a state of their own
|
|
660
|
+
* (see `runningSubagents` in protocol's `session-list.ts`), so this never
|
|
661
|
+
* competes with the row's status glyph: that still says what the *session* is
|
|
662
|
+
* doing.
|
|
663
|
+
*/
|
|
664
|
+
function StepToggle({ expanded, running, total, noun, onToggle }) {
|
|
665
|
+
const label = running > 0 && running < total ? `${running}/${total}` : String(total);
|
|
666
|
+
const words = running > 0 && running < total ? `${running} of ${total} ${noun}s running` : `${total} ${noun}${total === 1 ? "" : "s"}`;
|
|
667
|
+
const Chevron = expanded ? ChevronDown : ChevronRight;
|
|
668
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
669
|
+
type: "button",
|
|
670
|
+
"aria-expanded": expanded,
|
|
671
|
+
"aria-label": `${expanded ? "Hide" : "Show"} ${words}`,
|
|
672
|
+
title: `${expanded ? "Hide" : "Show"} ${words}`,
|
|
673
|
+
onClick: (e) => {
|
|
674
|
+
e.stopPropagation();
|
|
675
|
+
onToggle();
|
|
676
|
+
},
|
|
677
|
+
className: cn("flex shrink-0 items-center gap-0.5 rounded px-0.5 outline-none", "hover:bg-surface-hover hover:text-fg-2", running > 0 ? "text-info" : "text-fg-4"),
|
|
678
|
+
children: [/* @__PURE__ */ jsx(Chevron, { className: "size-3" }), /* @__PURE__ */ jsx("span", {
|
|
679
|
+
className: "tabular-nums",
|
|
680
|
+
children: label
|
|
681
|
+
})]
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* One step under its session. Pressing an **agent** hands the panel over to that
|
|
686
|
+
* agent's own work — it is not a session and never becomes one, but it does now
|
|
687
|
+
* have a surface (`SessionPanel.openSubagent`). A host that cannot frame one
|
|
688
|
+
* falls back to revealing its `Task` row, which was this row's only meaning
|
|
689
|
+
* before the takeover existed. A **task** is not pressable at all; see
|
|
690
|
+
* {@link Step.kind}.
|
|
691
|
+
*
|
|
692
|
+
* Divided from the row's header and from each other by a rule rather than by
|
|
693
|
+
* indentation: these are a list *inside* the row, and at 11px an indent is not
|
|
694
|
+
* enough to say so. The rule is black at 25% so it darkens whatever the row is
|
|
695
|
+
* filled with, selected or not, without needing a colour per state.
|
|
696
|
+
*/
|
|
697
|
+
function StepRow({ step, onSelect }) {
|
|
698
|
+
const agent = step.kind === "agent";
|
|
699
|
+
const body = step.state === "failed" ? "text-danger" : agent ? "text-success" : "text-fg-4";
|
|
700
|
+
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
701
|
+
/* @__PURE__ */ jsx(StepIcon, {
|
|
702
|
+
state: step.state,
|
|
703
|
+
kind: step.kind
|
|
704
|
+
}),
|
|
705
|
+
/* @__PURE__ */ jsx("span", {
|
|
706
|
+
className: "min-w-0 flex-1 truncate",
|
|
707
|
+
children: step.label
|
|
708
|
+
}),
|
|
709
|
+
step.detail ? /* @__PURE__ */ jsx("span", {
|
|
710
|
+
className: "shrink-0 tabular-nums text-fg-4",
|
|
711
|
+
children: step.detail
|
|
712
|
+
}) : null,
|
|
713
|
+
agent ? /* @__PURE__ */ jsx(ArrowRight, { className: "size-3 shrink-0 opacity-60" }) : null
|
|
714
|
+
] });
|
|
715
|
+
const shape = "flex w-full items-center gap-2 border-t border-black/25 py-1 pl-3 pr-2 text-left text-label outline-none";
|
|
716
|
+
if (!agent) return /* @__PURE__ */ jsx("div", {
|
|
717
|
+
title: step.title,
|
|
718
|
+
onClick: (e) => e.stopPropagation(),
|
|
719
|
+
className: cn(shape, body),
|
|
720
|
+
children: content
|
|
721
|
+
});
|
|
722
|
+
return /* @__PURE__ */ jsx("button", {
|
|
723
|
+
type: "button",
|
|
724
|
+
title: step.title,
|
|
725
|
+
onClick: (e) => {
|
|
726
|
+
e.stopPropagation();
|
|
727
|
+
onSelect();
|
|
728
|
+
},
|
|
729
|
+
className: cn(shape, "hover:bg-surface-hover", body),
|
|
730
|
+
children: content
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
function StepIcon({ state, kind }) {
|
|
734
|
+
if (kind === "task" && state !== "running" && state !== "failed") return /* @__PURE__ */ jsx(Dot, { className: "size-3 shrink-0" });
|
|
735
|
+
switch (state) {
|
|
736
|
+
case "running": return /* @__PURE__ */ jsx(Spinner, { className: "size-3 shrink-0" });
|
|
737
|
+
case "failed": return /* @__PURE__ */ jsx(CircleAlert, { className: "size-3 shrink-0" });
|
|
738
|
+
case "pending": return /* @__PURE__ */ jsx(PauseCircle, { className: "size-3 shrink-0" });
|
|
739
|
+
default: return /* @__PURE__ */ jsx(Check, { className: "size-3 shrink-0" });
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
//#endregion
|
|
314
743
|
//#region src/components/agent/SessionBrowser.tsx
|
|
315
744
|
/**
|
|
316
745
|
* How a list row is drawn, in one place, so `SidebarRow` in `web` matches this
|
|
@@ -331,7 +760,7 @@ function SessionList({ sessions, activeId, onSelect, onDelete, emptyText = "No s
|
|
|
331
760
|
function rowShapeClass(active) {
|
|
332
761
|
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");
|
|
333
762
|
}
|
|
334
|
-
function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelect, onDelete, onRename, emptyState, showControls = true, className }) {
|
|
763
|
+
function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelect, onDelete, onRename, onSelectSubagent, emptyState, showControls = true, projectIcons, className }) {
|
|
335
764
|
const visible = useMemo(() => filterRows(rows, config, scope), [
|
|
336
765
|
rows,
|
|
337
766
|
config,
|
|
@@ -340,6 +769,7 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
340
769
|
const groups = useMemo(() => groupRows(visible, config), [visible, config]);
|
|
341
770
|
const subset = subsetSummary(config, scope, visible.length, rows.length);
|
|
342
771
|
const adapters = useMemo(() => adaptersOf(rows), [rows]);
|
|
772
|
+
const projects = useMemo(() => projectsOf(rows), [rows]);
|
|
343
773
|
const gateways = useMemo(() => {
|
|
344
774
|
const seen = /* @__PURE__ */ new Map();
|
|
345
775
|
for (const row of rows) seen.set(row.hostId, row.hostName);
|
|
@@ -405,6 +835,18 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
405
835
|
onChange: (gateways) => set({ gateways })
|
|
406
836
|
})
|
|
407
837
|
}) : null,
|
|
838
|
+
projects.length > 1 ? /* @__PURE__ */ jsx(FilterRow, {
|
|
839
|
+
label: "Project",
|
|
840
|
+
children: /* @__PURE__ */ jsx(FacetSelect, {
|
|
841
|
+
label: "Project",
|
|
842
|
+
value: config.projects ?? [],
|
|
843
|
+
options: projects.map((p) => ({
|
|
844
|
+
value: p.key,
|
|
845
|
+
label: p.label
|
|
846
|
+
})),
|
|
847
|
+
onChange: (next) => set({ projects: next })
|
|
848
|
+
})
|
|
849
|
+
}) : null,
|
|
408
850
|
/* @__PURE__ */ jsx(FilterRow, {
|
|
409
851
|
label: "Group",
|
|
410
852
|
children: /* @__PURE__ */ jsx(OneOfSelect, {
|
|
@@ -423,6 +865,10 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
423
865
|
value: "adapter",
|
|
424
866
|
label: "By engine"
|
|
425
867
|
},
|
|
868
|
+
...projects.length > 1 ? [{
|
|
869
|
+
value: "project",
|
|
870
|
+
label: "By project"
|
|
871
|
+
}] : [],
|
|
426
872
|
...gateways.length > 1 ? [{
|
|
427
873
|
value: "gateway",
|
|
428
874
|
label: "By gateway"
|
|
@@ -449,6 +895,10 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
449
895
|
value: "state",
|
|
450
896
|
label: "State"
|
|
451
897
|
},
|
|
898
|
+
...projects.length > 1 ? [{
|
|
899
|
+
value: "project",
|
|
900
|
+
label: "Project"
|
|
901
|
+
}] : [],
|
|
452
902
|
...gateways.length > 1 ? [{
|
|
453
903
|
value: "gateway",
|
|
454
904
|
label: "Gateway"
|
|
@@ -491,114 +941,197 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
|
|
|
491
941
|
children: groups.map((group) => /* @__PURE__ */ jsxs("div", {
|
|
492
942
|
className: "flex flex-col gap-1",
|
|
493
943
|
children: [config.groupBy !== "none" && group.label ? /* @__PURE__ */ jsxs("div", {
|
|
494
|
-
className: "flex items-
|
|
495
|
-
children: [
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
944
|
+
className: "flex items-center gap-2 px-3 text-label font-medium text-fg-4",
|
|
945
|
+
children: [
|
|
946
|
+
config.groupBy === "project" ? /* @__PURE__ */ jsx(ProjectIcon, {
|
|
947
|
+
icon: group.rows[0]?.info.project?.icon,
|
|
948
|
+
src: iconSrcOf(group.rows[0], projectIcons),
|
|
949
|
+
name: group.label
|
|
950
|
+
}) : null,
|
|
951
|
+
/* @__PURE__ */ jsx("span", {
|
|
952
|
+
className: "uppercase tracking-wide",
|
|
953
|
+
children: group.label
|
|
954
|
+
}),
|
|
955
|
+
/* @__PURE__ */ jsx("span", {
|
|
956
|
+
className: "text-fg-4/70",
|
|
957
|
+
children: group.rows.length
|
|
958
|
+
})
|
|
959
|
+
]
|
|
502
960
|
}) : null, group.rows.map((row) => /* @__PURE__ */ jsx(SessionRowItem, {
|
|
503
961
|
row,
|
|
504
962
|
active: row.info.id === activeId,
|
|
505
|
-
showGateway: gateways.length > 1,
|
|
963
|
+
showGateway: gateways.length > 1 && config.groupBy !== "gateway",
|
|
964
|
+
showProject: config.groupBy !== "project",
|
|
965
|
+
projectIcons,
|
|
506
966
|
onSelect,
|
|
507
967
|
onDelete,
|
|
508
|
-
onRename
|
|
968
|
+
onRename,
|
|
969
|
+
onSelectSubagent
|
|
509
970
|
}, `${row.hostId}:${row.info.id}`))]
|
|
510
971
|
}, group.key))
|
|
511
972
|
})
|
|
512
973
|
]
|
|
513
974
|
});
|
|
514
975
|
}
|
|
515
|
-
|
|
976
|
+
/** The bytes for a row's project icon, if it has an image one and the caller has
|
|
977
|
+
* fetched it yet. Shared by the row and its group header so the two cannot draw
|
|
978
|
+
* different pictures for one project. */
|
|
979
|
+
function iconSrcOf(row, icons) {
|
|
980
|
+
const icon = row?.info.project?.icon;
|
|
981
|
+
return icon?.type === "image" ? icons?.[icon.hash] : void 0;
|
|
982
|
+
}
|
|
983
|
+
function SessionRowItem({ row, active, showGateway, showProject = true, projectIcons, onSelect, onDelete, onRename, onSelectSubagent }) {
|
|
516
984
|
const { info } = row;
|
|
517
985
|
const [editing, setEditing] = useState(false);
|
|
518
|
-
const
|
|
986
|
+
const [expanded, setExpanded] = useState(false);
|
|
987
|
+
const project = showProject ? projectLabel(row) : projectSubpath(row);
|
|
988
|
+
const projectIcon = showProject ? info.project?.icon : void 0;
|
|
989
|
+
const engine = info.engine ?? "claude";
|
|
519
990
|
const details = [
|
|
991
|
+
project,
|
|
520
992
|
showGateway ? row.hostName : void 0,
|
|
521
|
-
friendlyModel(info.model),
|
|
522
|
-
folder,
|
|
523
993
|
info.profile ? `@${info.profile}` : void 0,
|
|
524
994
|
formatCost(info.totalCostUsd)
|
|
525
995
|
].filter(Boolean);
|
|
996
|
+
const steps = sessionSteps(info, (toolUseId) => onSelectSubagent ? onSelectSubagent(row, toolUseId) : onSelect?.(row));
|
|
997
|
+
const cut = project === void 0 ? -1 : details.indexOf(project);
|
|
526
998
|
return /* @__PURE__ */ jsxs("div", {
|
|
527
999
|
"data-slot": "session-row",
|
|
528
1000
|
"data-active": active || void 0,
|
|
529
1001
|
onClick: () => !editing && onSelect?.(row),
|
|
530
1002
|
className: cn("group flex cursor-pointer flex-col gap-0.5 text-left transition-colors", rowShapeClass(active === true)),
|
|
531
|
-
children: [
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
1003
|
+
children: [
|
|
1004
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1005
|
+
className: "flex items-center gap-1.5",
|
|
1006
|
+
children: [
|
|
1007
|
+
/* @__PURE__ */ jsx(Gutter, { children: /* @__PURE__ */ jsx(SessionStatusIcon, { row }) }),
|
|
1008
|
+
editing && onRename ? /* @__PURE__ */ jsx(NameEditor, {
|
|
1009
|
+
initial: info.title ?? "",
|
|
1010
|
+
onCommit: (title) => {
|
|
1011
|
+
setEditing(false);
|
|
1012
|
+
onRename(row, title);
|
|
1013
|
+
},
|
|
1014
|
+
onCancel: () => setEditing(false)
|
|
1015
|
+
}) : /* @__PURE__ */ jsx("button", {
|
|
1016
|
+
type: "button",
|
|
1017
|
+
className: cn("min-w-0 flex-1 truncate text-left text-body-sm outline-none", active ? "font-medium text-fg-1" : "text-fg-2"),
|
|
1018
|
+
children: sessionLabel(info)
|
|
1019
|
+
}),
|
|
1020
|
+
row.unseen > 0 ? /* @__PURE__ */ jsx("span", {
|
|
1021
|
+
title: `${row.unseen} new`,
|
|
1022
|
+
className: "shrink-0 rounded-full bg-accent px-1.5 text-label text-accent-fg",
|
|
1023
|
+
children: row.unseen
|
|
1024
|
+
}) : null,
|
|
1025
|
+
/* @__PURE__ */ jsx("span", {
|
|
1026
|
+
className: "shrink-0 text-label text-fg-4",
|
|
1027
|
+
children: formatRelativeTime(info.lastActivityAt ?? info.createdAt)
|
|
1028
|
+
}),
|
|
1029
|
+
/* @__PURE__ */ jsx(ContextRing, { usage: info.contextUsage })
|
|
1030
|
+
]
|
|
1031
|
+
}),
|
|
1032
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1033
|
+
className: "flex items-center gap-1 text-label text-fg-4",
|
|
1034
|
+
children: [
|
|
1035
|
+
/* @__PURE__ */ jsx(Gutter, { children: /* @__PURE__ */ jsx(EngineIcon, {
|
|
1036
|
+
engine,
|
|
1037
|
+
model: info.model,
|
|
1038
|
+
className: vendorMarkClass(engine, info.model)
|
|
1039
|
+
}) }),
|
|
1040
|
+
/* @__PURE__ */ jsxs("button", {
|
|
1041
|
+
type: "button",
|
|
1042
|
+
tabIndex: -1,
|
|
1043
|
+
className: "min-w-0 flex-1 truncate text-left font-mono outline-none",
|
|
1044
|
+
children: [
|
|
1045
|
+
/* @__PURE__ */ jsx("span", {
|
|
1046
|
+
className: vendorTextClass(engine, info.model),
|
|
1047
|
+
children: friendlyModel(info.model)
|
|
1048
|
+
}),
|
|
1049
|
+
details.length > 0 ? " · " : "",
|
|
1050
|
+
cut < 0 ? details.join(" · ") : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1051
|
+
details.slice(0, cut).map((part) => `${part} · `),
|
|
1052
|
+
/* @__PURE__ */ jsx(ProjectIcon, {
|
|
1053
|
+
icon: projectIcon,
|
|
1054
|
+
src: iconSrcOf(row, projectIcons),
|
|
1055
|
+
name: project,
|
|
1056
|
+
className: "mr-1 align-[-0.2em]"
|
|
1057
|
+
}),
|
|
1058
|
+
details.slice(cut).join(" · ")
|
|
1059
|
+
] })
|
|
1060
|
+
]
|
|
1061
|
+
}),
|
|
1062
|
+
steps.length > 0 ? /* @__PURE__ */ jsx(StepToggle, {
|
|
1063
|
+
expanded,
|
|
1064
|
+
running: runningSteps(steps),
|
|
1065
|
+
total: steps.length,
|
|
1066
|
+
noun: steps[0].noun,
|
|
1067
|
+
onToggle: () => setExpanded((v) => !v)
|
|
1068
|
+
}) : null,
|
|
1069
|
+
onRename && !editing ? /* @__PURE__ */ jsx(Button, {
|
|
1070
|
+
variant: "ghost",
|
|
1071
|
+
size: "icon-sm",
|
|
1072
|
+
"aria-label": "Rename session",
|
|
1073
|
+
className: "size-5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100",
|
|
1074
|
+
onClick: (e) => {
|
|
1075
|
+
e.stopPropagation();
|
|
1076
|
+
setEditing(true);
|
|
1077
|
+
},
|
|
1078
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "size-3 text-fg-3" })
|
|
1079
|
+
}) : null,
|
|
1080
|
+
onDelete ? /* @__PURE__ */ jsx(Button, {
|
|
1081
|
+
variant: "ghost",
|
|
1082
|
+
size: "icon-sm",
|
|
1083
|
+
"aria-label": "Close session",
|
|
1084
|
+
className: "size-5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100",
|
|
1085
|
+
onClick: (e) => {
|
|
1086
|
+
e.stopPropagation();
|
|
1087
|
+
onDelete(row);
|
|
1088
|
+
},
|
|
1089
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "size-3 text-fg-3" })
|
|
1090
|
+
}) : null
|
|
1091
|
+
]
|
|
1092
|
+
}),
|
|
1093
|
+
expanded ? steps.map((step) => /* @__PURE__ */ jsx(StepRow, {
|
|
1094
|
+
step,
|
|
1095
|
+
onSelect: step.onSelect
|
|
1096
|
+
}, step.key)) : null
|
|
1097
|
+
]
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* The one 14px cell both lines hang their glyph in.
|
|
1102
|
+
*
|
|
1103
|
+
* A shared column rather than a leading character: the state and the engine mark
|
|
1104
|
+
* are different widths and a bare glyph would let the two text columns start at
|
|
1105
|
+
* different x. Centring inside a fixed cell is what makes them agree —
|
|
1106
|
+
* `packages/ui`'s terminal-gutter argument at row scale.
|
|
1107
|
+
*/
|
|
1108
|
+
function Gutter({ children }) {
|
|
1109
|
+
return /* @__PURE__ */ jsx("span", {
|
|
1110
|
+
className: "flex w-3.5 shrink-0 items-center justify-center",
|
|
1111
|
+
children
|
|
590
1112
|
});
|
|
591
1113
|
}
|
|
592
1114
|
/**
|
|
593
|
-
* State as one glyph
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
1115
|
+
* State as one glyph — a ringing bell when it wants a human, a spinner while it
|
|
1116
|
+
* works, a moon when it is only sleeping. Replaces the text badge: in a sidebar
|
|
1117
|
+
* the word costs more room than it earns, and the states that matter are the two
|
|
1118
|
+
* you can recognise without reading.
|
|
1119
|
+
*
|
|
1120
|
+
* **It reads `row.state`, not `info.status`, and that distinction is the whole
|
|
1121
|
+
* point of the row model.** `sessionState` already folds in the arm this glyph
|
|
1122
|
+
* cannot see for itself: a *background* sub-agent outlives its turn by design, so
|
|
1123
|
+
* the turn ends, `status` comes to rest at `idle`, and the agent keeps working.
|
|
1124
|
+
* Reading the raw status drew a **moon on a row filed under the "Working"
|
|
1125
|
+
* header** — the list contradicting itself on one line, which is exactly what a
|
|
1126
|
+
* derived view model exists to prevent. The value was in scope and unread.
|
|
1127
|
+
*
|
|
1128
|
+
* The terminal statuses still come off `info.status`, because `ended` collapses
|
|
1129
|
+
* `failed` and `closed` into one bucket and those are worth telling apart here.
|
|
597
1130
|
*/
|
|
598
1131
|
function SessionStatusIcon({ row }) {
|
|
599
1132
|
const { info } = row;
|
|
600
|
-
if (
|
|
601
|
-
if (
|
|
1133
|
+
if (row.state === "attention") return /* @__PURE__ */ jsx(BellRing, { className: "size-3.5 shrink-0 animate-pulse text-warning" });
|
|
1134
|
+
if (row.state === "working") return /* @__PURE__ */ jsx(Spinner, { className: "size-3.5 shrink-0 text-info" });
|
|
602
1135
|
switch (info.status) {
|
|
603
1136
|
case "failed": return /* @__PURE__ */ jsx(CircleAlert, { className: "size-3.5 shrink-0 text-danger" });
|
|
604
1137
|
case "closed": return /* @__PURE__ */ jsx(CircleSlash, { className: "size-3.5 shrink-0 text-fg-4" });
|
|
@@ -692,84 +1225,6 @@ function OneOfSelect({ label, value, options, onChange }) {
|
|
|
692
1225
|
});
|
|
693
1226
|
}
|
|
694
1227
|
//#endregion
|
|
695
|
-
|
|
696
|
-
/**
|
|
697
|
-
* The engine's own mark, monochrome.
|
|
698
|
-
*
|
|
699
|
-
* Inlined rather than depended on: the React package these come from
|
|
700
|
-
* (`@lobehub/icons`) pulls antd, `@lobehub/ui` and a second copy of
|
|
701
|
-
* lucide-react — an absurd amount of bundle for a few glyphs in a sidebar.
|
|
702
|
-
* These are paths from `@lobehub/icons-static-svg` (MIT, © LobeHub), already
|
|
703
|
-
* `fill="currentColor"` single-path marks, so they take the row's colour like
|
|
704
|
-
* any other glyph and need no light/dark variants.
|
|
705
|
-
*
|
|
706
|
-
* The marks are trademarks of their owners (Anthropic, OpenAI, Google,
|
|
707
|
-
* DeepSeek, Moonshot), used here only to identify which engine a session runs
|
|
708
|
-
* on.
|
|
709
|
-
*
|
|
710
|
-
* Codex is drawn as OpenAI: the session's engine *is* OpenAI's, and OpenAI's
|
|
711
|
-
* mark is the one a person recognises at 12px.
|
|
712
|
-
*/
|
|
713
|
-
const PATHS = {
|
|
714
|
-
claude: {
|
|
715
|
-
title: "Claude",
|
|
716
|
-
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"
|
|
717
|
-
},
|
|
718
|
-
codex: {
|
|
719
|
-
title: "OpenAI",
|
|
720
|
-
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"
|
|
721
|
-
},
|
|
722
|
-
gemini: {
|
|
723
|
-
title: "Gemini",
|
|
724
|
-
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"
|
|
725
|
-
},
|
|
726
|
-
deepseek: {
|
|
727
|
-
title: "DeepSeek",
|
|
728
|
-
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"
|
|
729
|
-
},
|
|
730
|
-
moonshot: {
|
|
731
|
-
title: "Moonshot",
|
|
732
|
-
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"
|
|
733
|
-
}
|
|
734
|
-
};
|
|
735
|
-
/**
|
|
736
|
-
* Which mark a session wears.
|
|
737
|
-
*
|
|
738
|
-
* The two first-party engines are named directly. A `provider` session is
|
|
739
|
-
* whatever the host wired up, so its *model* is the only thing that says whose
|
|
740
|
-
* it is — sniffed loosely on purpose (`gemini-2.5-pro`, `deepseek-chat`,
|
|
741
|
-
* `kimi-k2`), and falling through to no mark rather than guessing wrong.
|
|
742
|
-
*/
|
|
743
|
-
function engineMark(engine, model) {
|
|
744
|
-
if (engine === "claude") return "claude";
|
|
745
|
-
if (engine === "codex") return "codex";
|
|
746
|
-
const id = model?.toLowerCase() ?? "";
|
|
747
|
-
if (!id) return void 0;
|
|
748
|
-
if (id.includes("gemini")) return "gemini";
|
|
749
|
-
if (id.includes("deepseek")) return "deepseek";
|
|
750
|
-
if (id.includes("moonshot") || id.includes("kimi")) return "moonshot";
|
|
751
|
-
if (id.includes("claude")) return "claude";
|
|
752
|
-
if (id.startsWith("gpt") || id.startsWith("o1") || id.startsWith("o3") || id.includes("openai")) return "codex";
|
|
753
|
-
}
|
|
754
|
-
function EngineIcon({ engine, model, className }) {
|
|
755
|
-
const mark = PATHS[engineMark(engine, model) ?? ""];
|
|
756
|
-
if (!mark) return /* @__PURE__ */ jsx("span", {
|
|
757
|
-
"aria-hidden": true,
|
|
758
|
-
title: engine,
|
|
759
|
-
className: cn("shrink-0 text-fg-3", className),
|
|
760
|
-
children: "·"
|
|
761
|
-
});
|
|
762
|
-
return /* @__PURE__ */ jsxs("svg", {
|
|
763
|
-
viewBox: "0 0 24 24",
|
|
764
|
-
fill: "currentColor",
|
|
765
|
-
fillRule: "evenodd",
|
|
766
|
-
role: "img",
|
|
767
|
-
"aria-label": mark.title,
|
|
768
|
-
className: cn("size-3 shrink-0 text-fg-3", className),
|
|
769
|
-
children: [/* @__PURE__ */ jsx("title", { children: mark.title }), /* @__PURE__ */ jsx("path", { d: mark.d })]
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
//#endregion
|
|
773
|
-
export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, Band, Blank, Button, Card, CardContent, CardHeader, CardTitle, CodeBlock, Composer, ContextDialog, Conversation, ConversationContent, ConversationScrollButton, CopyAction, CopyButton, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, Empty, EmptyKey, EngineIcon, FileCard, HostFilesDialog, Ink, Input, Loader, McpDialog, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, ModelSelect, PERMISSION_MODES, PermissionModeSelect, PermissionPrompt, ProgressRing, PromptArea, PromptTokenText, QUESTION_BEHAVIORS, QuestionPrompt, Reasoning, Response, Row, STATUS_META, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, SessionEmptyState, SessionInfoDialog, SessionList, SessionListItem, SessionPanel, SessionStatusIcon, SkillsDialog, Spinner, Splitter, StatusBar, TerminalDiff, TerminalItemView, TerminalMarkdown, TerminalPermissionPrompt, TerminalQuestionPrompt, TerminalStatusLine, TerminalSurface, TerminalTranscript, Textarea, Tip, Toaster, ToolCallCard, TooltipContent, TooltipProvider, Transcript, TranscriptDensityProvider, TranscriptVariantProvider, UsageDialog, UsageMeters, WithActions, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, previewPatch, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, useAffordances, useMinuteClock, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
|
|
1228
|
+
export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, Band, Blank, Button, Card, CardContent, CardHeader, CardTitle, CodeBlock, Composer, ContextDialog, ContextRing, Conversation, ConversationContent, ConversationScrollButton, CopyAction, CopyButton, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, Empty, EmptyKey, EngineIcon, FileCard, HostFilesDialog, Ink, Input, Loader, McpDialog, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, ModelSelect, PERMISSION_MODES, PermissionModeSelect, PermissionPrompt, ProgressRing, ProjectIcon, PromptArea, PromptTokenText, QUESTION_BEHAVIORS, QuestionPrompt, Reasoning, Response, Row, STATUS_META, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, SessionEmptyState, SessionInfoDialog, SessionList, SessionListItem, SessionPanel, SessionStatusIcon, SkillsDialog, Spinner, Splitter, StatusBar, StepRow, StepToggle, SubagentStrip, TerminalDiff, TerminalItemView, TerminalMarkdown, TerminalPermissionPrompt, TerminalQuestionPrompt, TerminalStatusLine, TerminalSurface, TerminalTranscript, Textarea, Tip, Toaster, ToolCallCard, TooltipContent, TooltipProvider, Transcript, TranscriptDensityProvider, TranscriptVariantProvider, UsageDialog, UsageMeters, WithActions, badgeVariants, buttonVariants, cn, commandTrigger, copyText, engineMark, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, previewPatch, rateLimitWindowSeconds, rowShapeClass, runningSteps, segmentsToPlainText, sessionSteps, skillPrompt, toast, toolIcon, toolInputPreview, useAffordances, useMinuteClock, usePromptAreaState, useTranscriptDensity, useTranscriptVariant, vendorMarkClass, vendorTextClass };
|
|
774
1229
|
|
|
775
1230
|
//# sourceMappingURL=index.mjs.map
|