@invergent/agent-chat-react 2.0.2 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { cn } from './chunk-QSC4UIVT.js';
2
- import { createContext, memo, useRef, useEffect, useCallback, useMemo, useState, lazy, useContext, Suspense, Children } from 'react';
2
+ import { createContext, memo, useRef, useEffect, useCallback, useMemo, useState, lazy, useContext, Fragment as Fragment$1, Suspense, Children } from 'react';
3
3
  import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, File as File$1, FileImage, FileAudio, FileVideo, FileText, FileCode, FileArchive, FileSpreadsheet, InboxIcon, Loader2, AlertCircle, Pause, Play, Ban, TargetIcon, ChevronRightIcon, CalendarClockIcon, UsersIcon, MessageSquareIcon, ZapIcon, Maximize2Icon, FolderOpenIcon, Loader2Icon, UploadIcon, RefreshCwIcon, AlertCircleIcon, ExternalLinkIcon, ClipboardCheckIcon, ShieldAlertIcon, TimerIcon, CircleDotIcon, XIcon, Trash2Icon, SquareIcon, ArrowDownIcon, RotateCcwIcon, MousePointer2Icon, DownloadIcon, TrashIcon, ImageIcon, FileTextIcon, CheckIcon, CopyIcon, TerminalIcon, SparklesIcon, ClockIcon, PlusIcon, CloudIcon, HardDriveIcon, PaperclipIcon, GlobeIcon, FolderIcon, FileIcon, ChevronLeftIcon, MinusIcon, SearchIcon, GitBranchIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, EyeIcon, ListTodoIcon, ArrowUpIcon, XCircleIcon, CheckCircle2Icon, Code, CircleCheckIcon, CircleXIcon, SkullIcon, CheckCircleIcon, CircleIcon } from 'lucide-react';
4
4
  import { cva } from 'class-variance-authority';
5
- import { Collapsible as Collapsible$1, Slot, Tooltip as Tooltip$1, Separator as Separator$1, Dialog as Dialog$1, ScrollArea as ScrollArea$1, Popover as Popover$1, Progress as Progress$1, Tabs as Tabs$1 } from 'radix-ui';
5
+ import { Collapsible as Collapsible$1, Slot, Tooltip as Tooltip$1, Progress as Progress$1, Tabs as Tabs$1, Dialog as Dialog$1, ScrollArea as ScrollArea$1, Popover as Popover$1 } from 'radix-ui';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { StickToBottom, useStickToBottomContext } from 'use-stick-to-bottom';
8
8
  import { cjk } from '@streamdown/cjk';
@@ -597,26 +597,6 @@ var ConversationScrollButton = ({
597
597
  }
598
598
  );
599
599
  };
