@tangle-network/ui 11.6.0 → 11.7.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/CHANGELOG.md +6 -0
- package/README.md +43 -0
- package/dist/chat.d.ts +18 -8
- package/dist/chat.js +6 -5
- package/dist/{chunk-XROQW5J7.js → chunk-4ENFLPWQ.js} +1 -1
- package/dist/{chunk-XPYPZMYT.js → chunk-6RIX7M27.js} +1 -1
- package/dist/{chunk-R5GVQDL3.js → chunk-CVX53NCC.js} +7 -5
- package/dist/{chunk-ULDNFLIM.js → chunk-EIUE5GV2.js} +10 -14
- package/dist/chunk-L57WRIND.js +59 -0
- package/dist/chunk-LFVF2HFB.js +19 -0
- package/dist/{chunk-AZWDI2JG.js → chunk-UYTRNR7Z.js} +1 -1
- package/dist/{chunk-RKC3GXHE.js → chunk-VDCZHOOO.js} +99 -104
- package/dist/{chunk-J2G7KCYH.js → chunk-XT4JMYVB.js} +109 -67
- package/dist/hooks.js +6 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -10
- package/dist/primitives.d.ts +15 -1
- package/dist/primitives.js +5 -1
- package/dist/run.d.ts +22 -17
- package/dist/run.js +8 -6
- package/dist/sdk-hooks.js +6 -5
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +1 -1
- package/package.json +1 -1
- package/src/chat/agent-timeline.stories.tsx +163 -10
- package/src/chat/agent-timeline.test.tsx +114 -7
- package/src/chat/agent-timeline.tsx +120 -158
- package/src/chat/chat-container.test.tsx +59 -0
- package/src/chat/user-message.test.tsx +33 -0
- package/src/chat/user-message.tsx +13 -8
- package/src/primitives/index.ts +3 -0
- package/src/primitives/text-shimmer.test.tsx +34 -0
- package/src/primitives/text-shimmer.tsx +82 -0
- package/src/run/inline-thinking-item.stories.tsx +2 -2
- package/src/run/inline-thinking-item.tsx +2 -2
- package/src/run/inline-tool-item.test.tsx +76 -0
- package/src/run/inline-tool-item.tsx +9 -7
- package/src/run/run-group.tsx +4 -3
- package/src/run/run-row-shell.test.tsx +74 -4
- package/src/run/run-row-shell.tsx +81 -53
- package/src/run/tool-call-step.tsx +9 -7
- package/src/utils/tool-display.test.ts +53 -0
- package/src/utils/tool-display.ts +16 -15
- package/dist/chunk-LQS34IGP.js +0 -0
- /package/dist/{chunk-EJ5NBW7V.js → chunk-LDLOJKPC.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
useSSEStream,
|
|
21
21
|
useSdkSession,
|
|
22
22
|
useToolCallStream
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-4ENFLPWQ.js";
|
|
24
24
|
import {
|
|
25
25
|
addMessage,
|
|
26
26
|
addParts,
|
|
@@ -118,7 +118,7 @@ import {
|
|
|
118
118
|
UploadProgress,
|
|
119
119
|
useTheme,
|
|
120
120
|
useToast
|
|
121
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-LDLOJKPC.js";
|
|
122
122
|
import {
|
|
123
123
|
Avatar,
|
|
124
124
|
AvatarFallback,
|
|
@@ -146,28 +146,29 @@ import {
|
|
|
146
146
|
MessageList,
|
|
147
147
|
ThinkingIndicator,
|
|
148
148
|
UserMessage
|
|
149
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-VDCZHOOO.js";
|
|
150
150
|
import {
|
|
151
151
|
useAutoScroll,
|
|
152
152
|
useRunCollapseState,
|
|
153
153
|
useRunGroups
|
|
154
|
-
} from "./chunk-
|
|
155
|
-
import
|
|
154
|
+
} from "./chunk-UYTRNR7Z.js";
|
|
155
|
+
import {
|
|
156
|
+
LiveDuration
|
|
157
|
+
} from "./chunk-LFVF2HFB.js";
|
|
156
158
|
import {
|
|
157
159
|
ToolCallFeed,
|
|
158
160
|
parseToolEvent
|
|
159
|
-
} from "./chunk-
|
|
161
|
+
} from "./chunk-6RIX7M27.js";
|
|
160
162
|
import {
|
|
161
163
|
InlineThinkingItem,
|
|
162
164
|
RunGroup
|
|
163
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-CVX53NCC.js";
|
|
164
166
|
import {
|
|
165
167
|
ExpandedToolDetail,
|
|
166
168
|
InlineToolItem,
|
|
167
|
-
LiveDuration,
|
|
168
169
|
RunRowShell,
|
|
169
170
|
RunRowStatusDot
|
|
170
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-XT4JMYVB.js";
|
|
171
172
|
import {
|
|
172
173
|
TOOL_CATEGORY_ICONS,
|
|
173
174
|
formatBytes,
|
|
@@ -177,7 +178,7 @@ import {
|
|
|
177
178
|
getToolDisplayMetadata,
|
|
178
179
|
getToolErrorText,
|
|
179
180
|
truncateText
|
|
180
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-EIUE5GV2.js";
|
|
181
182
|
import {
|
|
182
183
|
CommandPreview,
|
|
183
184
|
DiffPreview,
|
|
@@ -187,6 +188,9 @@ import {
|
|
|
187
188
|
WebSearchPreview,
|
|
188
189
|
WriteFilePreview
|
|
189
190
|
} from "./chunk-AAUNOHVL.js";
|
|
191
|
+
import {
|
|
192
|
+
TextShimmer
|
|
193
|
+
} from "./chunk-L57WRIND.js";
|
|
190
194
|
import "./chunk-RQGKSCEZ.js";
|
|
191
195
|
import {
|
|
192
196
|
OpenUIArtifactRenderer
|
|
@@ -364,6 +368,7 @@ export {
|
|
|
364
368
|
TerminalDisplay,
|
|
365
369
|
TerminalInput,
|
|
366
370
|
TerminalLine,
|
|
371
|
+
TextShimmer,
|
|
367
372
|
Textarea,
|
|
368
373
|
ThemeToggle,
|
|
369
374
|
ThinkingIndicator,
|
package/dist/primitives.d.ts
CHANGED
|
@@ -192,6 +192,20 @@ declare function SkeletonTable({ rows }: {
|
|
|
192
192
|
rows?: number;
|
|
193
193
|
}): react_jsx_runtime.JSX.Element;
|
|
194
194
|
|
|
195
|
+
interface TextShimmerProps {
|
|
196
|
+
children: ReactNode;
|
|
197
|
+
className?: string;
|
|
198
|
+
/** One sweep across the text, in milliseconds. */
|
|
199
|
+
durationMs?: number;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Inline text with a gradient-mask sweep — the in-flight signal for a run row
|
|
203
|
+
* label ("Thinking…", a tool verb while its call is running). Carries the
|
|
204
|
+
* styles it needs, so a consumer that only scans this package for Tailwind
|
|
205
|
+
* classes still gets the animation.
|
|
206
|
+
*/
|
|
207
|
+
declare function TextShimmer({ children, className, durationMs, }: TextShimmerProps): react_jsx_runtime.JSX.Element;
|
|
208
|
+
|
|
195
209
|
interface Toast {
|
|
196
210
|
id: string;
|
|
197
211
|
title: string;
|
|
@@ -506,4 +520,4 @@ interface FilterFieldProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
|
506
520
|
}
|
|
507
521
|
declare const FilterField: React$1.ForwardRefExoticComponent<FilterFieldProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
508
522
|
|
|
509
|
-
export { Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, FilterField, type FilterFieldProps, InlineCode, type InlineCodeProps, Input, type InputProps, Label, Metric, type MetricProps, MetricStrip, type MetricStripProps, PageHeader, type PageHeaderProps, Progress, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, Textarea, type TextareaProps, ThemeToggle, type Toast, ToastContainer, ToastProvider, Toolbar, type ToolbarProps, type UploadFile, UploadProgress, type UploadProgressProps, badgeVariants, useTheme, useToast };
|
|
523
|
+
export { Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, FilterField, type FilterFieldProps, InlineCode, type InlineCodeProps, Input, type InputProps, Label, Metric, type MetricProps, MetricStrip, type MetricStripProps, PageHeader, type PageHeaderProps, Progress, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, type Toast, ToastContainer, ToastProvider, Toolbar, type ToolbarProps, type UploadFile, UploadProgress, type UploadProgressProps, badgeVariants, useTheme, useToast };
|
package/dist/primitives.js
CHANGED
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
UploadProgress,
|
|
51
51
|
useTheme,
|
|
52
52
|
useToast
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-LDLOJKPC.js";
|
|
54
54
|
import {
|
|
55
55
|
Avatar,
|
|
56
56
|
AvatarFallback,
|
|
@@ -71,6 +71,9 @@ import {
|
|
|
71
71
|
DropdownMenuSubTrigger,
|
|
72
72
|
DropdownMenuTrigger
|
|
73
73
|
} from "./chunk-34A66VBG.js";
|
|
74
|
+
import {
|
|
75
|
+
TextShimmer
|
|
76
|
+
} from "./chunk-L57WRIND.js";
|
|
74
77
|
import {
|
|
75
78
|
Badge,
|
|
76
79
|
Card,
|
|
@@ -194,6 +197,7 @@ export {
|
|
|
194
197
|
TerminalDisplay,
|
|
195
198
|
TerminalInput,
|
|
196
199
|
TerminalLine,
|
|
200
|
+
TextShimmer,
|
|
197
201
|
Textarea,
|
|
198
202
|
ThemeToggle,
|
|
199
203
|
ToastContainer,
|
package/dist/run.d.ts
CHANGED
|
@@ -30,28 +30,31 @@ declare const RunGroup: React.MemoExoticComponent<({ run, partMap, collapsed, on
|
|
|
30
30
|
|
|
31
31
|
type RunRowStatus = "running" | "success" | "error" | "idle";
|
|
32
32
|
/**
|
|
33
|
-
* Trailing status indicator shared by every run row
|
|
34
|
-
* a
|
|
35
|
-
* —
|
|
33
|
+
* Trailing status indicator shared by every run row. Only `error` draws a
|
|
34
|
+
* mark (a red dot). Success is silence, and a running row carries its state in
|
|
35
|
+
* the title — a `TextShimmer` sweep — so neither renders anything here.
|
|
36
36
|
*/
|
|
37
37
|
declare function RunRowStatusDot({ status }: {
|
|
38
38
|
status: RunRowStatus;
|
|
39
39
|
}): react_jsx_runtime.JSX.Element | null;
|
|
40
40
|
interface RunRowShellProps {
|
|
41
|
-
/** Semantic lead glyph
|
|
41
|
+
/** Semantic lead glyph (14px). At rest it is the row's only ornament; on
|
|
42
|
+
* hover and while open the expand chevron takes its slot. */
|
|
42
43
|
icon: ReactNode;
|
|
43
44
|
/** Row title. A string in the common case; a node when the title carries its
|
|
44
|
-
* own treatment
|
|
45
|
-
* the shell
|
|
45
|
+
* own treatment — a running row passes `<TextShimmer>` here, which is the
|
|
46
|
+
* whole in-flight signal (the shell draws no spinner). */
|
|
46
47
|
title: ReactNode;
|
|
47
48
|
/** Secondary inline text (tool path/command, or a reasoning preview). */
|
|
48
49
|
description?: string;
|
|
49
50
|
/** Render the description in mono (tools) vs prose (reasoning). */
|
|
50
51
|
descriptionMono?: boolean;
|
|
51
52
|
status?: RunRowStatus;
|
|
52
|
-
/**
|
|
53
|
+
/** @deprecated The shell no longer ticks a live duration while running; the
|
|
54
|
+
* running state lives in the title (`TextShimmer`). Accepted and ignored so
|
|
55
|
+
* existing callers keep compiling. */
|
|
53
56
|
startTime?: number;
|
|
54
|
-
/** Static duration
|
|
57
|
+
/** Static duration, revealed on hover once the row is no longer running. */
|
|
55
58
|
durationMs?: number;
|
|
56
59
|
/** Radius shaping when rows are stacked into a group. */
|
|
57
60
|
groupPosition?: "single" | "first" | "middle" | "last";
|
|
@@ -68,12 +71,13 @@ interface RunRowShellProps {
|
|
|
68
71
|
children?: ReactNode;
|
|
69
72
|
}
|
|
70
73
|
/**
|
|
71
|
-
* Shared shell for the agent activity rows (reasoning + tool).
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
74
|
+
* Shared shell for the agent activity rows (reasoning + tool). A quiet
|
|
75
|
+
* one-liner at rest — bare glyph, muted title and description, no fill, no
|
|
76
|
+
* border — that becomes a bordered card only while open. The border is always
|
|
77
|
+
* present (transparent at rest) so hover and expand never shift layout.
|
|
78
|
+
* Both row kinds render through it so they read as one family.
|
|
75
79
|
*/
|
|
76
|
-
declare function RunRowShell({ icon, title, description, descriptionMono, status,
|
|
80
|
+
declare function RunRowShell({ icon, title, description, descriptionMono, status, durationMs, groupPosition, collapsedError, actions, open: openProp, onOpenChange, defaultOpen, className, contentClassName, children, }: RunRowShellProps): react_jsx_runtime.JSX.Element;
|
|
77
81
|
|
|
78
82
|
interface InlineToolItemProps {
|
|
79
83
|
part: ToolPart;
|
|
@@ -88,10 +92,11 @@ interface InlineToolItemProps {
|
|
|
88
92
|
description?: string;
|
|
89
93
|
}
|
|
90
94
|
/**
|
|
91
|
-
* Compact single-line tool call display
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
+
* Compact single-line tool call display: a category glyph, the tool verb, and
|
|
96
|
+
* the path or command it acted on. While the call runs the verb shimmers;
|
|
97
|
+
* once it completes the row goes quiet (duration on hover, a red dot only on
|
|
98
|
+
* error). Expands on click to show ExpandedToolDetail. Rendered through the
|
|
99
|
+
* shared RunRowShell so it stays consistent with the reasoning row.
|
|
95
100
|
*/
|
|
96
101
|
declare const InlineToolItem: React.MemoExoticComponent<({ part, renderToolDetail, groupPosition, className, contentClassName, actions, title: titleOverride, description: descriptionOverride, }: InlineToolItemProps) => react_jsx_runtime.JSX.Element>;
|
|
97
102
|
|
package/dist/run.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
LiveDuration
|
|
3
|
+
} from "./chunk-LFVF2HFB.js";
|
|
2
4
|
import {
|
|
3
5
|
ToolCallFeed,
|
|
4
6
|
parseToolEvent
|
|
5
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-6RIX7M27.js";
|
|
6
8
|
import {
|
|
7
9
|
InlineThinkingItem,
|
|
8
10
|
RunGroup
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-CVX53NCC.js";
|
|
10
12
|
import {
|
|
11
13
|
ExpandedToolDetail,
|
|
12
14
|
InlineToolItem,
|
|
13
|
-
LiveDuration,
|
|
14
15
|
RunRowShell,
|
|
15
16
|
RunRowStatusDot
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-XT4JMYVB.js";
|
|
18
|
+
import "./chunk-EIUE5GV2.js";
|
|
18
19
|
import "./chunk-AAUNOHVL.js";
|
|
20
|
+
import "./chunk-L57WRIND.js";
|
|
19
21
|
import "./chunk-3M7BPSSW.js";
|
|
20
22
|
import "./chunk-GYPQXTJU.js";
|
|
21
23
|
import "./chunk-MKTSMWVD.js";
|
package/dist/sdk-hooks.js
CHANGED
|
@@ -5,17 +5,18 @@ import {
|
|
|
5
5
|
useSSEStream,
|
|
6
6
|
useSdkSession,
|
|
7
7
|
useToolCallStream
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-4ENFLPWQ.js";
|
|
9
9
|
import "./chunk-OEX7NZE3.js";
|
|
10
10
|
import {
|
|
11
11
|
useAutoScroll,
|
|
12
12
|
useRunCollapseState,
|
|
13
13
|
useRunGroups
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-UYTRNR7Z.js";
|
|
15
|
+
import "./chunk-6RIX7M27.js";
|
|
16
|
+
import "./chunk-XT4JMYVB.js";
|
|
17
|
+
import "./chunk-EIUE5GV2.js";
|
|
18
18
|
import "./chunk-AAUNOHVL.js";
|
|
19
|
+
import "./chunk-L57WRIND.js";
|
|
19
20
|
import "./chunk-ZRVH3WCA.js";
|
|
20
21
|
import "./chunk-P5F43A65.js";
|
|
21
22
|
import "./chunk-WUQDUBJG.js";
|
package/dist/utils.d.ts
CHANGED
|
@@ -36,6 +36,12 @@ declare function timeAgo(ts: number): string;
|
|
|
36
36
|
|
|
37
37
|
declare const TOOL_CATEGORY_ICONS: Record<ToolCategory, string>;
|
|
38
38
|
declare function getToolCategory(toolName: string): ToolCategory;
|
|
39
|
+
/**
|
|
40
|
+
* Title is the bare verb ("Read", "Edit", "Shell"); the path, command, pattern
|
|
41
|
+
* or query lives in `description` only, so a row prints its subject once.
|
|
42
|
+
* `targetPath` / `commandSnippet` carry the untruncated value for consumers
|
|
43
|
+
* that need it (diff headers, expanded detail).
|
|
44
|
+
*/
|
|
39
45
|
declare function getToolDisplayMetadata(part: ToolPart): ToolDisplayMetadata;
|
|
40
46
|
/** Extract error text from a tool part, if any. */
|
|
41
47
|
declare function getToolErrorText(part: ToolPart, fallback?: string): string | undefined;
|
package/dist/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -3,6 +3,9 @@ import { useState } from 'react'
|
|
|
3
3
|
import { Code, FileText } from 'lucide-react'
|
|
4
4
|
import { AgentTimeline } from './agent-timeline'
|
|
5
5
|
import type { AgentTimelineItem } from './agent-timeline'
|
|
6
|
+
import { ChatContainer } from './chat-container'
|
|
7
|
+
import type { SessionMessage } from '../types/message'
|
|
8
|
+
import type { SessionPart } from '../types/parts'
|
|
6
9
|
|
|
7
10
|
const meta: Meta<typeof AgentTimeline> = {
|
|
8
11
|
title: 'Chat/AgentTimeline',
|
|
@@ -52,8 +55,9 @@ const codingSession: AgentTimelineItem[] = [
|
|
|
52
55
|
call: {
|
|
53
56
|
id: 'tc-1',
|
|
54
57
|
type: 'glob',
|
|
55
|
-
label: 'Find
|
|
58
|
+
label: 'Find',
|
|
56
59
|
status: 'success',
|
|
60
|
+
detail: 'src/**/*.ts',
|
|
57
61
|
output:
|
|
58
62
|
'src/index.ts\nsrc/types.ts\nsrc/utils/format.ts\nsrc/utils/parse.ts',
|
|
59
63
|
duration: 18,
|
|
@@ -65,8 +69,9 @@ const codingSession: AgentTimelineItem[] = [
|
|
|
65
69
|
call: {
|
|
66
70
|
id: 'tc-2',
|
|
67
71
|
type: 'read',
|
|
68
|
-
label: 'Read
|
|
72
|
+
label: 'Read',
|
|
69
73
|
status: 'success',
|
|
74
|
+
detail: 'src/types.ts',
|
|
70
75
|
output:
|
|
71
76
|
'// Existing types\nexport type Maybe<T> = T | null | undefined\nexport type Nullable<T> = T | null',
|
|
72
77
|
duration: 31,
|
|
@@ -86,8 +91,9 @@ const codingSession: AgentTimelineItem[] = [
|
|
|
86
91
|
call: {
|
|
87
92
|
id: 'tc-3',
|
|
88
93
|
type: 'write',
|
|
89
|
-
label: 'Write
|
|
94
|
+
label: 'Write',
|
|
90
95
|
status: 'success',
|
|
96
|
+
detail: 'src/types.ts',
|
|
91
97
|
output: 'File written — 47 lines added.',
|
|
92
98
|
duration: 22,
|
|
93
99
|
},
|
|
@@ -98,7 +104,7 @@ const codingSession: AgentTimelineItem[] = [
|
|
|
98
104
|
call: {
|
|
99
105
|
id: 'tc-4',
|
|
100
106
|
type: 'bash',
|
|
101
|
-
label: '
|
|
107
|
+
label: 'Shell',
|
|
102
108
|
status: 'success',
|
|
103
109
|
detail: 'npx tsc --noEmit --strict',
|
|
104
110
|
output: '✓ No type errors',
|
|
@@ -201,8 +207,9 @@ export const WhileThinking: Story = {
|
|
|
201
207
|
call: {
|
|
202
208
|
id: 'tc-1',
|
|
203
209
|
type: 'glob',
|
|
204
|
-
label: 'Find
|
|
210
|
+
label: 'Find',
|
|
205
211
|
status: 'success',
|
|
212
|
+
detail: 'src/**/*.ts',
|
|
206
213
|
duration: 14,
|
|
207
214
|
},
|
|
208
215
|
},
|
|
@@ -234,24 +241,27 @@ export const WithToolGroup: Story = {
|
|
|
234
241
|
{
|
|
235
242
|
id: 'tc-1',
|
|
236
243
|
type: 'read',
|
|
237
|
-
label: 'Read
|
|
244
|
+
label: 'Read',
|
|
238
245
|
status: 'success',
|
|
246
|
+
detail: 'src/routes/users.ts',
|
|
239
247
|
output: "router.get('/', authMiddleware, listUsers)\nrouter.post('/', authMiddleware, createUser)",
|
|
240
248
|
duration: 24,
|
|
241
249
|
},
|
|
242
250
|
{
|
|
243
251
|
id: 'tc-2',
|
|
244
252
|
type: 'read',
|
|
245
|
-
label: 'Read
|
|
253
|
+
label: 'Read',
|
|
246
254
|
status: 'success',
|
|
255
|
+
detail: 'src/routes/sessions.ts',
|
|
247
256
|
output: "router.get('/', listSessions) // missing auth!\nrouter.delete('/:id', authMiddleware, deleteSession)",
|
|
248
257
|
duration: 19,
|
|
249
258
|
},
|
|
250
259
|
{
|
|
251
260
|
id: 'tc-3',
|
|
252
261
|
type: 'read',
|
|
253
|
-
label: 'Read
|
|
262
|
+
label: 'Read',
|
|
254
263
|
status: 'success',
|
|
264
|
+
detail: 'src/routes/health.ts',
|
|
255
265
|
output: "router.get('/', healthCheck) // intentionally public",
|
|
256
266
|
duration: 11,
|
|
257
267
|
},
|
|
@@ -305,7 +315,7 @@ export const WithError: Story = {
|
|
|
305
315
|
call: {
|
|
306
316
|
id: 'tc-1',
|
|
307
317
|
type: 'bash',
|
|
308
|
-
label: '
|
|
318
|
+
label: 'Shell',
|
|
309
319
|
status: 'error',
|
|
310
320
|
detail: 'pnpm test --run',
|
|
311
321
|
output:
|
|
@@ -351,8 +361,9 @@ export const WithArtifact: Story = {
|
|
|
351
361
|
call: {
|
|
352
362
|
id: 'tc-1',
|
|
353
363
|
type: 'write',
|
|
354
|
-
label: 'Write
|
|
364
|
+
label: 'Write',
|
|
355
365
|
status: 'success',
|
|
366
|
+
detail: 'openapi.yaml',
|
|
356
367
|
output: '187 lines written.',
|
|
357
368
|
duration: 44,
|
|
358
369
|
},
|
|
@@ -438,3 +449,145 @@ export const StatusTones: Story = {
|
|
|
438
449
|
],
|
|
439
450
|
},
|
|
440
451
|
}
|
|
452
|
+
|
|
453
|
+
// ---------------------------------------------------------------------------
|
|
454
|
+
// Full transcript through ChatContainer — the real consumer path. Tool titles
|
|
455
|
+
// and descriptions come from `getToolDisplayMetadata`, so this story shows the
|
|
456
|
+
// row grammar a product sees (not hand-written labels): prose, reasoning, a
|
|
457
|
+
// tool sequence, a running row, an error row, and a streaming reply.
|
|
458
|
+
// ---------------------------------------------------------------------------
|
|
459
|
+
|
|
460
|
+
const transcriptMessages: SessionMessage[] = [
|
|
461
|
+
{ id: 'u-1', role: 'user', time: { created: NOW - 240_000 } },
|
|
462
|
+
{ id: 'a-1', role: 'assistant', time: { created: NOW - 230_000 } },
|
|
463
|
+
{ id: 'u-2', role: 'user', time: { created: NOW - 60_000 } },
|
|
464
|
+
{ id: 'a-2', role: 'assistant', time: { created: NOW - 50_000 } },
|
|
465
|
+
]
|
|
466
|
+
|
|
467
|
+
const transcriptParts: Record<string, SessionPart[]> = {
|
|
468
|
+
'u-1': [
|
|
469
|
+
{
|
|
470
|
+
type: 'text',
|
|
471
|
+
text: 'The retry loop in `src/batch-writer.ts` hammers the API when the token expires. Add jittered backoff and make sure the tests cover it.',
|
|
472
|
+
},
|
|
473
|
+
],
|
|
474
|
+
'a-1': [
|
|
475
|
+
{
|
|
476
|
+
type: 'reasoning',
|
|
477
|
+
text: 'The loop retries immediately on 401. I should read the writer, find where the delay is computed, add exponential backoff with jitter, and extend the existing test.',
|
|
478
|
+
time: { start: NOW - 229_000, end: NOW - 226_000 },
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
type: 'tool',
|
|
482
|
+
id: 't-1',
|
|
483
|
+
tool: 'read',
|
|
484
|
+
state: {
|
|
485
|
+
status: 'completed',
|
|
486
|
+
input: { file_path: 'src/batch-writer.ts' },
|
|
487
|
+
output: 'export async function flush(batch: Row[]) {\n for (let attempt = 0; attempt < 5; attempt++) {\n try { return await post(batch) } catch (err) { /* retry */ }\n }\n}',
|
|
488
|
+
time: { start: NOW - 225_000, end: NOW - 224_960 },
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
type: 'tool',
|
|
493
|
+
id: 't-2',
|
|
494
|
+
tool: 'grep',
|
|
495
|
+
state: {
|
|
496
|
+
status: 'completed',
|
|
497
|
+
input: { pattern: 'flush\\(', path: 'src/' },
|
|
498
|
+
output: 'src/batch-writer.ts:12\nsrc/batch-writer.test.ts:8\nsrc/batch-writer.test.ts:31',
|
|
499
|
+
time: { start: NOW - 224_000, end: NOW - 223_970 },
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
type: 'tool',
|
|
504
|
+
id: 't-3',
|
|
505
|
+
tool: 'edit',
|
|
506
|
+
state: {
|
|
507
|
+
status: 'completed',
|
|
508
|
+
input: {
|
|
509
|
+
file_path: 'src/batch-writer.ts',
|
|
510
|
+
old_string: '} catch (err) { /* retry */ }',
|
|
511
|
+
new_string: '} catch (err) {\n await sleep(backoff(attempt))\n }',
|
|
512
|
+
},
|
|
513
|
+
output: 'Applied 1 edit',
|
|
514
|
+
time: { start: NOW - 223_000, end: NOW - 222_980 },
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
type: 'tool',
|
|
519
|
+
id: 't-4',
|
|
520
|
+
tool: 'bash',
|
|
521
|
+
state: {
|
|
522
|
+
status: 'completed',
|
|
523
|
+
input: { command: 'pnpm vitest run src/batch-writer.test.ts' },
|
|
524
|
+
output: ' ✓ src/batch-writer.test.ts (3)\n\nTest Files 1 passed (1)\n Tests 3 passed (3)',
|
|
525
|
+
time: { start: NOW - 222_000, end: NOW - 219_600 },
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
type: 'text',
|
|
530
|
+
text: 'Added `backoff(attempt)` — exponential from 200ms with ±25% jitter, capped at 5s — and the writer now waits before each retry. The existing three tests still pass.',
|
|
531
|
+
},
|
|
532
|
+
],
|
|
533
|
+
'u-2': [
|
|
534
|
+
{
|
|
535
|
+
type: 'text',
|
|
536
|
+
text: 'Now add a test that proves the jitter actually spreads the retries.',
|
|
537
|
+
},
|
|
538
|
+
],
|
|
539
|
+
'a-2': [
|
|
540
|
+
{
|
|
541
|
+
type: 'tool',
|
|
542
|
+
id: 't-5',
|
|
543
|
+
tool: 'write',
|
|
544
|
+
state: {
|
|
545
|
+
status: 'completed',
|
|
546
|
+
input: {
|
|
547
|
+
file_path: 'src/batch-writer.jitter.test.ts',
|
|
548
|
+
content: "import { backoff } from './batch-writer'\n\ntest('jitter spreads retries', () => {\n const delays = new Set(Array.from({ length: 50 }, () => backoff(2)))\n expect(delays.size).toBeGreaterThan(10)\n})",
|
|
549
|
+
},
|
|
550
|
+
output: 'File written',
|
|
551
|
+
time: { start: NOW - 49_000, end: NOW - 48_970 },
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
type: 'tool',
|
|
556
|
+
id: 't-6',
|
|
557
|
+
tool: 'bash',
|
|
558
|
+
state: {
|
|
559
|
+
status: 'error',
|
|
560
|
+
input: { command: 'pnpm vitest run src/batch-writer.jitter.test.ts' },
|
|
561
|
+
error: "Cannot find module './batch-writer' — did you mean './batch-writer.ts'? (resolve.extensions does not include .ts in this config)",
|
|
562
|
+
time: { start: NOW - 48_000, end: NOW - 46_800 },
|
|
563
|
+
},
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
type: 'tool',
|
|
567
|
+
id: 't-7',
|
|
568
|
+
tool: 'bash',
|
|
569
|
+
state: {
|
|
570
|
+
status: 'running',
|
|
571
|
+
input: { command: 'pnpm vitest run src/batch-writer.jitter.test.ts --config vitest.config.ts' },
|
|
572
|
+
time: { start: NOW - 3_000 },
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
type: 'text',
|
|
577
|
+
text: 'The first run failed on module resolution — the test runner was picking up the root config. Re-running with the package config',
|
|
578
|
+
},
|
|
579
|
+
],
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export const FullTranscript: Story = {
|
|
583
|
+
render: () => (
|
|
584
|
+
<div className="h-screen">
|
|
585
|
+
<ChatContainer
|
|
586
|
+
presentation="timeline"
|
|
587
|
+
messages={transcriptMessages}
|
|
588
|
+
partMap={transcriptParts}
|
|
589
|
+
isStreaming
|
|
590
|
+
/>
|
|
591
|
+
</div>
|
|
592
|
+
),
|
|
593
|
+
}
|