refactor(conversation-status): share sidebar status glyphs across menus, search, and manage dialog
This commit is contained in:
@@ -61,10 +61,11 @@ import type {
|
|||||||
import {
|
import {
|
||||||
AGENT_LABELS,
|
AGENT_LABELS,
|
||||||
ALL_AGENT_TYPES,
|
ALL_AGENT_TYPES,
|
||||||
STATUS_COLORS,
|
STATUS_ICON_COLORS,
|
||||||
STATUS_ORDER,
|
STATUS_ORDER,
|
||||||
} from "@/lib/types"
|
} from "@/lib/types"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
import { ConversationStatusIcon } from "@/components/conversations/conversation-status-icon"
|
||||||
|
|
||||||
interface ConversationManageDialogProps {
|
interface ConversationManageDialogProps {
|
||||||
open: boolean
|
open: boolean
|
||||||
@@ -291,11 +292,9 @@ export function ConversationManageDialog({
|
|||||||
{STATUS_ORDER.map((s) => (
|
{STATUS_ORDER.map((s) => (
|
||||||
<SelectItem key={s} value={s}>
|
<SelectItem key={s} value={s}>
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">
|
||||||
<span
|
<ConversationStatusIcon
|
||||||
className={cn(
|
status={s}
|
||||||
"h-2 w-2 rounded-full",
|
className={cn("h-4 w-4", STATUS_ICON_COLORS[s])}
|
||||||
STATUS_COLORS[s]
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
{tStatus(s)}
|
{tStatus(s)}
|
||||||
</span>
|
</span>
|
||||||
@@ -388,11 +387,7 @@ export function ConversationManageDialog({
|
|||||||
{formatRelative(conv.updated_at)}
|
{formatRelative(conv.updated_at)}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className="shrink-0 inline-flex"
|
||||||
"shrink-0 h-2 w-2 rounded-full",
|
|
||||||
STATUS_COLORS[conv.status as ConversationStatus] ??
|
|
||||||
"bg-gray-400"
|
|
||||||
)}
|
|
||||||
title={
|
title={
|
||||||
STATUS_ORDER.includes(
|
STATUS_ORDER.includes(
|
||||||
conv.status as ConversationStatus
|
conv.status as ConversationStatus
|
||||||
@@ -400,7 +395,17 @@ export function ConversationManageDialog({
|
|||||||
? tStatus(conv.status as ConversationStatus)
|
? tStatus(conv.status as ConversationStatus)
|
||||||
: conv.status
|
: conv.status
|
||||||
}
|
}
|
||||||
|
>
|
||||||
|
<ConversationStatusIcon
|
||||||
|
status={conv.status as ConversationStatus}
|
||||||
|
className={cn(
|
||||||
|
"h-4 w-4",
|
||||||
|
STATUS_ICON_COLORS[
|
||||||
|
conv.status as ConversationStatus
|
||||||
|
] ?? "text-muted-foreground"
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -434,11 +439,9 @@ export function ConversationManageDialog({
|
|||||||
key={s}
|
key={s}
|
||||||
onSelect={() => handleBulkStatus(s)}
|
onSelect={() => handleBulkStatus(s)}
|
||||||
>
|
>
|
||||||
<span
|
<ConversationStatusIcon
|
||||||
className={cn(
|
status={s}
|
||||||
"h-2 w-2 rounded-full mr-2",
|
className={cn("h-4 w-4", STATUS_ICON_COLORS[s])}
|
||||||
STATUS_COLORS[s]
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
{tStatus(s)}
|
{tStatus(s)}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|||||||
105
src/components/conversations/conversation-status-icon.tsx
Normal file
105
src/components/conversations/conversation-status-icon.tsx
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import type { ConversationStatus } from "@/lib/types"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
interface ConversationStatusIconProps {
|
||||||
|
status: ConversationStatus
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConversationStatusIcon({
|
||||||
|
status,
|
||||||
|
className,
|
||||||
|
}: ConversationStatusIconProps) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className={cn("shrink-0", className)}
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 10 10"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
aria-hidden
|
||||||
|
>
|
||||||
|
{status === "in_progress" ? (
|
||||||
|
<>
|
||||||
|
<circle
|
||||||
|
cx="5"
|
||||||
|
cy="5"
|
||||||
|
r="3.8"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.1"
|
||||||
|
opacity="0.28"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5 1.2 A 3.8 3.8 0 1 1 1.2 5"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.3"
|
||||||
|
strokeLinecap="round"
|
||||||
|
>
|
||||||
|
<animateTransform
|
||||||
|
attributeName="transform"
|
||||||
|
type="rotate"
|
||||||
|
from="0 5 5"
|
||||||
|
to="360 5 5"
|
||||||
|
dur="1.1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</path>
|
||||||
|
</>
|
||||||
|
) : status === "pending_review" ? (
|
||||||
|
<>
|
||||||
|
<circle
|
||||||
|
cx="5"
|
||||||
|
cy="5"
|
||||||
|
r="3.9"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.1"
|
||||||
|
opacity="0.35"
|
||||||
|
/>
|
||||||
|
<circle cx="5" cy="5" r="2" fill="currentColor" />
|
||||||
|
</>
|
||||||
|
) : status === "cancelled" ? (
|
||||||
|
<>
|
||||||
|
<circle
|
||||||
|
cx="5"
|
||||||
|
cy="5"
|
||||||
|
r="3.9"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.1"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3.4 3.4L6.6 6.6M6.6 3.4L3.4 6.6"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.3"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<circle
|
||||||
|
cx="5"
|
||||||
|
cy="5"
|
||||||
|
r="3.9"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.1"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3.2 5.1 L4.4 6.3 L6.9 3.6"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.3"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -17,8 +17,9 @@ import type {
|
|||||||
DbConversationSummary,
|
DbConversationSummary,
|
||||||
} from "@/lib/types"
|
} from "@/lib/types"
|
||||||
import { useFileTree, type FlatFileEntry } from "@/hooks/use-file-tree"
|
import { useFileTree, type FlatFileEntry } from "@/hooks/use-file-tree"
|
||||||
import { AGENT_LABELS, STATUS_COLORS, compareAgentType } from "@/lib/types"
|
import { AGENT_LABELS, STATUS_ICON_COLORS, compareAgentType } from "@/lib/types"
|
||||||
import { AgentIcon } from "@/components/agent-icon"
|
import { AgentIcon } from "@/components/agent-icon"
|
||||||
|
import { ConversationStatusIcon } from "@/components/conversations/conversation-status-icon"
|
||||||
import {
|
import {
|
||||||
CommandDialog,
|
CommandDialog,
|
||||||
CommandInput,
|
CommandInput,
|
||||||
@@ -268,11 +269,12 @@ export function SearchCommandDialog({
|
|||||||
value={`${conv.id}-${conv.title ?? ""}`}
|
value={`${conv.id}-${conv.title ?? ""}`}
|
||||||
onSelect={() => handleSelectConversation(conv)}
|
onSelect={() => handleSelectConversation(conv)}
|
||||||
>
|
>
|
||||||
<span
|
<ConversationStatusIcon
|
||||||
|
status={conv.status as ConversationStatus}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-2 h-2 rounded-full shrink-0",
|
"h-4 w-4",
|
||||||
STATUS_COLORS[conv.status as ConversationStatus] ??
|
STATUS_ICON_COLORS[conv.status as ConversationStatus] ??
|
||||||
"bg-gray-400"
|
"text-muted-foreground"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<span className="flex-1 truncate">
|
<span className="flex-1 truncate">
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { memo, useState, useCallback } from "react"
|
import { memo, useState, useCallback } from "react"
|
||||||
import {
|
import { Pencil, Trash2, Circle, Plus } from "lucide-react"
|
||||||
Pencil,
|
|
||||||
Trash2,
|
|
||||||
Circle,
|
|
||||||
CircleAlert,
|
|
||||||
CircleCheck,
|
|
||||||
CircleDashed,
|
|
||||||
CircleX,
|
|
||||||
Plus,
|
|
||||||
type LucideIcon,
|
|
||||||
} from "lucide-react"
|
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import type { DbConversationSummary, ConversationStatus } from "@/lib/types"
|
import type { DbConversationSummary, ConversationStatus } from "@/lib/types"
|
||||||
import { STATUS_ORDER } from "@/lib/types"
|
import { STATUS_ICON_COLORS, STATUS_ORDER } from "@/lib/types"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
@@ -45,24 +35,8 @@ import {
|
|||||||
} from "@/components/ui/alert-dialog"
|
} from "@/components/ui/alert-dialog"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import {
|
import { ConversationStatusIcon } from "./conversation-status-icon"
|
||||||
SidebarStatusIcon,
|
import { SidebarStatusIcon } from "./sidebar-status-icon"
|
||||||
conversationStatusToBead,
|
|
||||||
} from "./sidebar-status-icon"
|
|
||||||
|
|
||||||
const STATUS_ICONS: Record<ConversationStatus, LucideIcon> = {
|
|
||||||
in_progress: CircleDashed,
|
|
||||||
pending_review: CircleAlert,
|
|
||||||
completed: CircleCheck,
|
|
||||||
cancelled: CircleX,
|
|
||||||
}
|
|
||||||
|
|
||||||
const STATUS_ICON_COLORS: Record<ConversationStatus, string> = {
|
|
||||||
in_progress: "text-blue-500",
|
|
||||||
pending_review: "text-orange-500",
|
|
||||||
completed: "text-green-500",
|
|
||||||
cancelled: "text-red-500",
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SidebarConversationCardProps {
|
interface SidebarConversationCardProps {
|
||||||
conversation: DbConversationSummary
|
conversation: DbConversationSummary
|
||||||
@@ -123,7 +97,6 @@ export const SidebarConversationCard = memo(function SidebarConversationCard({
|
|||||||
}, [conversation.id, conversation.agent_type, onDelete])
|
}, [conversation.id, conversation.agent_type, onDelete])
|
||||||
|
|
||||||
const status = conversation.status as ConversationStatus
|
const status = conversation.status as ConversationStatus
|
||||||
const beadStatus = conversationStatusToBead(conversation.status)
|
|
||||||
const isRunning = status === "in_progress"
|
const isRunning = status === "in_progress"
|
||||||
const isFailed = status === "cancelled"
|
const isFailed = status === "cancelled"
|
||||||
|
|
||||||
@@ -165,7 +138,7 @@ export const SidebarConversationCard = memo(function SidebarConversationCard({
|
|||||||
transform: "translateX(-50%)",
|
transform: "translateX(-50%)",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SidebarStatusIcon status={beadStatus} emphasized={isOpenInTab} />
|
<SidebarStatusIcon status={status} emphasized={isOpenInTab} />
|
||||||
|
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -238,20 +211,18 @@ export const SidebarConversationCard = memo(function SidebarConversationCard({
|
|||||||
</ContextMenuSubTrigger>
|
</ContextMenuSubTrigger>
|
||||||
<ContextMenuSubContent>
|
<ContextMenuSubContent>
|
||||||
{STATUS_ORDER.filter((s) => s !== conversation.status).map(
|
{STATUS_ORDER.filter((s) => s !== conversation.status).map(
|
||||||
(s) => {
|
(s) => (
|
||||||
const StatusIcon = STATUS_ICONS[s]
|
|
||||||
return (
|
|
||||||
<ContextMenuItem
|
<ContextMenuItem
|
||||||
key={s}
|
key={s}
|
||||||
onSelect={() => onStatusChange(conversation.id, s)}
|
onSelect={() => onStatusChange(conversation.id, s)}
|
||||||
>
|
>
|
||||||
<StatusIcon
|
<ConversationStatusIcon
|
||||||
|
status={s}
|
||||||
className={cn("h-4 w-4", STATUS_ICON_COLORS[s])}
|
className={cn("h-4 w-4", STATUS_ICON_COLORS[s])}
|
||||||
/>
|
/>
|
||||||
{tStatus(s)}
|
{tStatus(s)}
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
)}
|
)}
|
||||||
</ContextMenuSubContent>
|
</ContextMenuSubContent>
|
||||||
</ContextMenuSub>
|
</ContextMenuSub>
|
||||||
|
|||||||
@@ -1,24 +1,29 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import type { ConversationStatus } from "@/lib/types"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
import { ConversationStatusIcon } from "./conversation-status-icon"
|
||||||
export type SidebarBeadStatus = "done" | "active" | "running" | "failed"
|
|
||||||
|
|
||||||
interface SidebarStatusIconProps {
|
interface SidebarStatusIconProps {
|
||||||
status: SidebarBeadStatus
|
status: ConversationStatus
|
||||||
emphasized?: boolean
|
emphasized?: boolean
|
||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function IconFrame({
|
export function SidebarStatusIcon({
|
||||||
children,
|
status,
|
||||||
colorClass,
|
emphasized = false,
|
||||||
className,
|
className,
|
||||||
}: {
|
}: SidebarStatusIconProps) {
|
||||||
children: React.ReactNode
|
const colorClass =
|
||||||
colorClass: string
|
status === "completed"
|
||||||
className?: string
|
? emphasized
|
||||||
}) {
|
? "text-sidebar-primary/75"
|
||||||
|
: "text-sidebar-primary/40"
|
||||||
|
: emphasized
|
||||||
|
? "text-sidebar-primary"
|
||||||
|
: "text-sidebar-primary/65"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -35,167 +40,10 @@ function IconFrame({
|
|||||||
}}
|
}}
|
||||||
aria-hidden
|
aria-hidden
|
||||||
>
|
>
|
||||||
{children}
|
<ConversationStatusIcon
|
||||||
|
status={status}
|
||||||
|
className="h-[0.75rem] w-[0.75rem]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SidebarStatusIcon({
|
|
||||||
status,
|
|
||||||
emphasized = false,
|
|
||||||
className,
|
|
||||||
}: SidebarStatusIconProps) {
|
|
||||||
if (status === "running") {
|
|
||||||
return (
|
|
||||||
<IconFrame
|
|
||||||
colorClass={
|
|
||||||
emphasized ? "text-sidebar-primary" : "text-sidebar-primary/65"
|
|
||||||
}
|
|
||||||
className={className}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="0.75rem"
|
|
||||||
height="0.75rem"
|
|
||||||
viewBox="0 0 10 10"
|
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="5"
|
|
||||||
cy="5"
|
|
||||||
r="3.8"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.1"
|
|
||||||
opacity="0.28"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M5 1.2 A 3.8 3.8 0 1 1 1.2 5"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.3"
|
|
||||||
strokeLinecap="round"
|
|
||||||
>
|
|
||||||
<animateTransform
|
|
||||||
attributeName="transform"
|
|
||||||
type="rotate"
|
|
||||||
from="0 5 5"
|
|
||||||
to="360 5 5"
|
|
||||||
dur="1.1s"
|
|
||||||
repeatCount="indefinite"
|
|
||||||
/>
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
</IconFrame>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status === "failed") {
|
|
||||||
return (
|
|
||||||
<IconFrame
|
|
||||||
colorClass={
|
|
||||||
emphasized ? "text-sidebar-primary" : "text-sidebar-primary/65"
|
|
||||||
}
|
|
||||||
className={className}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="0.75rem"
|
|
||||||
height="0.75rem"
|
|
||||||
viewBox="0 0 10 10"
|
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="5"
|
|
||||||
cy="5"
|
|
||||||
r="3.9"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.1"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3.4 3.4L6.6 6.6M6.6 3.4L3.4 6.6"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.3"
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</IconFrame>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status === "active") {
|
|
||||||
return (
|
|
||||||
<IconFrame
|
|
||||||
colorClass={
|
|
||||||
emphasized ? "text-sidebar-primary" : "text-sidebar-primary/65"
|
|
||||||
}
|
|
||||||
className={className}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="0.75rem"
|
|
||||||
height="0.75rem"
|
|
||||||
viewBox="0 0 10 10"
|
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="5"
|
|
||||||
cy="5"
|
|
||||||
r="3.9"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.1"
|
|
||||||
opacity="0.35"
|
|
||||||
/>
|
|
||||||
<circle cx="5" cy="5" r="2" fill="currentColor" />
|
|
||||||
</svg>
|
|
||||||
</IconFrame>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IconFrame
|
|
||||||
colorClass={
|
|
||||||
emphasized ? "text-sidebar-primary/75" : "text-sidebar-primary/40"
|
|
||||||
}
|
|
||||||
className={className}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="0.75rem"
|
|
||||||
height="0.75rem"
|
|
||||||
viewBox="0 0 10 10"
|
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="5"
|
|
||||||
cy="5"
|
|
||||||
r="3.9"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.1"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3.2 5.1 L4.4 6.3 L6.9 3.6"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.3"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</IconFrame>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function conversationStatusToBead(status: string): SidebarBeadStatus {
|
|
||||||
switch (status) {
|
|
||||||
case "in_progress":
|
|
||||||
return "running"
|
|
||||||
case "pending_review":
|
|
||||||
return "active"
|
|
||||||
case "cancelled":
|
|
||||||
return "failed"
|
|
||||||
case "completed":
|
|
||||||
default:
|
|
||||||
return "done"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -228,6 +228,13 @@ export const STATUS_COLORS: Record<ConversationStatus, string> = {
|
|||||||
cancelled: "bg-red-500",
|
cancelled: "bg-red-500",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const STATUS_ICON_COLORS: Record<ConversationStatus, string> = {
|
||||||
|
in_progress: "text-blue-500",
|
||||||
|
pending_review: "text-orange-500",
|
||||||
|
completed: "text-green-500",
|
||||||
|
cancelled: "text-red-500",
|
||||||
|
}
|
||||||
|
|
||||||
export const AGENT_DISPLAY_ORDER: AgentType[] = [
|
export const AGENT_DISPLAY_ORDER: AgentType[] = [
|
||||||
"codex",
|
"codex",
|
||||||
"claude_code",
|
"claude_code",
|
||||||
|
|||||||
Reference in New Issue
Block a user