600
- function Separator({
601
- className,
602
- orientation = "horizontal",
603
- decorative = true,
604
- ...props
605
- }) {
606
- return /* @__PURE__ */ jsx(
607
- Separator$1.Root,
608
- {
609
- "data-slot": "separator",
610
- decorative,
611
- orientation,
612
- className: cn(
613
- "shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
614
- className
615
- ),
616
- ...props
617
- }
618
- );
619
- }
620
600
  var Message = ({ className, from, ...props }) => /* @__PURE__ */ jsx(
621
601
  "div",
622
602
  {
@@ -10461,42 +10441,6 @@ function Card({
10461
10441
  }
10462
10442
  );
10463
10443
  }
10464
- function CardHeader({ className, ...props }) {
10465
- return /* @__PURE__ */ jsx(
10466
- "div",
10467
- {
10468
- "data-slot": "card-header",
10469
- className: cn(
10470
- "group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-none px-8 group-data-[size=sm]/card:px-5 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-8 group-data-[size=sm]/card:[.border-b]:pb-5",
10471
- className
10472
- ),
10473
- ...props
10474
- }
10475
- );
10476
- }
10477
- function CardTitle({ className, ...props }) {
10478
- return /* @__PURE__ */ jsx(
10479
- "div",
10480
- {
10481
- "data-slot": "card-title",
10482
- className: cn(
10483
- "font-heading text-lg font-semibold tracking-wider uppercase",
10484
- className
10485
- ),
10486
- ...props
10487
- }
10488
- );
10489
- }
10490
- function CardDescription({ className, ...props }) {
10491
- return /* @__PURE__ */ jsx(
10492
- "div",
10493
- {
10494
- "data-slot": "card-description",
10495
- className: cn("text-sm leading-relaxed text-muted-foreground", className),
10496
- ...props
10497
- }
10498
- );
10499
- }
10500
10444
  function CardContent({ className, ...props }) {
10501
10445
  return /* @__PURE__ */ jsx(
10502
10446
  "div",
@@ -10564,6 +10508,97 @@ var MISSION_WORKER_KIND_TOOLTIP = {
10564
10508
  worker: "Async one-shot session spawned by spawn_worker. Durable session, no retry/DAG.",
10565
10509
  delegation: "Sync fork-join child spawned by delegate_task. Coordinator's wake blocked until it finished."
10566
10510
  };
10511
+ function CountBadge({ n }) {
10512
+ if (n === 0) return null;
10513
+ return /* @__PURE__ */ jsx("span", { className: "ml-1 rounded bg-muted px-1 py-px text-[9px] text-muted-foreground/70", children: n });
10514
+ }
10515
+ function firstLine3(text, max = 140) {
10516
+ const trimmed = text.replace(/\s+/g, " ").trim();
10517
+ if (trimmed.length <= max) return trimmed;
10518
+ return `${trimmed.slice(0, max).trimEnd()}\u2026`;
10519
+ }
10520
+ var ACTIVITY_KIND_TONE = {
10521
+ "mission.defined": "bg-primary/10 text-primary border-primary/30",
10522
+ "mission.paused": "bg-amber-500/10 text-amber-600 border-amber-500/30",
10523
+ "mission.cancelled": "bg-destructive/10 text-destructive border-destructive/30",
10524
+ "task.spawned": "bg-foreground/5 text-foreground/80 border-foreground/20",
10525
+ "task.completed": "bg-emerald-500/10 text-emerald-600 border-emerald-500/30",
10526
+ "task.failed": "bg-destructive/10 text-destructive border-destructive/30",
10527
+ "task.cancelled": "bg-muted text-muted-foreground border-border",
10528
+ "worker.latest": "bg-foreground/5 text-foreground/70 border-foreground/15",
10529
+ "evaluator.verdict": "bg-primary/10 text-primary border-primary/30"
10530
+ };
10531
+ function buildMissionActivity(mission, tasks, workers) {
10532
+ const entries = [];
10533
+ entries.push({
10534
+ at: mission.createdAt,
10535
+ kind: "mission.defined",
10536
+ label: "Mission defined",
10537
+ detail: mission.description
10538
+ });
10539
+ if (mission.status === "paused" && mission.pausedReason) {
10540
+ entries.push({
10541
+ at: mission.updatedAt,
10542
+ kind: "mission.paused",
10543
+ label: "Paused",
10544
+ detail: mission.pausedReason
10545
+ });
10546
+ }
10547
+ if (mission.status === "cancelled" && mission.cancelledReason) {
10548
+ entries.push({
10549
+ at: mission.updatedAt,
10550
+ kind: "mission.cancelled",
10551
+ label: "Cancelled",
10552
+ detail: mission.cancelledReason
10553
+ });
10554
+ }
10555
+ for (const task of tasks) {
10556
+ if (task.createdAt) {
10557
+ entries.push({
10558
+ at: task.createdAt,
10559
+ kind: "task.spawned",
10560
+ label: `Spawn \xB7 ${task.agentDefName ?? "task"}`,
10561
+ detail: firstLine3(task.goal, 200)
10562
+ });
10563
+ }
10564
+ if (task.completedAt) {
10565
+ const kind = task.status === "done" ? "task.completed" : task.status === "failed" ? "task.failed" : task.status === "cancelled" ? "task.cancelled" : "task.completed";
10566
+ entries.push({
10567
+ at: task.completedAt,
10568
+ kind,
10569
+ label: `${task.status} \xB7 ${task.agentDefName ?? "task"}`,
10570
+ detail: task.result ? firstLine3(task.result, 200) : void 0
10571
+ });
10572
+ }
10573
+ }
10574
+ for (const worker of workers) {
10575
+ if (worker.latestEventAt && worker.latestEventKind) {
10576
+ entries.push({
10577
+ at: worker.latestEventAt,
10578
+ kind: "worker.latest",
10579
+ label: `${worker.kind} \xB7 ${worker.latestEventKind}`,
10580
+ detail: deriveMissionWorkerActivityLabel(worker)
10581
+ });
10582
+ }
10583
+ }
10584
+ if (mission.lastEvaluationAt && mission.lastEvaluationResult) {
10585
+ entries.push({
10586
+ at: mission.lastEvaluationAt,
10587
+ kind: "evaluator.verdict",
10588
+ label: `Verdict \xB7 ${mission.lastEvaluationResult}`,
10589
+ detail: mission.lastEvaluationFeedback ?? void 0
10590
+ });
10591
+ }
10592
+ entries.sort((a, b) => b.at.localeCompare(a.at));
10593
+ return entries;
10594
+ }
10595
+ function formatTimestamp(iso) {
10596
+ try {
10597
+ return new Date(iso).toLocaleTimeString();
10598
+ } catch {
10599
+ return iso;
10600
+ }
10601
+ }
10567
10602
  var INITIAL_STATE = {
10568
10603
  mission: null,
10569
10604
  tasks: [],
@@ -10716,210 +10751,153 @@ function MissionDashboard({
10716
10751
  setBusy(false);
10717
10752
  }
10718
10753
  };
10719
- const statusVariant = mission.status === "satisfied" ? "default" : mission.status === "failed" || mission.status === "cancelled" ? "destructive" : "secondary";
10720
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 p-4 sm:gap-6 sm:p-6", children: [
10721
- /* @__PURE__ */ jsxs(Card, { children: [
10722
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-stretch gap-4 sm:flex-row sm:items-start sm:justify-between", children: [
10723
- /* @__PURE__ */ jsxs("div", { className: "space-y-1 min-w-0 flex-1", children: [
10724
- /* @__PURE__ */ jsx(CardTitle, { className: "wrap-break-word -uppercase text-sm", children: mission.description }),
10725
- /* @__PURE__ */ jsxs(CardDescription, { className: "wrap-break-word text-foreground/70", children: [
10726
- "Rubric: ",
10727
- mission.rubric
10728
- ] }),
10729
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pt-2 text-xs text-foreground/70", children: [
10730
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant, className: "font-mono text-foreground", children: mission.status }),
10731
- /* @__PURE__ */ jsxs("span", { className: "font-mono text-primary", children: [
10732
- "Iteration ",
10733
- mission.iteration,
10734
- "/",
10735
- mission.maxIterations
10736
- ] }),
10737
- mission.lastEvaluationResult ? /* @__PURE__ */ jsxs("span", { children: [
10738
- "Last verdict:",
10739
- " ",
10740
- /* @__PURE__ */ jsx("span", { className: "font-mono text-primary", children: mission.lastEvaluationResult })
10741
- ] }) : null
10742
- ] })
10743
- ] }),
10744
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 shrink-0", children: ACTIVE_MISSION_STATUSES.has(mission.status) ? /* @__PURE__ */ jsxs(Fragment, { children: [
10745
- mission.status === "active" ? /* @__PURE__ */ jsxs(
10746
- Button,
10747
- {
10748
- size: "sm",
10749
- variant: "outline",
10750
- onClick: doPause,
10751
- disabled: busy,
10752
- children: [
10753
- /* @__PURE__ */ jsx(Pause, { className: "size-4" }),
10754
- " Pause"
10755
- ]
10756
- }
10757
- ) : /* @__PURE__ */ jsxs(
10758
- Button,
10754
+ const statusTone = mission.status === "satisfied" ? "border-emerald-500/40 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400" : mission.status === "failed" || mission.status === "cancelled" ? "border-destructive/40 bg-destructive/10 text-destructive" : mission.status === "paused" ? "border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-400" : "border-primary/40 bg-primary/10 text-primary";
10755
+ const activity = buildMissionActivity(mission, state.tasks, state.workers);
10756
+ const isActive = ACTIVE_MISSION_STATUSES.has(mission.status);
10757
+ const iterationPct = mission.maxIterations > 0 ? Math.min(100, mission.iteration / mission.maxIterations * 100) : 0;
10758
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-1 flex-col overflow-hidden bg-muted/30", children: [
10759
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 px-5 pt-5 sm:px-6 sm:pt-6", children: /* @__PURE__ */ jsx(Card, { className: "border-border/60 bg-card shadow-sm", children: /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4 p-5 sm:p-6", children: [
10760
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
10761
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
10762
+ /* @__PURE__ */ jsx(
10763
+ "span",
10759
10764
  {
10760
- size: "sm",
10761
- variant: "outline",
10762
- onClick: doResume,
10763
- disabled: busy,
10764
- children: [
10765
- /* @__PURE__ */ jsx(Play, { className: "size-4" }),
10766
- " Resume"
10767
- ]
10765
+ className: `rounded-md border px-2 py-0.5 font-mono text-[10px] font-semibold uppercase tracking-wider ${statusTone}`,
10766
+ children: mission.status
10768
10767
  }
10769
10768
  ),
10770
- /* @__PURE__ */ jsxs(
10769
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-1.5", children: [
10770
+ /* @__PURE__ */ jsx("span", { className: "font-display text-2xl font-bold tracking-tight tabular-nums text-foreground", children: mission.iteration }),
10771
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground/70", children: [
10772
+ "/ ",
10773
+ mission.maxIterations
10774
+ ] }),
10775
+ /* @__PURE__ */ jsx("span", { className: "ml-1 text-[10px] uppercase tracking-wider text-muted-foreground/60", children: "iterations" })
10776
+ ] }),
10777
+ mission.lastEvaluationResult ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-[11px] text-muted-foreground/70", children: [
10778
+ /* @__PURE__ */ jsx("span", { className: "opacity-70", children: "last verdict" }),
10779
+ /* @__PURE__ */ jsx("span", { className: "rounded border border-primary/30 bg-primary/10 px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wider text-primary", children: mission.lastEvaluationResult })
10780
+ ] }) : null
10781
+ ] }),
10782
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: [
10783
+ isActive ? /* @__PURE__ */ jsxs(Fragment, { children: [
10784
+ mission.status === "active" ? /* @__PURE__ */ jsxs(
10785
+ Button,
10786
+ {
10787
+ size: "sm",
10788
+ variant: "outline",
10789
+ onClick: doPause,
10790
+ disabled: busy,
10791
+ children: [
10792
+ /* @__PURE__ */ jsx(Pause, { className: "size-4" }),
10793
+ " Pause"
10794
+ ]
10795
+ }
10796
+ ) : /* @__PURE__ */ jsxs(
10797
+ Button,
10798
+ {
10799
+ size: "sm",
10800
+ variant: "outline",
10801
+ onClick: doResume,
10802
+ disabled: busy,
10803
+ children: [
10804
+ /* @__PURE__ */ jsx(Play, { className: "size-4" }),
10805
+ " Resume"
10806
+ ]
10807
+ }
10808
+ ),
10809
+ /* @__PURE__ */ jsxs(
10810
+ Button,
10811
+ {
10812
+ size: "sm",
10813
+ variant: "destructive",
10814
+ onClick: () => {
10815
+ setCancelCascade(false);
10816
+ setCancelOpen(true);
10817
+ },
10818
+ disabled: busy,
10819
+ children: [
10820
+ /* @__PURE__ */ jsx(Ban, { className: "size-4" }),
10821
+ " Cancel"
10822
+ ]
10823
+ }
10824
+ )
10825
+ ] }) : onNavigateBack ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: onNavigateBack, children: "Back" }) : null,
10826
+ /* @__PURE__ */ jsx(
10771
10827
  Button,
10772
10828
  {
10829
+ variant: "ghost",
10773
10830
  size: "sm",
10774
- variant: "destructive",
10775
- onClick: () => {
10776
- setCancelCascade(false);
10777
- setCancelOpen(true);
10778
- },
10831
+ onClick: () => void refresh(),
10779
10832
  disabled: busy,
10780
- children: [
10781
- /* @__PURE__ */ jsx(Ban, { className: "size-4" }),
10782
- " Cancel"
10783
- ]
10833
+ "aria-label": "Refresh",
10834
+ title: "Refresh",
10835
+ children: /* @__PURE__ */ jsx(RefreshCw, { className: "size-4" })
10784
10836
  }
10785
10837
  )
