@workerdeck/ui 3.4.0 → 3.5.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/build/index.mjs CHANGED
@@ -2,11 +2,11 @@ import { $ as Composer, $t as Splitter, A as PermissionPrompt, An as badgeVarian
2
2
  import { C as rateLimitWindowSeconds, S as friendlyModel, _ as formatDuration, b as formatRelativeTime, c as tightestWindow, g as formatCountdown, h as formatCost, i as meterSeverity, m as formatBytes, o as modelLabel, p as formatAgoPrecise, r as meterColorClass, s as statusPresentation, t as contextSeverity, u as windowLabel, v as formatRateLimitWindow, w as toolInputPreview, x as formatTokens, y as formatRateLimitWindowLong } from "./status-kmsBhuFG.mjs";
3
3
  import { Fragment, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
- import { Anchor, ArrowRight, Atom, Beaker, BedDouble, BellRing, Bike, Binary, Blocks, Bot, Box, Brain, Briefcase, Brush, Bug, Building2, Cable, Camera, Car, Cat, Check, ChevronDown, Circle, CircleAlert, CircleSlash, CircuitBoard, Cloud, Code, Coffee, Cog, Compass, Container, Cpu, CreditCard, Database, Diamond, Dog, Eraser, Feather, Film, Filter, Flame, FlaskConical, Folder, FolderOpen, Gamepad2, Gauge, Gem, Ghost, Gift, GitBranch, Globe, GraduationCap, GripVertical, 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, Plus, 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";
5
+ import { Anchor, ArrowRight, Atom, Beaker, BedDouble, BellRing, Bike, Binary, Blocks, Bot, Box, Brain, Briefcase, Brush, Bug, Building2, Cable, Camera, Car, Cat, Check, ChevronDown, ChevronRight, Circle, CircleAlert, CircleSlash, CircuitBoard, Cloud, Code, Coffee, Cog, Compass, Container, Cpu, CreditCard, Database, Diamond, Dog, Eraser, Feather, Film, Filter, Flame, FlaskConical, Folder, FolderOpen, Gamepad2, Gauge, Gem, Ghost, Gift, GitBranch, Globe, GraduationCap, GripVertical, 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, Plus, 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";
6
6
  import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
7
7
  import { Popover as Popover$1 } from "@base-ui/react/popover";
8
8
  import { Toaster as Toaster$1, toast } from "sonner";
9
- import { STATE_LABELS, STATE_ORDER, adaptersOf, addCustomGroup, clearFilters, displayCustomized, displayedTasks, facetFilterCount, filterRows, groupRows, hasFacetFilter, isAgentRecord, moveCustomGroup, moveToCustomGroup, newCustomGroupId, projectLabel, projectName, projectSubpath, projectsOf, removeCustomGroup, renameCustomGroup, scopeActive, sessionKey, sessionLabel, subagentLabel, subsetSummary, taskSummary, visibleShells, visibleSubagents, visibleTasks } from "@workerdeck/protocol";
9
+ import { STATE_LABELS, STATE_ORDER, adaptersOf, addCustomGroup, clearFilters, displayCustomized, displayedTasks, facetFilterCount, filterRows, groupRows, hasFacetFilter, isAgentRecord, isTeamCollapsed, moveCustomGroup, moveToCustomGroup, newCustomGroupId, projectLabel, projectName, projectSubpath, projectsOf, removeCustomGroup, renameCustomGroup, scopeActive, sessionKey, sessionLabel, subagentLabel, subsetSummary, taskSummary, teamSummary, toggleTeamCollapsed, visibleShells, visibleSubagents, visibleTasks } from "@workerdeck/protocol";
10
10
  //#region src/components/ui/Card.tsx
11
11
  function Card({ className, ...props }) {
12
12
  return /* @__PURE__ */ jsx("div", {
@@ -377,6 +377,174 @@ function SessionList({ sessions, activeId, onSelect, onDelete, emptyText = "No s
377
377
  });
378
378
  }
379
379
  //#endregion
380
+ //#region src/components/agent/EngineIcon.tsx
381
+ const PATHS = {
382
+ claude: {
383
+ title: "Claude",
384
+ 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"
385
+ },
386
+ codex: {
387
+ title: "OpenAI",
388
+ 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"
389
+ },
390
+ gemini: {
391
+ title: "Gemini",
392
+ 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"
393
+ },
394
+ deepseek: {
395
+ title: "DeepSeek",
396
+ 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"
397
+ },
398
+ moonshot: {
399
+ title: "Moonshot",
400
+ 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"
401
+ }
402
+ };
403
+ function engineMark(engine, model) {
404
+ if (engine === "claude") return "claude";
405
+ if (engine === "codex") return "codex";
406
+ const id = model?.toLowerCase() ?? "";
407
+ if (!id) return;
408
+ if (id.includes("gemini")) return "gemini";
409
+ if (id.includes("deepseek")) return "deepseek";
410
+ if (id.includes("moonshot") || id.includes("kimi")) return "moonshot";
411
+ if (id.includes("claude")) return "claude";
412
+ if (id.startsWith("gpt") || id.startsWith("o1") || id.startsWith("o3") || id.includes("openai")) return "codex";
413
+ }
414
+ const VENDOR_MARK = {
415
+ claude: "text-vendor-claude",
416
+ codex: "text-vendor-openai"
417
+ };
418
+ const VENDOR_TEXT = { claude: "text-vendor-claude" };
419
+ function vendorMarkClass(engine, model) {
420
+ return VENDOR_MARK[engineMark(engine, model) ?? ""] ?? "text-fg-3";
421
+ }
422
+ function vendorTextClass(engine, model) {
423
+ return VENDOR_TEXT[engineMark(engine, model) ?? ""] ?? "text-fg-3";
424
+ }
425
+ function EngineIcon({ engine, model, className }) {
426
+ const mark = PATHS[engineMark(engine, model) ?? ""];
427
+ if (!mark) return /* @__PURE__ */ jsx("span", {
428
+ "aria-hidden": true,
429
+ title: engine,
430
+ className: cn("shrink-0 text-fg-3", className),
431
+ children: "·"
432
+ });
433
+ return /* @__PURE__ */ jsxs("svg", {
434
+ viewBox: "0 0 24 24",
435
+ fill: "currentColor",
436
+ fillRule: "evenodd",
437
+ role: "img",
438
+ "aria-label": mark.title,
439
+ className: cn("size-3 shrink-0 text-fg-3", className),
440
+ children: [/* @__PURE__ */ jsx("title", { children: mark.title }), /* @__PURE__ */ jsx("path", { d: mark.d })]
441
+ });
442
+ }
443
+ //#endregion
444
+ //#region src/components/agent/SessionStatusIcon.tsx
445
+ function SessionStatusIcon({ row, className }) {
446
+ const { info } = row;
447
+ const size = cn("size-4 shrink-0", className);
448
+ if (row.state === "attention") return /* @__PURE__ */ jsx(BellRing, { className: cn(size, "animate-pulse text-warning") });
449
+ if (row.state === "working") return /* @__PURE__ */ jsx(Spinner, { className: cn(size, "text-info") });
450
+ switch (info.status) {
451
+ case "failed": return /* @__PURE__ */ jsx(CircleAlert, { className: cn(size, "text-danger") });
452
+ case "closed": return /* @__PURE__ */ jsx(CircleSlash, { className: cn(size, "text-fg-4") });
453
+ case "parked": return /* @__PURE__ */ jsx(PauseCircle, { className: cn(size, "text-fg-3") });
454
+ default: return /* @__PURE__ */ jsx(Moon, { className: cn(size, "text-fg-4") });
455
+ }
456
+ }
457
+ //#endregion
458
+ //#region src/components/agent/AgentAvatar.tsx
459
+ function avatarOf(avatars, agent) {
460
+ return agent?.avatar === void 0 ? void 0 : avatars?.[agent.avatar];
461
+ }
462
+ function AgentAvatar({ row, image, size = 32, state, badge = true, className }) {
463
+ const { info } = row;
464
+ const shown = state ?? row.state;
465
+ const busy = shown === "working" && image?.busy && image.busy.durations.length > 1 ? image.busy : void 0;
466
+ const asleep = info.engineAsleep === true;
467
+ const engine = info.engine ?? "claude";
468
+ const badgeSize = size >= 28 ? 14 : 11;
469
+ return /* @__PURE__ */ jsxs("span", {
470
+ "data-slot": "agent-avatar",
471
+ className: cn("relative inline-flex shrink-0", className),
472
+ style: {
473
+ width: size,
474
+ height: size
475
+ },
476
+ title: info.agent?.name,
477
+ children: [busy ? /* @__PURE__ */ jsx("span", {
478
+ "aria-hidden": true,
479
+ className: "wd-avatar-strip size-full rounded-[4px]",
480
+ style: {
481
+ backgroundImage: `url(${busy.src})`,
482
+ backgroundSize: `${busy.durations.length * size}px ${size}px`,
483
+ "--wd-strip-end": `-${busy.durations.length * size}px`,
484
+ "--wd-strip-steps": busy.durations.length,
485
+ animationDuration: `${busy.durations.reduce((sum, ms) => sum + ms, 0)}ms`
486
+ }
487
+ }) : image ? /* @__PURE__ */ jsx("img", {
488
+ src: image.still,
489
+ alt: "",
490
+ draggable: false,
491
+ className: cn("size-full rounded-[4px] [image-rendering:pixelated]", asleep && "opacity-60 grayscale")
492
+ }) : /* @__PURE__ */ jsx("span", {
493
+ className: "flex size-full items-center justify-center rounded-[4px] border border-dashed border-border",
494
+ children: /* @__PURE__ */ jsx(EngineIcon, {
495
+ engine,
496
+ model: info.model,
497
+ className: cn("size-1/2", vendorMarkClass(engine, info.model))
498
+ })
499
+ }), badge && (shown !== "idle" || asleep) ? /* @__PURE__ */ jsx("span", {
500
+ className: "absolute -right-1 -bottom-1 flex items-center justify-center rounded-full bg-bg",
501
+ style: {
502
+ width: badgeSize,
503
+ height: badgeSize
504
+ },
505
+ children: /* @__PURE__ */ jsx(SessionStatusIcon, {
506
+ row: {
507
+ ...row,
508
+ state: shown
509
+ },
510
+ className: "size-full p-px"
511
+ })
512
+ }) : null]
513
+ });
514
+ }
515
+ function LeadChip({ className }) {
516
+ return /* @__PURE__ */ jsx("span", {
517
+ className: cn("shrink-0 rounded-[3px] border border-accent/50 px-1 text-[0.625rem] leading-3.5 font-medium tracking-wide text-accent", className),
518
+ children: "LEAD"
519
+ });
520
+ }
521
+ function AgentHeading({ row, image, conversation, className }) {
522
+ const agent = row.info.agent;
523
+ if (!agent) return null;
524
+ const n = conversation ?? agent.conversation ?? 1;
525
+ const detail = [agent.lead !== void 0 && agent.team ? `${agent.team} team` : void 0, `conversation ${n}`].filter(Boolean).join(" · ");
526
+ return /* @__PURE__ */ jsxs("span", {
527
+ "data-slot": "agent-heading",
528
+ className: cn("flex min-w-0 items-center gap-2", className),
529
+ children: [
530
+ /* @__PURE__ */ jsx(AgentAvatar, {
531
+ row,
532
+ image,
533
+ size: 24
534
+ }),
535
+ /* @__PURE__ */ jsx("span", {
536
+ className: "truncate text-body-sm font-medium text-fg-1",
537
+ children: agent.name
538
+ }),
539
+ agent.leads ? /* @__PURE__ */ jsx(LeadChip, {}) : null,
540
+ detail ? /* @__PURE__ */ jsx("span", {
541
+ className: "shrink-0 text-label text-fg-4",
542
+ children: detail
543
+ }) : null
544
+ ]
545
+ });
546
+ }
547
+ //#endregion
380
548
  //#region src/components/agent/ProjectIcon.tsx
381
549
  const GLYPHS = {
382
550
  anchor: Anchor,
@@ -827,84 +995,6 @@ function ContextRing({ usage, engine, size = 11, className }) {
827
995
  });
828
996
  }
829
997
  //#endregion
830
- //#region src/components/agent/EngineIcon.tsx
831
- const PATHS = {
832
- claude: {
833
- title: "Claude",
834
- 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"
835
- },
836
- codex: {
837
- title: "OpenAI",
838
- 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"
839
- },
840
- gemini: {
841
- title: "Gemini",
842
- 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"
843
- },
844
- deepseek: {
845
- title: "DeepSeek",
846
- 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"
847
- },
848
- moonshot: {
849
- title: "Moonshot",
850
- 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"
851
- }
852
- };
853
- function engineMark(engine, model) {
854
- if (engine === "claude") return "claude";
855
- if (engine === "codex") return "codex";
856
- const id = model?.toLowerCase() ?? "";
857
- if (!id) return;
858
- if (id.includes("gemini")) return "gemini";
859
- if (id.includes("deepseek")) return "deepseek";
860
- if (id.includes("moonshot") || id.includes("kimi")) return "moonshot";
861
- if (id.includes("claude")) return "claude";
862
- if (id.startsWith("gpt") || id.startsWith("o1") || id.startsWith("o3") || id.includes("openai")) return "codex";
863
- }
864
- const VENDOR_MARK = {
865
- claude: "text-vendor-claude",
866
- codex: "text-vendor-openai"
867
- };
868
- const VENDOR_TEXT = { claude: "text-vendor-claude" };
869
- function vendorMarkClass(engine, model) {
870
- return VENDOR_MARK[engineMark(engine, model) ?? ""] ?? "text-fg-3";
871
- }
872
- function vendorTextClass(engine, model) {
873
- return VENDOR_TEXT[engineMark(engine, model) ?? ""] ?? "text-fg-3";
874
- }
875
- function EngineIcon({ engine, model, className }) {
876
- const mark = PATHS[engineMark(engine, model) ?? ""];
877
- if (!mark) return /* @__PURE__ */ jsx("span", {
878
- "aria-hidden": true,
879
- title: engine,
880
- className: cn("shrink-0 text-fg-3", className),
881
- children: "·"
882
- });
883
- return /* @__PURE__ */ jsxs("svg", {
884
- viewBox: "0 0 24 24",
885
- fill: "currentColor",
886
- fillRule: "evenodd",
887
- role: "img",
888
- "aria-label": mark.title,
889
- className: cn("size-3 shrink-0 text-fg-3", className),
890
- children: [/* @__PURE__ */ jsx("title", { children: mark.title }), /* @__PURE__ */ jsx("path", { d: mark.d })]
891
- });
892
- }
893
- //#endregion
894
- //#region src/components/agent/SessionStatusIcon.tsx
895
- function SessionStatusIcon({ row, className }) {
896
- const { info } = row;
897
- const size = cn("size-4 shrink-0", className);
898
- if (row.state === "attention") return /* @__PURE__ */ jsx(BellRing, { className: cn(size, "animate-pulse text-warning") });
899
- if (row.state === "working") return /* @__PURE__ */ jsx(Spinner, { className: cn(size, "text-info") });
900
- switch (info.status) {
901
- case "failed": return /* @__PURE__ */ jsx(CircleAlert, { className: cn(size, "text-danger") });
902
- case "closed": return /* @__PURE__ */ jsx(CircleSlash, { className: cn(size, "text-fg-4") });
903
- case "parked": return /* @__PURE__ */ jsx(PauseCircle, { className: cn(size, "text-fg-3") });
904
- default: return /* @__PURE__ */ jsx(Moon, { className: cn(size, "text-fg-4") });
905
- }
906
- }
907
- //#endregion
908
998
  //#region src/components/agent/SessionSteps.tsx
909
999
  function sessionSteps(info, onSelect, show = "all", shells, tasks) {
910
1000
  const agents = visibleSubagents(info, show).filter(isAgentRecord).map((sub) => ({
@@ -1046,7 +1136,7 @@ const NO_MODIFIERS = {
1046
1136
  ctrl: false,
1047
1137
  alt: false
1048
1138
  };
1049
- function SessionItem({ row, active = false, activeStepKey, showGateway, showProject = true, projectIcons, subagents = "active", shells = "active", tasks = "active", onSelect, onSelectSubagent, onSelectTask, onStopTask, onSelectShell, onKillShell, onShellAgentWrite, now, onRename, renameOn = "doubleClick", editing, onEditingChange, actions, className }) {
1139
+ function SessionItem({ row, active = false, activeStepKey, showGateway, showProject = true, projectIcons, subagents = "active", shells = "active", tasks = "active", onSelect, onSelectSubagent, onSelectTask, onStopTask, onSelectShell, onKillShell, onShellAgentWrite, now, onRename, renameOn = "doubleClick", editing, onEditingChange, actions, avatars, variant = "card", badgeState, teamUnseen = 0, teamTray, tile = false, className }) {
1050
1140
  const { info } = row;
1051
1141
  const [ownEditing, setOwnEditing] = useState(false);
1052
1142
  const isEditing = editing ?? ownEditing;
@@ -1094,6 +1184,31 @@ function SessionItem({ row, active = false, activeStepKey, showGateway, showProj
1094
1184
  onStop: onStopTask
1095
1185
  });
1096
1186
  const holdsOpenStep = steps.some((s) => s.key === activeStepKey);
1187
+ const agent = info.agent;
1188
+ const label = agent ? agent.name : sessionLabel(info);
1189
+ const editable = agent ? agent.name : info.title ?? "";
1190
+ const time = formatRelativeTime(info.lastActivityAt ?? info.createdAt);
1191
+ const nameLabel = isEditing && onRename ? /* @__PURE__ */ jsx(NameEditor, {
1192
+ initial: editable,
1193
+ placeholder: agent ? "Agent name" : "Session name",
1194
+ onCommit: (title) => {
1195
+ setEditing(false);
1196
+ if (title !== editable && (title || !agent)) onRename(title);
1197
+ },
1198
+ onCancel: () => setEditing(false)
1199
+ }) : /* @__PURE__ */ jsx("span", {
1200
+ onDoubleClick: onRename && renameOn === "doubleClick" ? (e) => {
1201
+ e.stopPropagation();
1202
+ setEditing(true);
1203
+ } : void 0,
1204
+ className: "min-w-0 shrink truncate text-body-sm font-medium tracking-[-0.005em] text-fg-1",
1205
+ children: label
1206
+ });
1207
+ const unread = row.unseen > 0 ? /* @__PURE__ */ jsx("span", {
1208
+ title: `${row.unseen} new message${row.unseen === 1 ? "" : "s"}`,
1209
+ className: cn("flex h-4 min-w-6 shrink-0 items-center justify-center rounded-full px-2", "text-[0.75rem] leading-none tracking-[-0.005em] tabular-nums", row.state === "working" ? "bg-badge text-badge-fg" : "bg-accent text-accent-fg"),
1210
+ children: row.unseen
1211
+ }) : null;
1097
1212
  return /* @__PURE__ */ jsxs("div", {
1098
1213
  "data-slot": "session-item",
1099
1214
  "data-active": active || void 0,
@@ -1121,32 +1236,91 @@ function SessionItem({ row, active = false, activeStepKey, showGateway, showProj
1121
1236
  }
1122
1237
  },
1123
1238
  className: cn("group flex w-full cursor-pointer flex-col p-1 text-left outline-none", "rounded-[4px] transition-colors focus-visible:ring-2 focus-visible:ring-ring", holdsOpenStep ? "bg-row-selected-weak" : active ? "bg-row-selected" : "hover:bg-row-hover", className),
1124
- children: [/* @__PURE__ */ jsxs("div", {
1239
+ children: [agent && variant === "member" ? /* @__PURE__ */ jsxs("div", {
1240
+ className: cn("flex h-6 items-center gap-1.5 overflow-hidden py-0.5 pr-0.5 pl-1.5", info.engineAsleep && "opacity-60"),
1241
+ children: [
1242
+ /* @__PURE__ */ jsx(AgentAvatar, {
1243
+ row,
1244
+ image: avatarOf(avatars, agent),
1245
+ size: 22
1246
+ }),
1247
+ nameLabel,
1248
+ info.title ? /* @__PURE__ */ jsx("span", {
1249
+ className: "min-w-0 flex-1 truncate text-body-sm text-fg-3",
1250
+ children: info.title
1251
+ }) : /* @__PURE__ */ jsx("span", { className: "flex-1" }),
1252
+ unread,
1253
+ /* @__PURE__ */ jsx("span", {
1254
+ className: "shrink-0 text-body-sm text-fg-4",
1255
+ children: time
1256
+ }),
1257
+ actions
1258
+ ]
1259
+ }) : agent || tile ? /* @__PURE__ */ jsxs("div", {
1260
+ className: cn("flex items-center gap-2 py-0.5 pr-0.5 pl-1.5", info.engineAsleep && "opacity-60"),
1261
+ children: [/* @__PURE__ */ jsx(AgentAvatar, {
1262
+ row,
1263
+ image: avatarOf(avatars, agent),
1264
+ state: badgeState
1265
+ }), /* @__PURE__ */ jsxs("div", {
1266
+ className: "flex min-w-0 flex-1 flex-col gap-1",
1267
+ children: [/* @__PURE__ */ jsxs("div", {
1268
+ className: "flex h-5 items-center gap-1.5 overflow-hidden",
1269
+ children: [
1270
+ nameLabel,
1271
+ agent?.leads ? /* @__PURE__ */ jsx(LeadChip, {}) : null,
1272
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
1273
+ unread,
1274
+ teamUnseen > 0 ? /* @__PURE__ */ jsxs("span", {
1275
+ title: `${teamUnseen} new message${teamUnseen === 1 ? "" : "s"} in the team`,
1276
+ className: "flex h-4 shrink-0 items-center gap-0.5 rounded-full bg-accent px-1.5 text-[0.75rem] leading-none text-accent-fg tabular-nums",
1277
+ children: [/* @__PURE__ */ jsx(Users, { className: "size-3" }), teamUnseen]
1278
+ }) : null,
1279
+ teamTray,
1280
+ /* @__PURE__ */ jsx(ContextRing, {
1281
+ usage: info.contextUsage,
1282
+ engine,
1283
+ size: 16,
1284
+ className: "p-0.5"
1285
+ })
1286
+ ]
1287
+ }), /* @__PURE__ */ jsxs("div", {
1288
+ className: "flex h-5 items-center gap-1.5 overflow-hidden text-body-sm tracking-[-0.005em]",
1289
+ children: [
1290
+ agent ? /* @__PURE__ */ jsxs(Fragment$1, { children: [info.title ? /* @__PURE__ */ jsx("span", {
1291
+ className: "min-w-0 truncate text-fg-4",
1292
+ children: info.title
1293
+ }) : null, /* @__PURE__ */ jsxs("span", {
1294
+ className: "shrink-0 text-fg-4",
1295
+ children: [model ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
1296
+ info.title ? "· " : "",
1297
+ /* @__PURE__ */ jsx("span", {
1298
+ className: vendorTextClass(engine, info.model),
1299
+ children: model
1300
+ }),
1301
+ " · "
1302
+ ] }) : info.title ? "· " : null, time]
1303
+ })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
1304
+ className: "min-w-0 truncate text-fg-4",
1305
+ children: parts.map((part, i) => /* @__PURE__ */ jsxs(Fragment, { children: [i > 0 ? " · " : "", part] }, i))
1306
+ }), /* @__PURE__ */ jsxs("span", {
1307
+ className: "shrink-0 text-fg-4",
1308
+ children: [parts.length > 0 ? "· " : "", time]
1309
+ })] }),
1310
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
1311
+ actions
1312
+ ]
1313
+ })]
1314
+ })]
1315
+ }) : /* @__PURE__ */ jsxs("div", {
1125
1316
  className: cn("flex flex-col gap-1 py-0.5 pr-0.5 pl-1.5", info.engineAsleep && "opacity-60"),
1126
1317
  children: [/* @__PURE__ */ jsxs("div", {
1127
1318
  className: "flex h-5 items-center gap-1.5 overflow-hidden",
1128
1319
  children: [
1129
1320
  /* @__PURE__ */ jsx(Gutter, { children: /* @__PURE__ */ jsx(SessionStatusIcon, { row }) }),
1130
- isEditing && onRename ? /* @__PURE__ */ jsx(NameEditor, {
1131
- initial: info.title ?? "",
1132
- onCommit: (title) => {
1133
- setEditing(false);
1134
- if (title !== (info.title ?? "")) onRename(title);
1135
- },
1136
- onCancel: () => setEditing(false)
1137
- }) : /* @__PURE__ */ jsx("span", {
1138
- onDoubleClick: onRename && renameOn === "doubleClick" ? (e) => {
1139
- e.stopPropagation();
1140
- setEditing(true);
1141
- } : void 0,
1142
- className: "min-w-0 flex-1 truncate text-body-sm font-medium tracking-[-0.005em] text-fg-1",
1143
- children: sessionLabel(info)
1144
- }),
1145
- row.unseen > 0 ? /* @__PURE__ */ jsx("span", {
1146
- title: `${row.unseen} new message${row.unseen === 1 ? "" : "s"}`,
1147
- className: cn("flex h-4 min-w-6 shrink-0 items-center justify-center rounded-full px-2", "text-[0.75rem] leading-none tracking-[-0.005em] tabular-nums", row.state === "working" ? "bg-badge text-badge-fg" : "bg-accent text-accent-fg"),
1148
- children: row.unseen
1149
- }) : null,
1321
+ nameLabel,
1322
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
1323
+ unread,
1150
1324
  /* @__PURE__ */ jsx(ContextRing, {
1151
1325
  usage: info.contextUsage,
1152
1326
  engine,
@@ -1168,7 +1342,7 @@ function SessionItem({ row, active = false, activeStepKey, showGateway, showProj
1168
1342
  }),
1169
1343
  /* @__PURE__ */ jsxs("span", {
1170
1344
  className: "shrink-0 text-fg-4",
1171
- children: [parts.length > 0 ? "· " : "", formatRelativeTime(info.lastActivityAt ?? info.createdAt)]
1345
+ children: [parts.length > 0 ? "· " : "", time]
1172
1346
  }),
1173
1347
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
1174
1348
  actions
@@ -1190,7 +1364,7 @@ function Gutter({ children }) {
1190
1364
  children
1191
1365
  });
1192
1366
  }
1193
- function NameEditor({ initial, onCommit, onCancel }) {
1367
+ function NameEditor({ initial, placeholder, onCommit, onCancel }) {
1194
1368
  const [value, setValue] = useState(initial);
1195
1369
  const ref = useRef(null);
1196
1370
  useEffect(() => {
@@ -1209,8 +1383,8 @@ function NameEditor({ initial, onCommit, onCancel }) {
1209
1383
  ref,
1210
1384
  value,
1211
1385
  spellCheck: false,
1212
- placeholder: "Session name",
1213
- "aria-label": "Session name",
1386
+ placeholder,
1387
+ "aria-label": placeholder,
1214
1388
  onClick: (e) => e.stopPropagation(),
1215
1389
  onDoubleClick: (e) => e.stopPropagation(),
1216
1390
  onChange: (e) => setValue(e.target.value),
@@ -1226,10 +1400,56 @@ function NameEditor({ initial, onCommit, onCancel }) {
1226
1400
  });
1227
1401
  }
1228
1402
  //#endregion
1403
+ //#region src/lib/team-drop.ts
1404
+ function dropZone(offsetY, height) {
1405
+ if (height <= 0) return "join";
1406
+ const at = offsetY / height;
1407
+ return at < .25 ? "before" : at > .75 ? "after" : "join";
1408
+ }
1409
+ function teamDropRefusal(dragged, lead) {
1410
+ const mover = dragged.info.agent;
1411
+ const target = lead.info.agent;
1412
+ if (dragged.hostId !== lead.hostId) return "a team stays on one gateway";
1413
+ if (!target) return "only an agent can lead a team";
1414
+ if (mover?.id === target.id || dragged.info.id === lead.info.id) return "an agent cannot lead its own team";
1415
+ if (target.lead !== void 0) return `${target.name} is a member of a team; teams are one level deep`;
1416
+ if (mover?.leads) return `${mover.name} leads a team; teams are one level deep`;
1417
+ }
1418
+ function memberDrop(dragged, lead, member, zone) {
1419
+ const refusal = teamDropRefusal(dragged, lead);
1420
+ if (refusal) return refusal;
1421
+ const others = (lead.members ?? []).filter((row) => row.info.id !== dragged.info.id || row.hostId !== dragged.hostId);
1422
+ const at = others.findIndex((row) => row.info.id === member.info.id && row.hostId === member.hostId);
1423
+ return placeMember(dragged, lead, others, at < 0 ? others.length : zone === "before" ? at : at + 1);
1424
+ }
1425
+ function joinDrop(dragged, lead) {
1426
+ const refusal = teamDropRefusal(dragged, lead);
1427
+ if (refusal) return refusal;
1428
+ const others = (lead.members ?? []).filter((row) => row.info.id !== dragged.info.id || row.hostId !== dragged.hostId);
1429
+ return placeMember(dragged, lead, others, others.length);
1430
+ }
1431
+ function placeMember(dragged, lead, others, index) {
1432
+ const siblings = others.map((row, i) => ({
1433
+ row,
1434
+ order: i < index ? i : i + 1
1435
+ })).filter(({ row, order }) => row.info.agent?.order !== order);
1436
+ return {
1437
+ row: dragged,
1438
+ lead,
1439
+ order: index,
1440
+ ...siblings.length ? { siblings } : {}
1441
+ };
1442
+ }
1443
+ //#endregion
1229
1444
  //#region src/components/agent/SessionGroups.tsx
1230
- function useGroupDrag(groups, onChange) {
1445
+ const ERROR_MS = 5e3;
1446
+ function useGroupDrag(groups, onChange, options) {
1447
+ const { custom, team } = options;
1231
1448
  const [item, setItem] = useState();
1232
1449
  const [over, setOver] = useState();
1450
+ const [failure, setFailure] = useState();
1451
+ const failureTimer = useRef(void 0);
1452
+ useEffect(() => () => clearTimeout(failureTimer.current), []);
1233
1453
  const end = () => {
1234
1454
  setItem(void 0);
1235
1455
  setOver(void 0);
@@ -1240,13 +1460,74 @@ function useGroupDrag(groups, onChange) {
1240
1460
  e.dataTransfer.setData("text/plain", next.kind === "session" ? next.key : next.id);
1241
1461
  setItem(next);
1242
1462
  };
1243
- const accept = (e, spot) => {
1463
+ const accept = (e, next) => {
1244
1464
  e.preventDefault();
1245
1465
  e.stopPropagation();
1246
- e.dataTransfer.dropEffect = "move";
1247
- setOver(spot);
1466
+ e.dataTransfer.dropEffect = next.refusal ? "none" : "move";
1467
+ if (over?.spot !== next.spot || over.refusal !== next.refusal) setOver(next);
1248
1468
  };
1249
- function session(key, group) {
1469
+ const fail = (key, err) => {
1470
+ clearTimeout(failureTimer.current);
1471
+ setFailure({
1472
+ key,
1473
+ message: err instanceof Error ? err.message : String(err)
1474
+ });
1475
+ failureTimer.current = setTimeout(() => setFailure(void 0), ERROR_MS);
1476
+ };
1477
+ const move = (key, next) => () => {
1478
+ setFailure(void 0);
1479
+ Promise.resolve().then(() => team.onMove(next)).catch((err) => fail(key, err));
1480
+ };
1481
+ function land(e, key, group, place) {
1482
+ if (item?.kind !== "session" || item.key === key) return;
1483
+ const reorder = custom ? {
1484
+ spot: `row:${key}`,
1485
+ run: () => onChange(moveToCustomGroup(groups, item.key, group.custom, group.custom ? key : void 0))
1486
+ } : void 0;
1487
+ const dragged = team?.rowOf(item.key);
1488
+ if (!team || !dragged || !place) return reorder;
1489
+ const rect = e.currentTarget.getBoundingClientRect();
1490
+ const zone = dropZone(e.clientY - rect.top, rect.height);
1491
+ if (place.lead) {
1492
+ const result = memberDrop(dragged, place.lead, place.row, zone);
1493
+ return typeof result === "string" ? {
1494
+ spot: `refused:${key}`,
1495
+ refusal: result
1496
+ } : {
1497
+ spot: `${zone === "before" ? "before" : "after"}:${key}`,
1498
+ run: move(key, result)
1499
+ };
1500
+ }
1501
+ if (zone === "join") {
1502
+ const result = joinDrop(dragged, place.row);
1503
+ if (typeof result !== "string") return {
1504
+ spot: `join:${key}`,
1505
+ run: move(key, result)
1506
+ };
1507
+ return reorder ?? {
1508
+ spot: `refused:${key}`,
1509
+ refusal: result
1510
+ };
1511
+ }
1512
+ if (dragged.info.agent?.lead !== void 0) {
1513
+ const leave = move(key, {
1514
+ row: dragged,
1515
+ lead: null
1516
+ });
1517
+ return {
1518
+ spot: `${zone}:${key}`,
1519
+ run: () => {
1520
+ leave();
1521
+ reorder?.run();
1522
+ }
1523
+ };
1524
+ }
1525
+ return reorder ? {
1526
+ ...reorder,
1527
+ spot: `${zone}:${key}`
1528
+ } : void 0;
1529
+ }
1530
+ function session(key, group, place) {
1250
1531
  return {
1251
1532
  draggable: true,
1252
1533
  onDragStart: (e) => start(e, {
@@ -1255,26 +1536,37 @@ function useGroupDrag(groups, onChange) {
1255
1536
  }),
1256
1537
  onDragEnd: end,
1257
1538
  onDragOver: (e) => {
1258
- if (item?.kind === "session") accept(e, `row:${key}`);
1539
+ const landing = land(e, key, group, place);
1540
+ if (landing) accept(e, landing);
1259
1541
  },
1260
1542
  onDrop: (e) => {
1261
- if (item?.kind !== "session") return;
1543
+ const landing = land(e, key, group, place);
1544
+ if (!landing) return;
1262
1545
  e.preventDefault();
1263
1546
  e.stopPropagation();
1264
- if (item.key !== key) onChange(moveToCustomGroup(groups, item.key, group.custom, group.custom ? key : void 0));
1547
+ landing.run?.();
1265
1548
  end();
1266
1549
  }
1267
1550
  };
1268
1551
  }
1269
1552
  function container(group) {
1553
+ const leaving = () => {
1554
+ const dragged = item?.kind === "session" ? team?.rowOf(item.key) : void 0;
1555
+ return dragged?.info.agent?.lead !== void 0 ? dragged : void 0;
1556
+ };
1270
1557
  return {
1271
1558
  onDragOver: (e) => {
1272
- if (item) accept(e, `group:${group.key}`);
1559
+ if (item && (custom || leaving())) accept(e, { spot: `group:${group.key}` });
1273
1560
  },
1274
1561
  onDrop: (e) => {
1275
1562
  e.preventDefault();
1276
- if (item?.kind === "session") onChange(moveToCustomGroup(groups, item.key, group.custom));
1277
- else if (item?.kind === "group") onChange(moveCustomGroup(groups, item.id, group.custom));
1563
+ const member = leaving();
1564
+ if (member) move(sessionKey(member), {
1565
+ row: member,
1566
+ lead: null
1567
+ })();
1568
+ if (custom && item?.kind === "session") onChange(moveToCustomGroup(groups, item.key, group.custom));
1569
+ else if (custom && item?.kind === "group") onChange(moveCustomGroup(groups, item.id, group.custom));
1278
1570
  end();
1279
1571
  }
1280
1572
  };
@@ -1291,9 +1583,24 @@ function useGroupDrag(groups, onChange) {
1291
1583
  onDragEnd: end
1292
1584
  };
1293
1585
  }
1586
+ function cue(key) {
1587
+ if (failure?.key === key) return {
1588
+ zone: "refused",
1589
+ message: failure.message
1590
+ };
1591
+ const spot = over?.spot;
1592
+ if (!spot || spot.slice(spot.indexOf(":") + 1) !== key) return {};
1593
+ const kind = spot.slice(0, spot.indexOf(":"));
1594
+ if (kind === "refused") return {
1595
+ zone: "refused",
1596
+ message: over?.refusal
1597
+ };
1598
+ return kind === "row" || kind === "before" ? { zone: "before" } : kind === "after" ? { zone: "after" } : kind === "join" ? { zone: "join" } : {};
1599
+ }
1294
1600
  return {
1295
1601
  dragging: item !== void 0,
1296
- isOver: (spot) => over === spot,
1602
+ isOver: (spot) => over?.spot === spot,
1603
+ cue,
1297
1604
  session,
1298
1605
  container,
1299
1606
  header,
@@ -1408,7 +1715,7 @@ function NewGroupButton({ onClick }) {
1408
1715
  function rowShapeClass(active) {
1409
1716
  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");
1410
1717
  }
1411
- function SessionBrowser({ rows, config, onConfigChange, scope, activeId, activeSubagentId, activeShellId, now, isActive = (row) => row.info.id === activeId, rowActions, gatewayCount, showSubset = true, onSelect, onDelete, onRename, onClearContext, onSleep, onSelectSubagent, onSelectTask, onStopTask, onSelectShell, onKillShell, onShellAgentWrite, onCreateInGroup, emptyState, showControls = true, showSearch = showControls, autoFocusSearch, projectIcons, className }) {
1718
+ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, activeSubagentId, activeShellId, now, isActive = (row) => row.info.id === activeId, rowActions, gatewayCount, showSubset = true, onSelect, onDelete, onRename, onRenameAgent, onClearContext, onSleep, onSelectSubagent, onSelectTask, onStopTask, onSelectShell, onKillShell, onShellAgentWrite, avatars, onTeamMove, onCreateInGroup, emptyState, showControls = true, showSearch = showControls, autoFocusSearch, projectIcons, className }) {
1412
1719
  const rowGateways = useMemo(() => new Set(rows.map((row) => row.hostId)).size, [rows]);
1413
1720
  const gateways = gatewayCount ?? rowGateways;
1414
1721
  const visible = useMemo(() => filterRows(rows, config, scope), [
@@ -1416,19 +1723,32 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, activeS
1416
1723
  config,
1417
1724
  scope
1418
1725
  ]);
1419
- const groups = useMemo(() => groupRows(visible, config, { gatewayCount: gateways }), [
1726
+ const groups = useMemo(() => groupRows(visible, config, {
1727
+ gatewayCount: gateways,
1728
+ all: rows
1729
+ }), [
1420
1730
  visible,
1421
1731
  config,
1422
- gateways
1732
+ gateways,
1733
+ rows
1423
1734
  ]);
1424
1735
  const subset = subsetSummary(config, scope, visible.length, rows.length);
1736
+ const tiles = useMemo(() => rows.some((row) => row.info.agent !== void 0), [rows]);
1425
1737
  const custom = config.groupBy === "custom";
1426
1738
  const [editingGroup, setEditingGroup] = useState();
1427
1739
  const set = (patch) => onConfigChange({
1428
1740
  ...config,
1429
1741
  ...patch
1430
1742
  });
1431
- const drag = useGroupDrag(config.customGroups ?? [], (customGroups) => set({ customGroups }));
1743
+ const byKey = useMemo(() => new Map(rows.map((row) => [sessionKey(row), row])), [rows]);
1744
+ const drag = useGroupDrag(config.customGroups ?? [], (customGroups) => set({ customGroups }), {
1745
+ custom,
1746
+ team: onTeamMove ? {
1747
+ rowOf: (key) => byKey.get(key),
1748
+ onMove: onTeamMove
1749
+ } : void 0
1750
+ });
1751
+ const draggable = custom || onTeamMove !== void 0;
1432
1752
  const heading = (group) => {
1433
1753
  if (custom) return /* @__PURE__ */ jsx(CustomGroupHeader, {
1434
1754
  group,
@@ -1438,6 +1758,19 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, activeS
1438
1758
  onRemove: () => group.custom && drag.remove(group.custom),
1439
1759
  dragProps: drag.header(group)
1440
1760
  });
1761
+ if (group.earlier) return /* @__PURE__ */ jsxs("button", {
1762
+ type: "button",
1763
+ "aria-expanded": config.earlierOpen === true,
1764
+ onClick: () => set({ earlierOpen: !config.earlierOpen }),
1765
+ className: "flex items-center gap-1 px-2 text-left text-label text-fg-4 hover:text-fg-2",
1766
+ children: [
1767
+ config.earlierOpen ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5" }),
1768
+ "Earlier · ",
1769
+ group.rows.length,
1770
+ " one-off session",
1771
+ group.rows.length === 1 ? "" : "s"
1772
+ ]
1773
+ });
1441
1774
  if (config.groupBy === "none" || !group.label) return null;
1442
1775
  const project = config.groupBy === "project";
1443
1776
  const target = project && group.hostId ? {
@@ -1523,41 +1856,65 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, activeS
1523
1856
  }) : /* @__PURE__ */ jsxs("div", {
1524
1857
  className: "flex flex-col gap-4 px-1",
1525
1858
  children: [groups.map((group) => /* @__PURE__ */ jsxs("div", {
1526
- ...custom ? drag.container(group) : {},
1527
- className: cn("flex flex-col gap-1 rounded-md", custom && drag.isOver(`group:${group.key}`) && "bg-row-hover/50"),
1859
+ ...draggable ? drag.container(group) : {},
1860
+ className: cn("flex flex-col gap-1 rounded-md", draggable && drag.isOver(`group:${group.key}`) && "bg-row-hover/50"),
1528
1861
  children: [
1529
1862
  heading(group),
1530
1863
  custom && group.custom !== void 0 && group.rows.length === 0 ? /* @__PURE__ */ jsx("div", {
1531
1864
  className: "mx-1 rounded-md border border-dashed border-border px-2 py-2 text-center text-label text-fg-4",
1532
1865
  children: "Drag sessions here"
1533
1866
  }) : null,
1534
- group.rows.map((row) => /* @__PURE__ */ jsx(SessionRowItem, {
1535
- dragProps: custom ? drag.session(sessionKey(row), group) : void 0,
1536
- dropTarget: custom && drag.isOver(`row:${sessionKey(row)}`),
1537
- row,
1538
- active: isActive(row),
1539
- activeSubagentId,
1540
- activeShellId,
1541
- actions: rowActions?.(row),
1542
- now,
1543
- showGateway: gateways > 1 && config.groupBy !== "project",
1544
- showProject: config.groupBy !== "project",
1545
- subagents: config.subagents,
1546
- shells: config.shells,
1547
- tasks: config.tasks,
1548
- projectIcons,
1549
- onSelect,
1550
- onDelete,
1551
- onRename,
1552
- onClearContext,
1553
- onSleep,
1554
- onSelectSubagent,
1555
- onSelectTask,
1556
- onStopTask,
1557
- onSelectShell,
1558
- onKillShell,
1559
- onShellAgentWrite
1560
- }, sessionKey(row)))
1867
+ group.earlier && !config.earlierOpen ? null : group.rows.map((row) => {
1868
+ const item = (member, variant, extra = {}) => /* @__PURE__ */ jsx(SessionRowItem, {
1869
+ dragProps: onTeamMove || custom && variant === "card" ? drag.session(sessionKey(member), group, variant === "member" ? {
1870
+ row: member,
1871
+ lead: row
1872
+ } : { row }) : void 0,
1873
+ dropCue: draggable ? drag.cue(sessionKey(member)) : void 0,
1874
+ row: member,
1875
+ variant,
1876
+ active: isActive(member),
1877
+ activeSubagentId,
1878
+ activeShellId,
1879
+ actions: rowActions?.(member),
1880
+ now,
1881
+ showGateway: gateways > 1 && config.groupBy !== "project",
1882
+ showProject: config.groupBy !== "project",
1883
+ subagents: config.subagents,
1884
+ shells: config.shells,
1885
+ tasks: config.tasks,
1886
+ projectIcons,
1887
+ avatars,
1888
+ tile: tiles,
1889
+ onSelect,
1890
+ onDelete,
1891
+ onRename: member.info.agent ? onRenameAgent : onRename,
1892
+ onClearContext,
1893
+ onSleep,
1894
+ onSelectSubagent,
1895
+ onSelectTask,
1896
+ onStopTask,
1897
+ onSelectShell,
1898
+ onKillShell,
1899
+ onShellAgentWrite,
1900
+ ...extra
1901
+ }, sessionKey(member));
1902
+ if (!row.members?.length) return item(row, "card", { className: row.context ? "opacity-50" : void 0 });
1903
+ const collapsed = isTeamCollapsed(config, row);
1904
+ return /* @__PURE__ */ jsx(TeamBlock, {
1905
+ lead: row,
1906
+ collapsed,
1907
+ avatars,
1908
+ onToggle: () => onConfigChange(toggleTeamCollapsed(config, row)),
1909
+ renderLead: (summary, tray) => item(row, "card", {
1910
+ className: row.context ? "opacity-50" : void 0,
1911
+ badgeState: collapsed ? row.teamState : void 0,
1912
+ teamUnseen: collapsed ? summary.unseen : 0,
1913
+ teamTray: tray
1914
+ }),
1915
+ renderMember: (member) => item(member, "member")
1916
+ }, sessionKey(row));
1917
+ })
1561
1918
  ]
1562
1919
  }, group.key)), custom ? /* @__PURE__ */ jsx(NewGroupButton, { onClick: () => setEditingGroup(drag.create()) }) : null]
1563
1920
  })
@@ -1568,11 +1925,18 @@ function iconSrcOf(row, icons) {
1568
1925
  const icon = row?.info.project?.icon;
1569
1926
  return icon?.type === "image" ? icons?.[icon.hash] : void 0;
1570
1927
  }
1571
- function SessionRowItem({ row, dragProps, dropTarget, active, actions, activeSubagentId, activeShellId, now, showGateway, showProject = true, subagents, shells, tasks, projectIcons, onSelect, onDelete, onRename, onClearContext, onSleep, onSelectSubagent, onSelectTask, onStopTask, onSelectShell, onKillShell, onShellAgentWrite }) {
1928
+ function SessionRowItem({ row, variant, avatars, badgeState, teamUnseen, teamTray, tile, className, dragProps, dropCue, active, actions, activeSubagentId, activeShellId, now, showGateway, showProject = true, subagents, shells, tasks, projectIcons, onSelect, onDelete, onRename, onClearContext, onSleep, onSelectSubagent, onSelectTask, onStopTask, onSelectShell, onKillShell, onShellAgentWrite }) {
1572
1929
  const { info } = row;
1573
1930
  const [editing, setEditing] = useState(false);
1574
1931
  const item = /* @__PURE__ */ jsx(SessionItem, {
1575
1932
  row,
1933
+ variant,
1934
+ avatars,
1935
+ badgeState,
1936
+ teamUnseen,
1937
+ teamTray,
1938
+ tile,
1939
+ className,
1576
1940
  active: active === true,
1577
1941
  activeStepKey: active ? activeShellId ?? activeSubagentId : void 0,
1578
1942
  now,
@@ -1595,7 +1959,7 @@ function SessionRowItem({ row, dragProps, dropTarget, active, actions, activeSub
1595
1959
  onEditingChange: actions === void 0 ? setEditing : void 0,
1596
1960
  actions: actions ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
1597
1961
  onRename && !editing ? /* @__PURE__ */ jsx(RowAction, {
1598
- label: "Rename session",
1962
+ label: info.agent ? "Rename agent" : "Rename session",
1599
1963
  onClick: () => setEditing(true),
1600
1964
  children: /* @__PURE__ */ jsx(Pencil, { className: "size-3 text-fg-3" })
1601
1965
  }) : null,
@@ -1619,10 +1983,81 @@ function SessionRowItem({ row, dragProps, dropTarget, active, actions, activeSub
1619
1983
  ] })
1620
1984
  });
1621
1985
  if (!dragProps) return item;
1622
- return /* @__PURE__ */ jsx("div", {
1986
+ const zone = dropCue?.zone;
1987
+ return /* @__PURE__ */ jsxs("div", {
1623
1988
  ...dragProps,
1624
- className: cn("rounded-md", dropTarget && "shadow-[inset_0_2px_0_0_var(--color-accent)]"),
1625
- children: item
1989
+ title: zone === "refused" ? dropCue?.message : void 0,
1990
+ className: cn("rounded-md", zone === "before" && "shadow-[inset_0_2px_0_0_var(--color-accent)]", zone === "after" && "shadow-[inset_0_-2px_0_0_var(--color-accent)]", zone === "join" && "bg-accent/10 ring-1 ring-accent", zone === "refused" && "ring-1 ring-danger/60"),
1991
+ children: [item, zone === "refused" && dropCue?.message ? /* @__PURE__ */ jsx("div", {
1992
+ role: "status",
1993
+ className: "px-3 pb-1 text-label text-danger",
1994
+ children: dropCue.message
1995
+ }) : null]
1996
+ });
1997
+ }
1998
+ const TRAY_MAX = 4;
1999
+ function TeamBlock({ lead, collapsed, avatars, onToggle, renderLead, renderMember }) {
2000
+ const members = lead.members ?? [];
2001
+ const summary = teamSummary(lead);
2002
+ if (collapsed) {
2003
+ const surfaced = members.filter((member) => member.state === "attention");
2004
+ const counts = [
2005
+ `${summary.members} member${summary.members === 1 ? "" : "s"}`,
2006
+ summary.working ? `${summary.working} working` : void 0,
2007
+ summary.attention ? `${summary.attention} need${summary.attention === 1 ? "s" : ""} you` : void 0
2008
+ ].filter(Boolean);
2009
+ const hidden = members.length - TRAY_MAX;
2010
+ const tray = /* @__PURE__ */ jsxs("button", {
2011
+ type: "button",
2012
+ "aria-expanded": false,
2013
+ "aria-label": `Expand ${lead.info.agent?.name ?? "team"}: ${counts.join(", ")}`,
2014
+ title: counts.join(" · "),
2015
+ onClick: (e) => {
2016
+ e.stopPropagation();
2017
+ onToggle();
2018
+ },
2019
+ className: "flex shrink-0 items-center gap-1 rounded-[4px] px-0.5 hover:bg-row-hover",
2020
+ children: [members.slice(0, hidden > 0 ? 3 : TRAY_MAX).map((member) => /* @__PURE__ */ jsx(AgentAvatar, {
2021
+ row: member,
2022
+ image: avatarOf(avatars, member.info.agent),
2023
+ size: 16,
2024
+ className: "rounded-[3px]"
2025
+ }, sessionKey(member))), hidden > 0 ? /* @__PURE__ */ jsxs("span", {
2026
+ className: "text-label text-fg-4 tabular-nums",
2027
+ children: ["+", hidden + 1]
2028
+ }) : null]
2029
+ });
2030
+ return /* @__PURE__ */ jsxs("div", {
2031
+ "data-slot": "team",
2032
+ "data-collapsed": true,
2033
+ className: "flex flex-col",
2034
+ children: [renderLead(summary, tray), surfaced.length ? /* @__PURE__ */ jsx("div", {
2035
+ className: "ml-3 flex flex-col",
2036
+ children: surfaced.map(renderMember)
2037
+ }) : null]
2038
+ });
2039
+ }
2040
+ return /* @__PURE__ */ jsxs("div", {
2041
+ "data-slot": "team",
2042
+ className: "flex flex-col",
2043
+ children: [renderLead(summary), /* @__PURE__ */ jsxs("div", {
2044
+ className: "relative ml-3.5 flex flex-col pl-1",
2045
+ children: [
2046
+ /* @__PURE__ */ jsx("span", {
2047
+ "aria-hidden": true,
2048
+ className: "absolute top-0 bottom-3 left-0 w-px bg-border"
2049
+ }),
2050
+ /* @__PURE__ */ jsx("button", {
2051
+ type: "button",
2052
+ "aria-expanded": true,
2053
+ "aria-label": `Collapse ${lead.info.agent?.name ?? "team"}`,
2054
+ onClick: onToggle,
2055
+ className: "absolute -top-1 -left-[7px] flex size-3.5 items-center justify-center rounded-full border border-border bg-bg text-fg-4 hover:text-fg-1",
2056
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-2.5" })
2057
+ }),
2058
+ members.map(renderMember)
2059
+ ]
2060
+ })]
1626
2061
  });
1627
2062
  }
1628
2063
  function RowAction({ label, title, onClick, children }) {
@@ -1744,6 +2179,6 @@ function SubagentToggle({ value, onChange, className }) {
1744
2179
  })] });
1745
2180
  }
1746
2181
  //#endregion
1747
- export { AgentWriteIcon, AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, Band, Blank, Button, Card, CardContent, CardHeader, CardTitle, CodeBlock, Composer, ContextDialog, ContextPanel, ContextRing, Conversation, ConversationContent, ConversationScrollButton, CopyAction, CopyButton, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, EffortSelect, Empty, EmptyKey, EngineIcon, FileCard, FileLinkProvider, HostFilesDialog, ImageViewer, ImageViewerProvider, Ink, Input, Loader, McpDialog, McpPanel, McpPanelActions, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, ModelSelect, OptionSelect, PERMISSION_MODES, PermissionModeSelect, PermissionPrompt, Popover, PopoverContent, PopoverTrigger, ProgressRing, ProjectIcon, PromptArea, PromptTokenText, QUESTION_BEHAVIORS, QuestionPrompt, Reasoning, Response, Row, SHELL_AGENT_WRITE_NOTE, SHELL_GLYPH, SHELL_KILL_GLYPH, STATUS_META, STEP_DISPLAY_OPTIONS, SUBAGENT_DISPLAY_META, SUBAGENT_DISPLAY_ORDER, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, SessionEmptyState, SessionFilters, SessionFiltersButton, SessionInfoDialog, SessionInfoPanel, SessionItem, SessionList, SessionListItem, SessionNamesProvider, SessionPanel, SessionSearch, SessionStatusIcon, ShellActionsProvider, ShellStrip, SkillNamesProvider, SkillsDialog, Spinner, Splitter, StatusBar, StepDisplayControl, StepRow, SubagentDisplayIcon, SubagentStrip, SubagentToggle, TaskList, TasksDialog, TerminalDiff, TerminalItemView, TerminalMarkdown, TerminalPermissionPrompt, TerminalQuestionPrompt, TerminalStatusLine, TerminalSurface, TerminalTranscript, Textarea, Tip, Toaster, ToolCallCard, ToolTitleProvider, TooltipContent, TooltipProvider, Transcript, TranscriptVariantProvider, UsageDialog, UsageMeters, ViewableImage, WithActions, badgeVariants, buttonVariants, cn, commandTrigger, copyText, effortChoices, engineMark, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, launchTrigger, matchClientCommand, matchPath, mentionTrigger, mergeComposerRows, parseFileLink, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, previewPatch, rankComposerRows, rankPeerSessions, rateLimitWindowSeconds, resolveAgainstCwd, rowShapeClass, segmentsToPlainText, sessionSteps, shellAgentWriteLabel, shellGrantable, shellInfoFailed, shellInfoLabel, shellInfoStatusText, shellTitle, skillPrompt, toast, toolIcon, toolInputPreview, useAffordances, useFileLinks, useMcpPanel, useMinuteClock, useOpenImage, usePathLinks, usePromptAreaState, useShellActions, useShellFrame, useToolTitle, useTranscriptVariant, vendorMarkClass, vendorTextClass };
2182
+ export { AgentAvatar, AgentHeading, AgentWriteIcon, AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, Band, Blank, Button, Card, CardContent, CardHeader, CardTitle, CodeBlock, Composer, ContextDialog, ContextPanel, ContextRing, Conversation, ConversationContent, ConversationScrollButton, CopyAction, CopyButton, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, EffortSelect, Empty, EmptyKey, EngineIcon, FileCard, FileLinkProvider, HostFilesDialog, ImageViewer, ImageViewerProvider, Ink, Input, LeadChip, Loader, McpDialog, McpPanel, McpPanelActions, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, ModelSelect, OptionSelect, PERMISSION_MODES, PermissionModeSelect, PermissionPrompt, Popover, PopoverContent, PopoverTrigger, ProgressRing, ProjectIcon, PromptArea, PromptTokenText, QUESTION_BEHAVIORS, QuestionPrompt, Reasoning, Response, Row, SHELL_AGENT_WRITE_NOTE, SHELL_GLYPH, SHELL_KILL_GLYPH, STATUS_META, STEP_DISPLAY_OPTIONS, SUBAGENT_DISPLAY_META, SUBAGENT_DISPLAY_ORDER, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, SessionEmptyState, SessionFilters, SessionFiltersButton, SessionInfoDialog, SessionInfoPanel, SessionItem, SessionList, SessionListItem, SessionNamesProvider, SessionPanel, SessionSearch, SessionStatusIcon, ShellActionsProvider, ShellStrip, SkillNamesProvider, SkillsDialog, Spinner, Splitter, StatusBar, StepDisplayControl, StepRow, SubagentDisplayIcon, SubagentStrip, SubagentToggle, TaskList, TasksDialog, TerminalDiff, TerminalItemView, TerminalMarkdown, TerminalPermissionPrompt, TerminalQuestionPrompt, TerminalStatusLine, TerminalSurface, TerminalTranscript, Textarea, Tip, Toaster, ToolCallCard, ToolTitleProvider, TooltipContent, TooltipProvider, Transcript, TranscriptVariantProvider, UsageDialog, UsageMeters, ViewableImage, WithActions, avatarOf, badgeVariants, buttonVariants, cn, commandTrigger, copyText, effortChoices, engineMark, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, launchTrigger, matchClientCommand, matchPath, mentionTrigger, mergeComposerRows, parseFileLink, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, previewPatch, rankComposerRows, rankPeerSessions, rateLimitWindowSeconds, resolveAgainstCwd, rowShapeClass, segmentsToPlainText, sessionSteps, shellAgentWriteLabel, shellGrantable, shellInfoFailed, shellInfoLabel, shellInfoStatusText, shellTitle, skillPrompt, teamDropRefusal, toast, toolIcon, toolInputPreview, useAffordances, useFileLinks, useMcpPanel, useMinuteClock, useOpenImage, usePathLinks, usePromptAreaState, useShellActions, useShellFrame, useToolTitle, useTranscriptVariant, vendorMarkClass, vendorTextClass };
1748
2183
 
1749
2184
  //# sourceMappingURL=index.mjs.map