@tonyclaw/agent-inspector 2.1.17 → 2.1.19
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/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-B9sLBHw5.js → CompareDrawer-CHXN5HYU.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-TZJV7HhE.js +106 -0
- package/.output/public/assets/{ReplayDialog-D9I9W9n3.js → ReplayDialog-DQ7nS5Rr.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DGXK_Rii.js → RequestAnatomy-DXWweH_2.js} +1 -1
- package/.output/public/assets/{ResponseView-df_JzwsS.js → ResponseView-3PimPfiD.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-i3DM5IKL.js → StreamingChunkSequence-4v52v-7a.js} +1 -1
- package/.output/public/assets/_sessionId-DfkBPvCC.js +1 -0
- package/.output/public/assets/{index-Dqc2r1ea.js → index-BuhFRImh.js} +1 -1
- package/.output/public/assets/index-ChgjUix0.css +1 -0
- package/.output/public/assets/index-Uf87L52J.js +1 -0
- package/.output/public/assets/{json-viewer-D3QWQlSB.js → json-viewer-d2gWBDLO.js} +1 -1
- package/.output/public/assets/{main-ZhxhOCmF.js → main-Do-E-46G.js} +2 -2
- package/.output/server/{_sessionId-YFrP0lZP.mjs → _sessionId-B82aMW2A.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-qC3adEeq.mjs → CompareDrawer-Bud_yIrM.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-DCZIJC2b.mjs → ProxyViewerContainer-DqgVb0So.mjs} +1976 -1988
- package/.output/server/_ssr/{ReplayDialog-CvX4XYCi.mjs → ReplayDialog-DKbV5fnW.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-HQfrxjO1.mjs → RequestAnatomy-MStxp1Wp.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-QSlSD11e.mjs → ResponseView-HLTCpJcF.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-DTAiwlnI.mjs → StreamingChunkSequence-DEiyiUs_.mjs} +2 -2
- package/.output/server/_ssr/{index-D_EzfXaN.mjs → index-DamOPFDI.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-CrIX0e0Q.mjs → json-viewer-MmTWKxqh.mjs} +2 -2
- package/.output/server/_ssr/{router-__o2wrfO.mjs → router-50BIB6ED.mjs} +545 -22
- package/.output/server/{_tanstack-start-manifest_v-DbqyLpsI.mjs → _tanstack-start-manifest_v-TSwb1vFc.mjs} +1 -1
- package/.output/server/index.mjs +66 -66
- package/package.json +1 -1
- package/src/components/proxy-viewer/ConversationGroupList.tsx +11 -11
- package/src/components/proxy-viewer/ConversationHeader.tsx +7 -7
- package/src/components/proxy-viewer/LogEntry.tsx +15 -26
- package/src/components/proxy-viewer/LogEntryHeader.tsx +11 -14
- package/src/components/proxy-viewer/RequestToolsPanel.tsx +15 -15
- package/src/components/proxy-viewer/ThreadConnector.tsx +75 -91
- package/src/components/proxy-viewer/ToolTraceEvents.tsx +1 -1
- package/src/components/proxy-viewer/TurnGroup.tsx +11 -14
- package/src/mcp/server.ts +275 -0
- package/src/mcp/toolHandlers.ts +380 -3
- package/src/proxy/logSearch.ts +3 -0
- package/src/proxy/store.ts +40 -15
- package/src/routes/api/logs.ts +8 -2
- package/.output/public/assets/ProxyViewerContainer-DbWjc_BE.js +0 -106
- package/.output/public/assets/_sessionId-CTpCHdFh.js +0 -1
- package/.output/public/assets/index-Blqvndcn.js +0 -1
- package/.output/public/assets/index-Cs79WRQj.css +0 -1
|
@@ -44,13 +44,13 @@ const CATEGORY_LABELS: Record<RequestToolCategory, string> = {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
const CATEGORY_CLASSES: Record<RequestToolCategory, string> = {
|
|
47
|
-
file: "border-
|
|
48
|
-
shell: "border-
|
|
49
|
-
browser: "border-
|
|
50
|
-
web: "border-
|
|
51
|
-
mcp: "border-
|
|
52
|
-
code: "border-
|
|
53
|
-
other: "border-
|
|
47
|
+
file: "border-transparent bg-blue-400/5 text-blue-300",
|
|
48
|
+
shell: "border-transparent bg-teal-400/5 text-teal-300",
|
|
49
|
+
browser: "border-transparent bg-cyan-400/5 text-cyan-300",
|
|
50
|
+
web: "border-transparent bg-sky-400/5 text-sky-300",
|
|
51
|
+
mcp: "border-transparent bg-violet-400/5 text-violet-300",
|
|
52
|
+
code: "border-transparent bg-emerald-400/5 text-emerald-300",
|
|
53
|
+
other: "border-transparent bg-muted/30 text-muted-foreground",
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
function CategoryIcon({ category }: { category: RequestToolCategory }): JSX.Element {
|
|
@@ -101,7 +101,7 @@ function ToolRow({ tool, called }: { tool: RequestToolDefinition; called: boolea
|
|
|
101
101
|
|
|
102
102
|
return (
|
|
103
103
|
<Collapsible open={open} onOpenChange={setOpen}>
|
|
104
|
-
<div className="
|
|
104
|
+
<div className="bg-white/[0.035] rounded-[8px]">
|
|
105
105
|
<div className="flex min-w-0 items-center gap-2 px-2.5 py-2">
|
|
106
106
|
<button
|
|
107
107
|
type="button"
|
|
@@ -140,7 +140,7 @@ function ToolRow({ tool, called }: { tool: RequestToolDefinition; called: boolea
|
|
|
140
140
|
</button>
|
|
141
141
|
<button
|
|
142
142
|
type="button"
|
|
143
|
-
className="
|
|
143
|
+
className="bg-white/[0.045] hover:bg-white/[0.075] inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
144
144
|
onClick={nameCopy.copy}
|
|
145
145
|
aria-label={nameCopy.copied ? "Copied tool name" : "Copy tool name"}
|
|
146
146
|
>
|
|
@@ -153,13 +153,13 @@ function ToolRow({ tool, called }: { tool: RequestToolDefinition; called: boolea
|
|
|
153
153
|
</div>
|
|
154
154
|
<CollapsibleContent>
|
|
155
155
|
{open && (
|
|
156
|
-
<div className="space-y-2
|
|
156
|
+
<div className="space-y-2 bg-white/[0.025] px-2.5 py-2">
|
|
157
157
|
{tool.description !== null && (
|
|
158
158
|
<p className="text-xs leading-relaxed text-muted-foreground">{tool.description}</p>
|
|
159
159
|
)}
|
|
160
160
|
<RequiredParameters names={tool.requiredParameters} />
|
|
161
161
|
{tool.schema !== null && (
|
|
162
|
-
<ScrollArea className="
|
|
162
|
+
<ScrollArea className="bg-black/[0.16] max-h-64 rounded-[8px] p-2">
|
|
163
163
|
<Suspense
|
|
164
164
|
fallback={<div className="text-xs text-muted-foreground">Loading JSON...</div>}
|
|
165
165
|
>
|
|
@@ -203,7 +203,7 @@ export const RequestTools = memo(function RequestTools({
|
|
|
203
203
|
const hiddenPreviewCount = summary.tools.length - previewTools.length;
|
|
204
204
|
|
|
205
205
|
return (
|
|
206
|
-
<section className="
|
|
206
|
+
<section className="bg-black/[0.10] mb-3 overflow-hidden rounded-[8px]">
|
|
207
207
|
<div className="flex min-w-0 flex-wrap items-center gap-2 px-3 py-2">
|
|
208
208
|
<div className="flex min-w-0 flex-1 items-center gap-2">
|
|
209
209
|
<Wrench className="size-4 shrink-0 text-sky-300/80" />
|
|
@@ -251,7 +251,7 @@ export const RequestTools = memo(function RequestTools({
|
|
|
251
251
|
</Button>
|
|
252
252
|
</div>
|
|
253
253
|
|
|
254
|
-
<div className="flex min-w-0 flex-wrap gap-1.5
|
|
254
|
+
<div className="flex min-w-0 flex-wrap gap-1.5 bg-white/[0.025] px-3 py-2">
|
|
255
255
|
{previewTools.map((tool) => (
|
|
256
256
|
<Badge
|
|
257
257
|
key={tool.name}
|
|
@@ -272,8 +272,8 @@ export const RequestTools = memo(function RequestTools({
|
|
|
272
272
|
</div>
|
|
273
273
|
|
|
274
274
|
{expanded && (
|
|
275
|
-
<div className="space-y-2
|
|
276
|
-
<label className="
|
|
275
|
+
<div className="space-y-2 bg-black/10 px-3 py-3">
|
|
276
|
+
<label className="bg-white/[0.045] hover:bg-white/[0.075] flex h-8 items-center gap-2 rounded-md px-2 text-xs">
|
|
277
277
|
<Search className="size-3.5 shrink-0 text-muted-foreground" />
|
|
278
278
|
<input
|
|
279
279
|
value={query}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type JSX, type KeyboardEvent, type MouseEvent, useMemo } from "react";
|
|
2
2
|
import { isTurnBoundary, type StopReason } from "../../lib/stopReason";
|
|
3
3
|
import { cn } from "../../lib/utils";
|
|
4
|
+
import { getCrabVariant, getInteriorCrabVariant } from "../ui/crab-variants";
|
|
4
5
|
|
|
5
6
|
export type ThreadConnectorProps = {
|
|
6
7
|
stopReason: StopReason;
|
|
@@ -10,13 +11,13 @@ export type ThreadConnectorProps = {
|
|
|
10
11
|
isTurnStart: boolean;
|
|
11
12
|
/** True when this entry is the turn's only request. */
|
|
12
13
|
isOnlyEntry?: boolean;
|
|
13
|
-
/**
|
|
14
|
+
/** Seed for crab variant selection (0-11). */
|
|
15
|
+
crabIndex?: number;
|
|
16
|
+
/** When true the crab is clickable (collapse / expand a turn). */
|
|
14
17
|
collapsible?: boolean;
|
|
15
18
|
onToggle?: () => void;
|
|
16
19
|
};
|
|
17
20
|
|
|
18
|
-
type MarkerTone = "start" | "end" | "fused" | "running" | "idle";
|
|
19
|
-
|
|
20
21
|
function boundaryTitle(stopReason: StopReason): string {
|
|
21
22
|
switch (stopReason) {
|
|
22
23
|
case "end_turn":
|
|
@@ -31,77 +32,8 @@ function boundaryTitle(stopReason: StopReason): string {
|
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
function
|
|
35
|
-
|
|
36
|
-
isBoundary,
|
|
37
|
-
isTurnStart,
|
|
38
|
-
isRunning,
|
|
39
|
-
}: {
|
|
40
|
-
isFusedBoundary: boolean;
|
|
41
|
-
isBoundary: boolean;
|
|
42
|
-
isTurnStart: boolean;
|
|
43
|
-
isRunning: boolean;
|
|
44
|
-
}): MarkerTone {
|
|
45
|
-
if (isFusedBoundary) return "fused";
|
|
46
|
-
if (isBoundary) return "end";
|
|
47
|
-
if (isTurnStart) return "start";
|
|
48
|
-
if (isRunning) return "running";
|
|
49
|
-
return "idle";
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function markerClass(tone: MarkerTone, interactive: boolean): string {
|
|
53
|
-
const base =
|
|
54
|
-
"inline-flex size-3.5 items-center justify-center rounded-full border transition-colors";
|
|
55
|
-
const cursor = interactive ? "cursor-pointer hover:border-cyan-200/70 hover:bg-cyan-300/20" : "";
|
|
56
|
-
|
|
57
|
-
switch (tone) {
|
|
58
|
-
case "start":
|
|
59
|
-
return cn(base, cursor, "border-cyan-300/50 bg-cyan-300/12 text-cyan-200");
|
|
60
|
-
case "end":
|
|
61
|
-
return cn(base, cursor, "border-amber-300/55 bg-amber-300/12 text-amber-200");
|
|
62
|
-
case "fused":
|
|
63
|
-
return cn(
|
|
64
|
-
base,
|
|
65
|
-
cursor,
|
|
66
|
-
"border-slate-200/50 bg-slate-200/10 text-slate-100 ring-2 ring-cyan-300/15",
|
|
67
|
-
);
|
|
68
|
-
case "running":
|
|
69
|
-
return cn(
|
|
70
|
-
base,
|
|
71
|
-
cursor,
|
|
72
|
-
"border-amber-300/45 bg-amber-300/10 text-amber-200 ring-2 ring-amber-300/10",
|
|
73
|
-
);
|
|
74
|
-
case "idle":
|
|
75
|
-
return cn(base, cursor, "border-muted-foreground/25 bg-muted/30 text-muted-foreground/60");
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function markerInnerClass(tone: MarkerTone): string {
|
|
80
|
-
switch (tone) {
|
|
81
|
-
case "running":
|
|
82
|
-
return "size-1.5 rounded-full bg-current animate-pulse";
|
|
83
|
-
case "idle":
|
|
84
|
-
return "size-1 rounded-full bg-current opacity-55";
|
|
85
|
-
case "start":
|
|
86
|
-
case "end":
|
|
87
|
-
case "fused":
|
|
88
|
-
return "size-1.5 rounded-full bg-current";
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function markerTitle(tone: MarkerTone, stopReason: StopReason): string {
|
|
93
|
-
switch (tone) {
|
|
94
|
-
case "start":
|
|
95
|
-
return "Start of turn";
|
|
96
|
-
case "end":
|
|
97
|
-
return boundaryTitle(stopReason);
|
|
98
|
-
case "fused":
|
|
99
|
-
return "Single-request turn";
|
|
100
|
-
case "running":
|
|
101
|
-
return "Processing";
|
|
102
|
-
case "idle":
|
|
103
|
-
return "Request in turn";
|
|
104
|
-
}
|
|
35
|
+
function crabShellClass(interactive: boolean): string {
|
|
36
|
+
return interactive ? "cursor-pointer transition-transform hover:scale-110" : "";
|
|
105
37
|
}
|
|
106
38
|
|
|
107
39
|
export function ThreadConnector({
|
|
@@ -110,22 +42,24 @@ export function ThreadConnector({
|
|
|
110
42
|
isFirst,
|
|
111
43
|
isTurnStart,
|
|
112
44
|
isOnlyEntry = false,
|
|
45
|
+
crabIndex = 0,
|
|
113
46
|
collapsible = false,
|
|
114
47
|
onToggle,
|
|
115
48
|
}: ThreadConnectorProps): JSX.Element {
|
|
116
49
|
const isBoundary = isTurnBoundary(stopReason);
|
|
117
50
|
const isFusedBoundary = isOnlyEntry && isTurnStart && isBoundary;
|
|
118
51
|
const isRunning = isPending && !isBoundary;
|
|
119
|
-
const tone = markerTone({ isFusedBoundary, isBoundary, isTurnStart, isRunning });
|
|
120
52
|
const interactive = collapsible && onToggle !== undefined;
|
|
53
|
+
const Crab = useMemo(() => getCrabVariant(crabIndex), [crabIndex]);
|
|
54
|
+
const FusedCrab = useMemo(() => getInteriorCrabVariant(crabIndex), [crabIndex]);
|
|
121
55
|
|
|
122
|
-
const
|
|
56
|
+
const handleCrabClick = (event: MouseEvent<HTMLSpanElement>): void => {
|
|
123
57
|
if (!interactive || onToggle === undefined) return;
|
|
124
58
|
event.stopPropagation();
|
|
125
59
|
onToggle();
|
|
126
60
|
};
|
|
127
61
|
|
|
128
|
-
const
|
|
62
|
+
const handleCrabKeyDown = (event: KeyboardEvent<HTMLSpanElement>): void => {
|
|
129
63
|
if (!interactive || onToggle === undefined) return;
|
|
130
64
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
131
65
|
event.preventDefault();
|
|
@@ -135,19 +69,69 @@ export function ThreadConnector({
|
|
|
135
69
|
return (
|
|
136
70
|
<div className="flex flex-col items-center w-6 shrink-0 pt-0.5 pb-0.5">
|
|
137
71
|
<div className="flex justify-center h-[calc(0.75rem-8px)]">
|
|
138
|
-
{!isFirst && <div className="w-
|
|
72
|
+
{!isFirst && <div className="w-px bg-muted-foreground/18 h-full" />}
|
|
139
73
|
</div>
|
|
140
74
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
75
|
+
{isFusedBoundary ? (
|
|
76
|
+
<span
|
|
77
|
+
role={interactive ? "button" : undefined}
|
|
78
|
+
tabIndex={interactive ? 0 : undefined}
|
|
79
|
+
title="Single-request turn"
|
|
80
|
+
className={crabShellClass(interactive)}
|
|
81
|
+
onClick={handleCrabClick}
|
|
82
|
+
onKeyDown={handleCrabKeyDown}
|
|
83
|
+
>
|
|
84
|
+
<FusedCrab
|
|
85
|
+
className={cn(
|
|
86
|
+
"size-3.5 text-[#80FF00]",
|
|
87
|
+
"animate-crab-settle",
|
|
88
|
+
"drop-shadow-[0_0_4px_rgba(128,255,0,0.5)]",
|
|
89
|
+
)}
|
|
90
|
+
/>
|
|
91
|
+
</span>
|
|
92
|
+
) : isBoundary ? (
|
|
93
|
+
<span
|
|
94
|
+
role={interactive ? "button" : undefined}
|
|
95
|
+
tabIndex={interactive ? 0 : undefined}
|
|
96
|
+
title={boundaryTitle(stopReason)}
|
|
97
|
+
className={crabShellClass(interactive)}
|
|
98
|
+
onClick={handleCrabClick}
|
|
99
|
+
onKeyDown={handleCrabKeyDown}
|
|
100
|
+
>
|
|
101
|
+
<Crab
|
|
102
|
+
className={cn(
|
|
103
|
+
"size-3.5 text-amber-400",
|
|
104
|
+
"animate-crab-settle",
|
|
105
|
+
"drop-shadow-[0_0_4px_rgba(251,191,36,0.5)]",
|
|
106
|
+
)}
|
|
107
|
+
/>
|
|
108
|
+
</span>
|
|
109
|
+
) : isTurnStart ? (
|
|
110
|
+
<span
|
|
111
|
+
role={interactive ? "button" : undefined}
|
|
112
|
+
tabIndex={interactive ? 0 : undefined}
|
|
113
|
+
title="Start of turn"
|
|
114
|
+
className={crabShellClass(interactive)}
|
|
115
|
+
onClick={handleCrabClick}
|
|
116
|
+
onKeyDown={handleCrabKeyDown}
|
|
117
|
+
>
|
|
118
|
+
<Crab
|
|
119
|
+
className={cn(
|
|
120
|
+
"size-3.5 text-emerald-400",
|
|
121
|
+
"animate-crab-appear",
|
|
122
|
+
"drop-shadow-[0_0_4px_rgba(52,211,153,0.5)]",
|
|
123
|
+
)}
|
|
124
|
+
/>
|
|
125
|
+
</span>
|
|
126
|
+
) : isRunning ? (
|
|
127
|
+
<span title="Processing">
|
|
128
|
+
<Crab className={cn("size-3.5 text-amber-300/80", "animate-crab-crawl")} />
|
|
129
|
+
</span>
|
|
130
|
+
) : (
|
|
131
|
+
<span title="Request in turn">
|
|
132
|
+
<Crab className="size-3.5 text-muted-foreground/40" />
|
|
133
|
+
</span>
|
|
134
|
+
)}
|
|
151
135
|
|
|
152
136
|
<div className="flex-1 flex justify-center min-h-0">
|
|
153
137
|
{!isBoundary && (
|
|
@@ -155,8 +139,8 @@ export function ThreadConnector({
|
|
|
155
139
|
className={cn(
|
|
156
140
|
"w-0.5 h-full",
|
|
157
141
|
isPending
|
|
158
|
-
? "border-dashed bg-transparent border-l
|
|
159
|
-
: "bg-muted-foreground/
|
|
142
|
+
? "border-dashed bg-transparent border-l border-muted-foreground/14"
|
|
143
|
+
: "bg-muted-foreground/18",
|
|
160
144
|
)}
|
|
161
145
|
/>
|
|
162
146
|
)}
|
|
@@ -14,7 +14,7 @@ function ToolTraceEventRow({ event }: { event: ToolTraceEvent }): JSX.Element {
|
|
|
14
14
|
return (
|
|
15
15
|
<div
|
|
16
16
|
key={event.id}
|
|
17
|
-
className="group/tool-trace flex min-w-0 items-center gap-2 rounded-md
|
|
17
|
+
className="group/tool-trace flex min-w-0 items-center gap-2 rounded-md bg-white/[0.035] px-2.5 py-1.5 text-xs"
|
|
18
18
|
>
|
|
19
19
|
<Wrench className="size-3.5 shrink-0 text-sky-400/70" />
|
|
20
20
|
<span className="font-mono font-semibold text-foreground/80">{event.name}</span>
|
|
@@ -143,7 +143,7 @@ export const TurnGroup = memo(function TurnGroup({
|
|
|
143
143
|
};
|
|
144
144
|
}, [entries, lastIdx]);
|
|
145
145
|
|
|
146
|
-
const bgClass = turnIndex % 2 === 0 ? "bg-white/[0.
|
|
146
|
+
const bgClass = turnIndex % 2 === 0 ? "bg-white/[0.008]" : "bg-cyan-300/[0.008]";
|
|
147
147
|
const aggregateIsSlow =
|
|
148
148
|
aggregate.maxElapsed !== null &&
|
|
149
149
|
slowResponseThresholdSeconds > 0 &&
|
|
@@ -194,10 +194,8 @@ export const TurnGroup = memo(function TurnGroup({
|
|
|
194
194
|
aria-label={collapsed ? undefined : turnLabel}
|
|
195
195
|
data-nav-id={collapsed ? undefined : `turn-${String(firstLogId)}`}
|
|
196
196
|
className={cn(
|
|
197
|
-
"rounded-[8px]
|
|
198
|
-
isPending
|
|
199
|
-
? "border-amber-300/15 shadow-[0_0_0_1px_rgba(252,211,77,0.04)]"
|
|
200
|
-
: "border-transparent",
|
|
197
|
+
"rounded-[8px] transition-[background-color,box-shadow]",
|
|
198
|
+
isPending ? "bg-amber-300/[0.018] shadow-[0_0_0_1px_rgba(252,211,77,0.035)]" : "",
|
|
201
199
|
!collapsed &&
|
|
202
200
|
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none",
|
|
203
201
|
)}
|
|
@@ -226,16 +224,14 @@ export const TurnGroup = memo(function TurnGroup({
|
|
|
226
224
|
|
|
227
225
|
<div className="w-6 shrink-0 flex flex-col items-center pt-1.5 pb-1.5">
|
|
228
226
|
<div className="flex justify-center h-[calc(0.75rem-8px)]" />
|
|
229
|
-
<span className="size-2 rounded-full
|
|
227
|
+
<span className="size-2 rounded-full bg-cyan-300/45" />
|
|
230
228
|
<div className="flex-1 flex justify-center min-h-0">
|
|
231
|
-
<div className="w-px bg-muted-foreground/
|
|
229
|
+
<div className="w-px bg-muted-foreground/14 h-full" />
|
|
232
230
|
</div>
|
|
233
231
|
<span
|
|
234
232
|
className={cn(
|
|
235
|
-
"size-2 rounded-full
|
|
236
|
-
isComplete
|
|
237
|
-
? "border-amber-300/45 bg-amber-300/20"
|
|
238
|
-
: "border-muted-foreground/30 bg-muted/30",
|
|
233
|
+
"size-2 rounded-full",
|
|
234
|
+
isComplete ? "bg-amber-300/45" : "bg-muted-foreground/25",
|
|
239
235
|
)}
|
|
240
236
|
/>
|
|
241
237
|
</div>
|
|
@@ -244,8 +240,8 @@ export const TurnGroup = memo(function TurnGroup({
|
|
|
244
240
|
{entries.length > 1 && (
|
|
245
241
|
<div
|
|
246
242
|
className={cn(
|
|
247
|
-
"flex-1 min-w-0 mb-0.5 rounded-[8px] py-1.5 px-3 flex items-center gap-3 text-xs
|
|
248
|
-
"
|
|
243
|
+
"flex-1 min-w-0 mb-0.5 rounded-[8px] py-1.5 px-3 flex items-center gap-3 text-xs",
|
|
244
|
+
"bg-card/80 transition-colors hover:bg-card",
|
|
249
245
|
bgClass,
|
|
250
246
|
)}
|
|
251
247
|
>
|
|
@@ -318,7 +314,7 @@ export const TurnGroup = memo(function TurnGroup({
|
|
|
318
314
|
<span className="flex-1 min-w-0" />
|
|
319
315
|
|
|
320
316
|
<span
|
|
321
|
-
className="
|
|
317
|
+
className="bg-white/[0.045] inline-flex size-7 shrink-0 items-center justify-center rounded-md text-slate-200"
|
|
322
318
|
aria-hidden="true"
|
|
323
319
|
>
|
|
324
320
|
<ChevronRight className="size-4 shrink-0" />
|
|
@@ -349,6 +345,7 @@ export const TurnGroup = memo(function TurnGroup({
|
|
|
349
345
|
isFirst={visibleIdx === 0}
|
|
350
346
|
isTurnStart={isTurnStart}
|
|
351
347
|
isOnlyEntry={isSingleLog}
|
|
348
|
+
crabIndex={log.id % 12}
|
|
352
349
|
collapsible={collapsible && isTurnStart}
|
|
353
350
|
onToggle={toggleCollapse}
|
|
354
351
|
/>
|