10786
- ] }) : onNavigateBack ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: onNavigateBack, children: "Back" }) : null })
10787
- ] }) }),
10788
- mission.lastEvaluationFeedback ? /* @__PURE__ */ jsxs(CardContent, { className: "space-y-2", children: [
10789
- /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold uppercase tracking-widest text-foreground/70", children: "Evaluator feedback" }),
10790
- /* @__PURE__ */ jsx("p", { className: "text-sm whitespace-pre-wrap wrap-break-word", children: mission.lastEvaluationFeedback }),
10791
- mission.lastEvaluationExplanation ? /* @__PURE__ */ jsx("p", { className: "text-xs text-foreground/70 whitespace-pre-wrap wrap-break-word", children: mission.lastEvaluationExplanation }) : null
10792
- ] }) : null
10793
- ] }),
10794
- /* @__PURE__ */ jsxs(Card, { children: [
10795
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { children: [
10796
- "Tasks (",
10797
- state.tasks.length,
10798
- ")"
10799
- ] }) }),
10800
- /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
10801
- ["in_flight", "blocked", "done", "failed_or_cancelled"].map((bucket) => {
10802
- const rows = taskBuckets[bucket];
10803
- if (rows.length === 0) return null;
10804
- const heading = {
10805
- in_flight: "In flight",
10806
- blocked: "Blocked",
10807
- done: "Done",
10808
- failed_or_cancelled: "Failed / cancelled"
10809
- }[bucket];
10810
- return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
10811
- /* @__PURE__ */ jsxs("div", { className: "text-xs font-semibold uppercase tracking-widest text-foreground/70", children: [
10812
- heading,
10813
- " (",
10814
- rows.length,
10815
- ")"
10816
- ] }),
10817
- /* @__PURE__ */ jsx("ul", { className: "space-y-1.5", children: rows.map((task) => /* @__PURE__ */ jsx(
10818
- "li",
10819
- {
10820
- className: "flex items-start justify-between gap-3 rounded border border-border/40 px-3 py-2 text-sm",
10821
- children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
10822
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10823
- task.agentDefName ? /* @__PURE__ */ jsx("span", { className: "text-xs text-foreground/70", children: task.agentDefName }) : null,
10824
- task.attemptCount > 1 ? /* @__PURE__ */ jsxs("span", { className: "text-xs text-foreground/70", children: [
10825
- "attempt ",
10826
- task.attemptCount,
10827
- "/",
10828
- task.maxAttempts
10829
- ] }) : null
10830
- ] }),
10831
- /* @__PURE__ */ jsx("div", { className: "text-sm wrap-break-word", children: task.goal }),
10832
- task.parentIds.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "text-xs text-foreground/70", children: [
10833
- "after:",
10834
- " ",
10835
- task.parentIds.map((p) => p.slice(0, 8)).join(", ")
10836
- ] }) : null,
10837
- task.result ? /* @__PURE__ */ jsx("pre", { className: "text-xs whitespace-pre-wrap bg-muted/30 rounded px-2 py-1 max-h-32 overflow-auto", children: task.result }) : null,
10838
- task.resultMetadata ? /* @__PURE__ */ jsx("pre", { className: "text-xs whitespace-pre-wrap bg-muted/30 rounded px-2 py-1 max-h-32 overflow-auto", children: JSON.stringify(task.resultMetadata, null, 2) }) : null
10839
- ] })
10840
- },
10841
- task.id
10842
- )) })
10843
- ] }, bucket);
10844
- }),
10845
- state.tasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-foreground/70", children: "No tasks spawned yet." }) : null
10846
- ] })
10847
- ] }),
10848
- /* @__PURE__ */ jsxs(Card, { children: [
10849
- /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { children: [
10850
- "Live workers (",
10851
- state.workers.length,
10852
- ")"
10853
- ] }) }),
10854
- /* @__PURE__ */ jsx(CardContent, { children: state.workers.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-sm text-foreground/70", children: "No workers attached to this mission right now." }) : /* @__PURE__ */ jsx("ul", { className: "space-y-1.5", children: state.workers.map((w) => {
10855
- const onTranscriptClick = (e) => {
10856
- if (onOpenTranscript) {
10857
- e.preventDefault();
10858
- onOpenTranscript(w.workerSessionId);
10859
- }
10860
- };
10861
- return /* @__PURE__ */ jsxs(
10862
- "li",
10863
- {
10864
- className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between rounded border border-border/40 px-3 py-2 text-sm",
10865
- children: [
10866
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
10867
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10868
- /* @__PURE__ */ jsx(
10869
- Badge,
10870
- {
10871
- variant: "outline",
10872
- className: MISSION_WORKER_KIND_BADGE_CLASS[w.kind],
10873
- title: MISSION_WORKER_KIND_TOOLTIP[w.kind],
10874
- children: w.kind
10875
- }
10876
- ),
10877
- /* @__PURE__ */ jsx(Badge, { className: "text-foreground/70", children: w.kind === "task" ? w.taskStatus ?? "\u2014" : w.sessionStatus }),
10878
- w.agentDefName ? /* @__PURE__ */ jsx("span", { className: "text-xs text-foreground/70", children: w.agentDefName }) : null
10879
- ] }),
10880
- /* @__PURE__ */ jsx("div", { className: "text-sm wrap-break-word", children: deriveMissionWorkerActivityLabel(w) }),
10881
- w.latestEventAt ? /* @__PURE__ */ jsx("div", { className: "text-xs text-foreground/70", children: new Date(w.latestEventAt).toLocaleTimeString() }) : null
10882
- ] }),
10883
- /* @__PURE__ */ jsx(
10884
- "a",
10885
- {
10886
- href: w.transcriptUrl,
10887
- target: "_blank",
10888
- rel: "noreferrer",
10889
- onClick: onTranscriptClick,
10890
- className: "text-xs text-primary hover:underline self-start",
10891
- children: "View session"
10892
- }
10893
- )
10894
- ]
10895
- },
10896
- w.workerSessionId
10897
- );
10898
- }) }) })
10899
- ] }),
10900
- /* @__PURE__ */ jsx(Separator, {}),
10901
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center text-xs text-foreground/70", children: [
10902
- /* @__PURE__ */ jsxs("span", { children: [
10903
- "Auto-refresh every ",
10904
- pollIntervalMs / 1e3,
10905
- "s while mission is active."
10838
+ ] })
10906
10839
  ] }),
10907
- /* @__PURE__ */ jsxs(
10908
- Button,
10840
+ /* @__PURE__ */ jsx(
10841
+ Progress,
10909
10842
  {
10910
- variant: "ghost",
10911
- size: "sm",
10912
- onClick: () => {
10913
- void refresh();
10914
- },
10915
- disabled: busy,
10916
- children: [
10917
- /* @__PURE__ */ jsx(RefreshCw, { className: "size-4" }),
10918
- " Refresh"
10919
- ]
10843
+ value: iterationPct,
10844
+ className: `h-1 ${isActive ? "" : "opacity-40"}`
10920
10845
  }
10921
- )
10922
- ] }),
10846
+ ),
10847
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
10848
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("h1", { className: "line-clamp-4 cursor-default font-display text-lg font-semibold leading-snug text-foreground wrap-break-word", children: mission.description }) }),
10849
+ mission.description.length > 240 ? /* @__PURE__ */ jsx(TooltipContent, { className: "max-w-lg", side: "bottom", children: /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap text-xs", children: mission.description }) }) : null
10850
+ ] }) }),
10851
+ /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border/60 bg-muted/40 px-3 py-2", children: [
10852
+ /* @__PURE__ */ jsx("div", { className: "mb-0.5 font-mono text-[9px] uppercase tracking-widest text-muted-foreground/70", children: "Rubric" }),
10853
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
10854
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("p", { className: "line-clamp-3 cursor-default text-sm leading-relaxed text-foreground/90 wrap-break-word", children: mission.rubric }) }),
10855
+ mission.rubric.length > 200 ? /* @__PURE__ */ jsx(TooltipContent, { className: "max-w-lg", side: "bottom", children: /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap text-xs", children: mission.rubric }) }) : null
10856
+ ] })
10857
+ ] })
10858
+ ] }) }) }),
10859
+ /* @__PURE__ */ jsxs(
10860
+ Tabs,
10861
+ {
10862
+ defaultValue: "activity",
10863
+ className: "mt-5 flex flex-1 flex-col overflow-hidden sm:mt-6",
10864
+ children: [
10865
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 border-b border-border bg-background px-5 sm:px-6", children: /* @__PURE__ */ jsxs(TabsList, { variant: "line", children: [
10866
+ /* @__PURE__ */ jsxs(TabsTrigger, { value: "activity", children: [
10867
+ "Activity",
10868
+ /* @__PURE__ */ jsx(CountBadge, { n: activity.length })
10869
+ ] }),
10870
+ /* @__PURE__ */ jsxs(TabsTrigger, { value: "tasks", children: [
10871
+ "Tasks",
10872
+ /* @__PURE__ */ jsx(CountBadge, { n: state.tasks.length })
10873
+ ] }),
10874
+ /* @__PURE__ */ jsxs(TabsTrigger, { value: "workers", children: [
10875
+ "Workers",
10876
+ /* @__PURE__ */ jsx(CountBadge, { n: state.workers.length })
10877
+ ] }),
10878
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "metadata", children: "Metadata" })
10879
+ ] }) }),
10880
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto bg-background px-5 py-4 sm:px-6", children: [
10881
+ /* @__PURE__ */ jsx(TabsContent, { value: "activity", className: "mt-0", children: /* @__PURE__ */ jsx(ActivityTimeline, { entries: activity }) }),
10882
+ /* @__PURE__ */ jsx(TabsContent, { value: "tasks", className: "mt-0", children: /* @__PURE__ */ jsx(
10883
+ TasksList,
10884
+ {
10885
+ taskBuckets,
10886
+ totalTasks: state.tasks.length
10887
+ }
10888
+ ) }),
10889
+ /* @__PURE__ */ jsx(TabsContent, { value: "workers", className: "mt-0", children: /* @__PURE__ */ jsx(
10890
+ WorkersList,
10891
+ {
10892
+ workers: state.workers,
10893
+ onOpenTranscript
10894
+ }
10895
+ ) }),
10896
+ /* @__PURE__ */ jsx(TabsContent, { value: "metadata", className: "mt-0", children: /* @__PURE__ */ jsx(MetadataPane, { mission }) })
10897
+ ] })
10898
+ ]
10899
+ }
10900
+ ),
10923
10901
  /* @__PURE__ */ jsx(
10924
10902
  Dialog,
10925
10903
  {
@@ -10977,6 +10955,234 @@ function MissionDashboard({
10977
10955
  ] })
10978
10956
  }
10979
10957
  )
10958
+ ] }) });
10959
+ }
10960
+ function ActivityTimeline({ entries }) {
10961
+ if (entries.length === 0) {
10962
+ return /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No mission activity yet." });
10963
+ }
10964
+ return /* @__PURE__ */ jsx("ol", { className: "space-y-1", children: entries.map((e, i) => /* @__PURE__ */ jsxs(
10965
+ "li",
10966
+ {
10967
+ className: "flex items-start gap-3 rounded px-2 py-1.5 text-sm hover:bg-muted/30",
10968
+ children: [
10969
+ /* @__PURE__ */ jsx("span", { className: "w-20 shrink-0 font-mono text-[10px] text-muted-foreground/60", children: formatTimestamp(e.at) }),
10970
+ /* @__PURE__ */ jsx(
10971
+ "span",
10972
+ {
10973
+ className: `shrink-0 rounded border px-1.5 py-0.5 font-mono text-[9px] uppercase tracking-wide ${ACTIVITY_KIND_TONE[e.kind]}`,
10974
+ children: e.label
10975
+ }
10976
+ ),
10977
+ e.detail ? /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-foreground/80", children: e.detail }) : null
10978
+ ]
10979
+ },
10980
+ `${e.kind}-${e.at}-${i}`
10981
+ )) });
10982
+ }
10983
+ function TaskRow({ task }) {
10984
+ const [open, setOpen] = useState(false);
10985
+ const goalPreview = firstLine3(task.goal, 160);
10986
+ const hasMore = task.goal.length > 160 || Boolean(task.result) || Boolean(task.resultMetadata);
10987
+ const statusTone = task.status === "done" ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600" : task.status === "failed" ? "border-destructive/30 bg-destructive/10 text-destructive" : task.status === "cancelled" ? "border-border bg-muted text-muted-foreground" : task.status === "running" ? "border-primary/30 bg-primary/10 text-primary" : "border-foreground/20 bg-foreground/5 text-foreground/70";
10988
+ return /* @__PURE__ */ jsx(Collapsible, { open, onOpenChange: setOpen, asChild: true, children: /* @__PURE__ */ jsxs("li", { className: "rounded border border-border/40 text-sm", children: [
10989
+ /* @__PURE__ */ jsx(
10990
+ CollapsibleTrigger,
10991
+ {
10992
+ asChild: true,
10993
+ disabled: !hasMore,
10994
+ children: /* @__PURE__ */ jsxs(
10995
+ "button",
10996
+ {
10997
+ type: "button",
10998
+ className: "flex w-full items-start gap-3 px-3 py-2 text-left hover:bg-muted/30 disabled:hover:bg-transparent",
10999
+ children: [
11000
+ /* @__PURE__ */ jsx(
11001
+ ChevronRight,
11002
+ {
11003
+ className: `mt-0.5 size-3.5 shrink-0 text-muted-foreground/60 transition-transform ${open ? "rotate-90" : ""} ${hasMore ? "" : "opacity-0"}`
11004
+ }
11005
+ ),
11006
+ /* @__PURE__ */ jsx(
11007
+ "span",
11008
+ {
11009
+ className: `shrink-0 rounded border px-1.5 py-0.5 font-mono text-[9px] uppercase tracking-wide ${statusTone}`,
11010
+ children: task.status
11011
+ }
11012
+ ),
11013
+ task.agentDefName ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground/70", children: task.agentDefName }) : null,
11014
+ task.attemptCount > 1 ? /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-[10px] text-muted-foreground/60", children: [
11015
+ "(",
11016
+ task.attemptCount,
11017
+ "/",
11018
+ task.maxAttempts,
11019
+ ")"
11020
+ ] }) : null,
11021
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-foreground/80", children: goalPreview })
11022
+ ]
11023
+ }
11024
+ )
11025
+ }
11026
+ ),
11027
+ /* @__PURE__ */ jsxs(CollapsibleContent, { className: "border-t border-border/40 px-3 py-2 text-xs", children: [
11028
+ /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
11029
+ /* @__PURE__ */ jsx("div", { className: "mb-1 font-mono text-[9px] uppercase tracking-wide text-muted-foreground/60", children: "Goal" }),
11030
+ /* @__PURE__ */ jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap rounded bg-muted/30 px-2 py-1.5 text-[11px] text-foreground/90", children: task.goal })
11031
+ ] }),
11032
+ task.parentIds.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "mb-2 text-[10px] text-muted-foreground/70", children: [
11033
+ "after: ",
11034
+ task.parentIds.map((p) => p.slice(0, 8)).join(", ")
11035
+ ] }) : null,
11036
+ task.result ? /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
11037
+ /* @__PURE__ */ jsx("div", { className: "mb-1 font-mono text-[9px] uppercase tracking-wide text-muted-foreground/60", children: "Result" }),
11038
+ /* @__PURE__ */ jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap rounded bg-muted/30 px-2 py-1.5 text-[11px] text-foreground/90", children: task.result })
11039
+ ] }) : null,
11040
+ task.resultMetadata ? /* @__PURE__ */ jsxs("div", { children: [
11041
+ /* @__PURE__ */ jsx("div", { className: "mb-1 font-mono text-[9px] uppercase tracking-wide text-muted-foreground/60", children: "Result metadata" }),
11042
+ /* @__PURE__ */ jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap rounded bg-muted/30 px-2 py-1.5 text-[11px] text-foreground/90", children: JSON.stringify(task.resultMetadata, null, 2) })
11043
+ ] }) : null
11044
+ ] })
11045
+ ] }) });
11046
+ }
11047
+ function TasksList({
11048
+ taskBuckets,
11049
+ totalTasks
11050
+ }) {
11051
+ if (totalTasks === 0) {
11052
+ return /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No tasks spawned yet." });
11053
+ }
11054
+ const headings = {
11055
+ in_flight: "In flight",
11056
+ blocked: "Blocked",
11057
+ done: "Done",
11058
+ failed_or_cancelled: "Failed / cancelled"
11059
+ };
11060
+ return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: Object.keys(headings).map((bucket) => {
11061
+ const rows = taskBuckets[bucket];
11062
+ if (rows.length === 0) return null;
11063
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
11064
+ /* @__PURE__ */ jsxs("div", { className: "font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: [
11065
+ headings[bucket],
11066
+ " (",
11067
+ rows.length,
11068
+ ")"
11069
+ ] }),
11070
+ /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: rows.map((task) => /* @__PURE__ */ jsx(TaskRow, { task }, task.id)) })
11071
+ ] }, bucket);
11072
+ }) });
11073
+ }
11074
+ function WorkersList({
11075
+ workers,
11076
+ onOpenTranscript
11077
+ }) {
11078
+ if (workers.length === 0) {
11079
+ return /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No workers attached to this mission right now." });
11080
+ }
11081
+ return /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: workers.map((w) => {
11082
+ const onTranscriptClick = (e) => {
11083
+ if (onOpenTranscript) {
11084
+ e.preventDefault();
11085
+ onOpenTranscript(w.workerSessionId);
11086
+ }
11087
+ };
11088
+ return /* @__PURE__ */ jsxs(
11089
+ "li",
11090
+ {
11091
+ className: "flex flex-col gap-2 rounded border border-border/40 px-3 py-2 text-sm sm:flex-row sm:items-start sm:justify-between",
11092
+ children: [
11093
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
11094
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
11095
+ /* @__PURE__ */ jsx(
11096
+ Badge,
11097
+ {
11098
+ variant: "outline",
11099
+ className: MISSION_WORKER_KIND_BADGE_CLASS[w.kind],
11100
+ title: MISSION_WORKER_KIND_TOOLTIP[w.kind],
11101
+ children: w.kind
11102
+ }
11103
+ ),
11104
+ /* @__PURE__ */ jsx(Badge, { className: "text-foreground/70", children: w.kind === "task" ? w.taskStatus ?? "\u2014" : w.sessionStatus }),
11105
+ w.agentDefName ? /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground/70", children: w.agentDefName }) : null,
11106
+ w.latestEventAt ? /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-[10px] text-muted-foreground/60", children: formatTimestamp(w.latestEventAt) }) : null
11107
+ ] }),
11108
+ /* @__PURE__ */ jsx("div", { className: "truncate text-sm text-foreground/80", children: deriveMissionWorkerActivityLabel(w) })
11109
+ ] }),
11110
+ /* @__PURE__ */ jsx(
11111
+ "a",
11112
+ {
11113
+ href: w.transcriptUrl,
11114
+ target: "_blank",
11115
+ rel: "noreferrer",
11116
+ onClick: onTranscriptClick,
11117
+ className: "self-start text-xs text-primary hover:underline",
11118
+ children: "View session"
11119
+ }
11120
+ )
11121
+ ]
11122
+ },
11123
+ w.workerSessionId
11124
+ );
11125
+ }) });
11126
+ }
11127
+ function MetadataPane({ mission }) {
11128
+ const rows = [];
11129
+ rows.push({
11130
+ label: "Mission ID",
11131
+ value: /* @__PURE__ */ jsx("code", { className: "text-[11px]", children: mission.id })
11132
+ });
11133
+ rows.push({
11134
+ label: "Session ID",
11135
+ value: /* @__PURE__ */ jsx("code", { className: "text-[11px]", children: mission.sessionId })
11136
+ });
11137
+ rows.push({
11138
+ label: "Agent ID",
11139
+ value: /* @__PURE__ */ jsx("code", { className: "text-[11px]", children: mission.agentId })
11140
+ });
11141
+ rows.push({ label: "Status", value: mission.status });
11142
+ rows.push({
11143
+ label: "Iteration",
11144
+ value: `${mission.iteration} / ${mission.maxIterations}`
11145
+ });
11146
+ rows.push({
11147
+ label: "Owner",
11148
+ value: mission.userId ? /* @__PURE__ */ jsxs(Fragment, { children: [
11149
+ "user ",
11150
+ /* @__PURE__ */ jsx("code", { className: "text-[11px]", children: mission.userId })
11151
+ ] }) : mission.serviceAccountId ? /* @__PURE__ */ jsxs(Fragment, { children: [
11152
+ "service account ",
11153
+ /* @__PURE__ */ jsx("code", { className: "text-[11px]", children: mission.serviceAccountId })
11154
+ ] }) : "\u2014"
11155
+ });
11156
+ rows.push({
11157
+ label: "Created",
11158
+ value: /* @__PURE__ */ jsx("span", { className: "font-mono text-[11px]", children: new Date(mission.createdAt).toLocaleString() })
11159
+ });
11160
+ rows.push({
11161
+ label: "Updated",
11162
+ value: /* @__PURE__ */ jsx("span", { className: "font-mono text-[11px]", children: new Date(mission.updatedAt).toLocaleString() })
11163
+ });
11164
+ if (mission.pausedReason) {
11165
+ rows.push({ label: "Paused reason", value: mission.pausedReason });
11166
+ }
11167
+ if (mission.cancelledReason) {
11168
+ rows.push({ label: "Cancelled reason", value: mission.cancelledReason });
11169
+ }
11170
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
11171
+ mission.lastEvaluationResult ? /* @__PURE__ */ jsxs("section", { className: "space-y-2", children: [
11172
+ /* @__PURE__ */ jsxs("div", { className: "font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: [
11173
+ "Last verdict \u2014 ",
11174
+ mission.lastEvaluationResult
11175
+ ] }),
11176
+ mission.lastEvaluationFeedback ? /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap text-sm text-foreground/90", children: mission.lastEvaluationFeedback }) : null,
11177
+ mission.lastEvaluationExplanation ? /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap text-xs text-muted-foreground/70", children: mission.lastEvaluationExplanation }) : null
11178
+ ] }) : null,
11179
+ /* @__PURE__ */ jsxs("section", { children: [
11180
+ /* @__PURE__ */ jsx("div", { className: "mb-2 font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: "Identifiers" }),
11181
+ /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-[max-content_1fr] gap-x-4 gap-y-1 text-xs", children: rows.map((r) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
11182
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground/70", children: r.label }),
11183
+ /* @__PURE__ */ jsx("dd", { className: "break-all text-foreground/90", children: r.value })
11184
+ ] }, r.label)) })
11185
+ ] })
10980
11186
  ] });
10981
11187
  }
10982
11188
  var DEFAULT_POLL_INTERVAL_MS2 = 3e4;