@sandbox-agent/react 0.3.1 → 0.4.0-rc.1
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.d.ts +184 -3
- package/dist/index.js +802 -17
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,180 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { RefObject, ReactNode, KeyboardEvent, Ref, TextareaHTMLAttributes, CSSProperties } from 'react';
|
|
3
4
|
import { SandboxAgent, TerminalExitStatus, TerminalErrorStatus } from 'sandbox-agent';
|
|
5
|
+
import * as _tanstack_react_virtual from '@tanstack/react-virtual';
|
|
6
|
+
|
|
7
|
+
type PermissionReply = "once" | "always" | "reject";
|
|
8
|
+
type PermissionOption = {
|
|
9
|
+
optionId: string;
|
|
10
|
+
name: string;
|
|
11
|
+
kind: string;
|
|
12
|
+
};
|
|
13
|
+
type TranscriptEntry = {
|
|
14
|
+
id: string;
|
|
15
|
+
eventId?: string;
|
|
16
|
+
kind: "message" | "tool" | "meta" | "reasoning" | "permission";
|
|
17
|
+
time: string;
|
|
18
|
+
role?: "user" | "assistant";
|
|
19
|
+
text?: string;
|
|
20
|
+
toolName?: string;
|
|
21
|
+
toolInput?: string;
|
|
22
|
+
toolOutput?: string;
|
|
23
|
+
toolStatus?: string;
|
|
24
|
+
reasoning?: {
|
|
25
|
+
text: string;
|
|
26
|
+
visibility?: string;
|
|
27
|
+
};
|
|
28
|
+
meta?: {
|
|
29
|
+
title: string;
|
|
30
|
+
detail?: string;
|
|
31
|
+
severity?: "info" | "error";
|
|
32
|
+
};
|
|
33
|
+
permission?: {
|
|
34
|
+
permissionId: string;
|
|
35
|
+
title: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
options: PermissionOption[];
|
|
38
|
+
resolved?: boolean;
|
|
39
|
+
selectedOptionId?: string;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
interface AgentTranscriptClassNames {
|
|
43
|
+
root: string;
|
|
44
|
+
divider: string;
|
|
45
|
+
dividerLine: string;
|
|
46
|
+
dividerText: string;
|
|
47
|
+
message: string;
|
|
48
|
+
messageContent: string;
|
|
49
|
+
messageText: string;
|
|
50
|
+
error: string;
|
|
51
|
+
toolGroupSingle: string;
|
|
52
|
+
toolGroupContainer: string;
|
|
53
|
+
toolGroupHeader: string;
|
|
54
|
+
toolGroupIcon: string;
|
|
55
|
+
toolGroupLabel: string;
|
|
56
|
+
toolGroupChevron: string;
|
|
57
|
+
toolGroupBody: string;
|
|
58
|
+
toolItem: string;
|
|
59
|
+
toolItemConnector: string;
|
|
60
|
+
toolItemDot: string;
|
|
61
|
+
toolItemLine: string;
|
|
62
|
+
toolItemContent: string;
|
|
63
|
+
toolItemHeader: string;
|
|
64
|
+
toolItemIcon: string;
|
|
65
|
+
toolItemLabel: string;
|
|
66
|
+
toolItemSpinner: string;
|
|
67
|
+
toolItemLink: string;
|
|
68
|
+
toolItemChevron: string;
|
|
69
|
+
toolItemBody: string;
|
|
70
|
+
toolSection: string;
|
|
71
|
+
toolSectionTitle: string;
|
|
72
|
+
toolCode: string;
|
|
73
|
+
toolCodeMuted: string;
|
|
74
|
+
permissionPrompt: string;
|
|
75
|
+
permissionHeader: string;
|
|
76
|
+
permissionIcon: string;
|
|
77
|
+
permissionTitle: string;
|
|
78
|
+
permissionDescription: string;
|
|
79
|
+
permissionActions: string;
|
|
80
|
+
permissionButton: string;
|
|
81
|
+
permissionAutoResolved: string;
|
|
82
|
+
thinkingRow: string;
|
|
83
|
+
thinkingAvatar: string;
|
|
84
|
+
thinkingAvatarImage: string;
|
|
85
|
+
thinkingAvatarLabel: string;
|
|
86
|
+
thinkingIndicator: string;
|
|
87
|
+
thinkingDot: string;
|
|
88
|
+
endAnchor: string;
|
|
89
|
+
}
|
|
90
|
+
interface PermissionOptionRenderContext {
|
|
91
|
+
entry: TranscriptEntry;
|
|
92
|
+
option: PermissionOption;
|
|
93
|
+
label: string;
|
|
94
|
+
reply: PermissionReply;
|
|
95
|
+
selected: boolean;
|
|
96
|
+
dimmed: boolean;
|
|
97
|
+
resolved: boolean;
|
|
98
|
+
}
|
|
99
|
+
interface AgentTranscriptProps {
|
|
100
|
+
entries: TranscriptEntry[];
|
|
101
|
+
className?: string;
|
|
102
|
+
classNames?: Partial<AgentTranscriptClassNames>;
|
|
103
|
+
endRef?: RefObject<HTMLDivElement>;
|
|
104
|
+
scrollRef?: RefObject<HTMLDivElement>;
|
|
105
|
+
scrollToEntryId?: string | null;
|
|
106
|
+
sessionError?: string | null;
|
|
107
|
+
eventError?: string | null;
|
|
108
|
+
isThinking?: boolean;
|
|
109
|
+
agentId?: string;
|
|
110
|
+
virtualize?: boolean;
|
|
111
|
+
onAtBottomChange?: (atBottom: boolean) => void;
|
|
112
|
+
onEventClick?: (eventId: string) => void;
|
|
113
|
+
onPermissionReply?: (permissionId: string, reply: PermissionReply) => void;
|
|
114
|
+
isDividerEntry?: (entry: TranscriptEntry) => boolean;
|
|
115
|
+
canOpenEvent?: (entry: TranscriptEntry) => boolean;
|
|
116
|
+
getToolGroupSummary?: (entries: TranscriptEntry[]) => string;
|
|
117
|
+
renderMessageText?: (entry: TranscriptEntry) => ReactNode;
|
|
118
|
+
renderInlinePendingIndicator?: () => ReactNode;
|
|
119
|
+
renderThinkingState?: (context: {
|
|
120
|
+
agentId?: string;
|
|
121
|
+
}) => ReactNode;
|
|
122
|
+
renderToolItemIcon?: (entry: TranscriptEntry) => ReactNode;
|
|
123
|
+
renderToolGroupIcon?: (entries: TranscriptEntry[], expanded: boolean) => ReactNode;
|
|
124
|
+
renderChevron?: (expanded: boolean) => ReactNode;
|
|
125
|
+
renderEventLinkContent?: (entry: TranscriptEntry) => ReactNode;
|
|
126
|
+
renderPermissionIcon?: (entry: TranscriptEntry) => ReactNode;
|
|
127
|
+
renderPermissionOptionContent?: (context: PermissionOptionRenderContext) => ReactNode;
|
|
128
|
+
}
|
|
129
|
+
declare const AgentTranscript: ({ entries, className, classNames: classNameOverrides, endRef, scrollRef, scrollToEntryId, sessionError, eventError, isThinking, agentId, virtualize, onAtBottomChange, onEventClick, onPermissionReply, isDividerEntry, canOpenEvent, getToolGroupSummary, renderMessageText, renderInlinePendingIndicator, renderThinkingState, renderToolItemIcon, renderToolGroupIcon, renderChevron, renderEventLinkContent, renderPermissionIcon, renderPermissionOptionContent, }: AgentTranscriptProps) => react_jsx_runtime.JSX.Element;
|
|
130
|
+
|
|
131
|
+
interface ChatComposerClassNames {
|
|
132
|
+
root: string;
|
|
133
|
+
form: string;
|
|
134
|
+
input: string;
|
|
135
|
+
submit: string;
|
|
136
|
+
submitContent: string;
|
|
137
|
+
}
|
|
138
|
+
interface ChatComposerProps {
|
|
139
|
+
message: string;
|
|
140
|
+
onMessageChange: (value: string) => void;
|
|
141
|
+
onSubmit: () => void;
|
|
142
|
+
onKeyDown?: (event: KeyboardEvent<HTMLTextAreaElement>) => void;
|
|
143
|
+
placeholder?: string;
|
|
144
|
+
disabled?: boolean;
|
|
145
|
+
submitDisabled?: boolean;
|
|
146
|
+
allowEmptySubmit?: boolean;
|
|
147
|
+
submitLabel?: string;
|
|
148
|
+
className?: string;
|
|
149
|
+
classNames?: Partial<ChatComposerClassNames>;
|
|
150
|
+
inputRef?: Ref<HTMLTextAreaElement>;
|
|
151
|
+
rows?: number;
|
|
152
|
+
textareaProps?: Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, "className" | "disabled" | "onChange" | "onKeyDown" | "placeholder" | "rows" | "value">;
|
|
153
|
+
renderSubmitContent?: () => ReactNode;
|
|
154
|
+
renderFooter?: () => ReactNode;
|
|
155
|
+
}
|
|
156
|
+
declare const ChatComposer: ({ message, onMessageChange, onSubmit, onKeyDown, placeholder, disabled, submitDisabled, allowEmptySubmit, submitLabel, className, classNames: classNameOverrides, inputRef, rows, textareaProps, renderSubmitContent, renderFooter, }: ChatComposerProps) => react_jsx_runtime.JSX.Element;
|
|
157
|
+
|
|
158
|
+
interface AgentConversationClassNames {
|
|
159
|
+
root: string;
|
|
160
|
+
transcript: string;
|
|
161
|
+
emptyState: string;
|
|
162
|
+
composer: string;
|
|
163
|
+
}
|
|
164
|
+
interface AgentConversationProps {
|
|
165
|
+
entries: TranscriptEntry[];
|
|
166
|
+
className?: string;
|
|
167
|
+
classNames?: Partial<AgentConversationClassNames>;
|
|
168
|
+
emptyState?: ReactNode;
|
|
169
|
+
transcriptClassName?: string;
|
|
170
|
+
transcriptClassNames?: Partial<AgentTranscriptClassNames>;
|
|
171
|
+
scrollRef?: RefObject<HTMLDivElement>;
|
|
172
|
+
composerClassName?: string;
|
|
173
|
+
composerClassNames?: Partial<ChatComposerClassNames>;
|
|
174
|
+
transcriptProps?: Omit<AgentTranscriptProps, "entries" | "className" | "classNames" | "scrollRef">;
|
|
175
|
+
composerProps?: Omit<ChatComposerProps, "className" | "classNames">;
|
|
176
|
+
}
|
|
177
|
+
declare const AgentConversation: ({ entries, className, classNames: classNameOverrides, emptyState, transcriptClassName, transcriptClassNames, scrollRef, composerClassName, composerClassNames, transcriptProps, composerProps, }: AgentConversationProps) => react_jsx_runtime.JSX.Element;
|
|
4
178
|
|
|
5
179
|
type ProcessTerminalClient = Pick<SandboxAgent, "connectProcessTerminal">;
|
|
6
180
|
interface ProcessTerminalProps {
|
|
@@ -9,10 +183,17 @@ interface ProcessTerminalProps {
|
|
|
9
183
|
className?: string;
|
|
10
184
|
style?: CSSProperties;
|
|
11
185
|
terminalStyle?: CSSProperties;
|
|
186
|
+
statusBarStyleOverride?: CSSProperties;
|
|
12
187
|
height?: number | string;
|
|
188
|
+
showStatusBar?: boolean;
|
|
13
189
|
onExit?: (status: TerminalExitStatus) => void;
|
|
14
190
|
onError?: (error: TerminalErrorStatus | Error) => void;
|
|
15
191
|
}
|
|
16
|
-
declare const ProcessTerminal: ({ client, processId, className, style, terminalStyle, height, onExit, onError, }: ProcessTerminalProps) => react_jsx_runtime.JSX.Element;
|
|
192
|
+
declare const ProcessTerminal: ({ client, processId, className, style, terminalStyle, statusBarStyleOverride, height, showStatusBar, onExit, onError, }: ProcessTerminalProps) => react_jsx_runtime.JSX.Element;
|
|
193
|
+
|
|
194
|
+
declare function useTranscriptVirtualizer<T>(items: T[], scrollElementRef?: RefObject<HTMLDivElement>, onAtBottomChange?: (atBottom: boolean) => void): {
|
|
195
|
+
virtualizer: _tanstack_react_virtual.Virtualizer<HTMLDivElement, Element>;
|
|
196
|
+
isFollowingRef: react.MutableRefObject<boolean>;
|
|
197
|
+
};
|
|
17
198
|
|
|
18
|
-
export { ProcessTerminal, type ProcessTerminalClient, type ProcessTerminalProps };
|
|
199
|
+
export { AgentConversation, type AgentConversationClassNames, type AgentConversationProps, AgentTranscript, type AgentTranscriptClassNames, type AgentTranscriptProps, ChatComposer, type ChatComposerClassNames, type ChatComposerProps, type PermissionOption, type PermissionOptionRenderContext, type PermissionReply, ProcessTerminal, type ProcessTerminalClient, type ProcessTerminalProps, type TranscriptEntry, useTranscriptVirtualizer };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,787 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import { useEffect, useRef, useState } from "react";
|
|
1
|
+
// src/AgentTranscript.tsx
|
|
2
|
+
import { useEffect as useEffect2, useMemo, useRef as useRef2, useState } from "react";
|
|
3
|
+
|
|
4
|
+
// src/useTranscriptVirtualizer.ts
|
|
5
|
+
import { useEffect, useRef } from "react";
|
|
6
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
7
|
+
function useTranscriptVirtualizer(items, scrollElementRef, onAtBottomChange) {
|
|
8
|
+
const isFollowingRef = useRef(true);
|
|
9
|
+
const virtualizer = useVirtualizer({
|
|
10
|
+
count: items.length,
|
|
11
|
+
getScrollElement: () => scrollElementRef?.current ?? null,
|
|
12
|
+
estimateSize: () => 80,
|
|
13
|
+
measureElement: (element) => element.getBoundingClientRect().height,
|
|
14
|
+
overscan: 10
|
|
15
|
+
});
|
|
16
|
+
virtualizer.shouldAdjustScrollPositionOnItemSizeChange = () => isFollowingRef.current;
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const scrollElement = scrollElementRef?.current;
|
|
19
|
+
if (!scrollElement) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const updateFollowState = () => {
|
|
23
|
+
const atBottom = scrollElement.scrollHeight - scrollElement.scrollTop - scrollElement.clientHeight < 50;
|
|
24
|
+
isFollowingRef.current = atBottom;
|
|
25
|
+
onAtBottomChange?.(atBottom);
|
|
26
|
+
};
|
|
27
|
+
updateFollowState();
|
|
28
|
+
scrollElement.addEventListener("scroll", updateFollowState, { passive: true });
|
|
29
|
+
return () => {
|
|
30
|
+
scrollElement.removeEventListener("scroll", updateFollowState);
|
|
31
|
+
};
|
|
32
|
+
}, [onAtBottomChange, scrollElementRef]);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!isFollowingRef.current || items.length === 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const frameId = requestAnimationFrame(() => {
|
|
38
|
+
virtualizer.scrollToIndex(items.length - 1, {
|
|
39
|
+
align: "end",
|
|
40
|
+
behavior: "smooth"
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
return () => {
|
|
44
|
+
cancelAnimationFrame(frameId);
|
|
45
|
+
};
|
|
46
|
+
}, [items.length, virtualizer]);
|
|
47
|
+
return { virtualizer, isFollowingRef };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/AgentTranscript.tsx
|
|
3
51
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
52
|
+
var VIRTUAL_GROUP_GAP_PX = 12;
|
|
53
|
+
var DEFAULT_CLASS_NAMES = {
|
|
54
|
+
root: "sa-agent-transcript",
|
|
55
|
+
divider: "sa-agent-transcript-divider",
|
|
56
|
+
dividerLine: "sa-agent-transcript-divider-line",
|
|
57
|
+
dividerText: "sa-agent-transcript-divider-text",
|
|
58
|
+
message: "sa-agent-transcript-message",
|
|
59
|
+
messageContent: "sa-agent-transcript-message-content",
|
|
60
|
+
messageText: "sa-agent-transcript-message-text",
|
|
61
|
+
error: "sa-agent-transcript-error",
|
|
62
|
+
toolGroupSingle: "sa-agent-transcript-tool-group-single",
|
|
63
|
+
toolGroupContainer: "sa-agent-transcript-tool-group",
|
|
64
|
+
toolGroupHeader: "sa-agent-transcript-tool-group-header",
|
|
65
|
+
toolGroupIcon: "sa-agent-transcript-tool-group-icon",
|
|
66
|
+
toolGroupLabel: "sa-agent-transcript-tool-group-label",
|
|
67
|
+
toolGroupChevron: "sa-agent-transcript-tool-group-chevron",
|
|
68
|
+
toolGroupBody: "sa-agent-transcript-tool-group-body",
|
|
69
|
+
toolItem: "sa-agent-transcript-tool-item",
|
|
70
|
+
toolItemConnector: "sa-agent-transcript-tool-item-connector",
|
|
71
|
+
toolItemDot: "sa-agent-transcript-tool-item-dot",
|
|
72
|
+
toolItemLine: "sa-agent-transcript-tool-item-line",
|
|
73
|
+
toolItemContent: "sa-agent-transcript-tool-item-content",
|
|
74
|
+
toolItemHeader: "sa-agent-transcript-tool-item-header",
|
|
75
|
+
toolItemIcon: "sa-agent-transcript-tool-item-icon",
|
|
76
|
+
toolItemLabel: "sa-agent-transcript-tool-item-label",
|
|
77
|
+
toolItemSpinner: "sa-agent-transcript-tool-item-spinner",
|
|
78
|
+
toolItemLink: "sa-agent-transcript-tool-item-link",
|
|
79
|
+
toolItemChevron: "sa-agent-transcript-tool-item-chevron",
|
|
80
|
+
toolItemBody: "sa-agent-transcript-tool-item-body",
|
|
81
|
+
toolSection: "sa-agent-transcript-tool-section",
|
|
82
|
+
toolSectionTitle: "sa-agent-transcript-tool-section-title",
|
|
83
|
+
toolCode: "sa-agent-transcript-tool-code",
|
|
84
|
+
toolCodeMuted: "sa-agent-transcript-tool-code-muted",
|
|
85
|
+
permissionPrompt: "sa-agent-transcript-permission-prompt",
|
|
86
|
+
permissionHeader: "sa-agent-transcript-permission-header",
|
|
87
|
+
permissionIcon: "sa-agent-transcript-permission-icon",
|
|
88
|
+
permissionTitle: "sa-agent-transcript-permission-title",
|
|
89
|
+
permissionDescription: "sa-agent-transcript-permission-description",
|
|
90
|
+
permissionActions: "sa-agent-transcript-permission-actions",
|
|
91
|
+
permissionButton: "sa-agent-transcript-permission-button",
|
|
92
|
+
permissionAutoResolved: "sa-agent-transcript-permission-auto-resolved",
|
|
93
|
+
thinkingRow: "sa-agent-transcript-thinking-row",
|
|
94
|
+
thinkingAvatar: "sa-agent-transcript-thinking-avatar",
|
|
95
|
+
thinkingAvatarImage: "sa-agent-transcript-thinking-avatar-image",
|
|
96
|
+
thinkingAvatarLabel: "sa-agent-transcript-thinking-avatar-label",
|
|
97
|
+
thinkingIndicator: "sa-agent-transcript-thinking-indicator",
|
|
98
|
+
thinkingDot: "sa-agent-transcript-thinking-dot",
|
|
99
|
+
endAnchor: "sa-agent-transcript-end"
|
|
100
|
+
};
|
|
101
|
+
var DEFAULT_DIVIDER_TITLES = /* @__PURE__ */ new Set(["Session Started", "Turn Started", "Turn Ended"]);
|
|
102
|
+
var cx = (...values) => values.filter(Boolean).join(" ");
|
|
103
|
+
var mergeClassNames = (defaults, overrides) => ({
|
|
104
|
+
root: cx(defaults.root, overrides?.root),
|
|
105
|
+
divider: cx(defaults.divider, overrides?.divider),
|
|
106
|
+
dividerLine: cx(defaults.dividerLine, overrides?.dividerLine),
|
|
107
|
+
dividerText: cx(defaults.dividerText, overrides?.dividerText),
|
|
108
|
+
message: cx(defaults.message, overrides?.message),
|
|
109
|
+
messageContent: cx(defaults.messageContent, overrides?.messageContent),
|
|
110
|
+
messageText: cx(defaults.messageText, overrides?.messageText),
|
|
111
|
+
error: cx(defaults.error, overrides?.error),
|
|
112
|
+
toolGroupSingle: cx(defaults.toolGroupSingle, overrides?.toolGroupSingle),
|
|
113
|
+
toolGroupContainer: cx(defaults.toolGroupContainer, overrides?.toolGroupContainer),
|
|
114
|
+
toolGroupHeader: cx(defaults.toolGroupHeader, overrides?.toolGroupHeader),
|
|
115
|
+
toolGroupIcon: cx(defaults.toolGroupIcon, overrides?.toolGroupIcon),
|
|
116
|
+
toolGroupLabel: cx(defaults.toolGroupLabel, overrides?.toolGroupLabel),
|
|
117
|
+
toolGroupChevron: cx(defaults.toolGroupChevron, overrides?.toolGroupChevron),
|
|
118
|
+
toolGroupBody: cx(defaults.toolGroupBody, overrides?.toolGroupBody),
|
|
119
|
+
toolItem: cx(defaults.toolItem, overrides?.toolItem),
|
|
120
|
+
toolItemConnector: cx(defaults.toolItemConnector, overrides?.toolItemConnector),
|
|
121
|
+
toolItemDot: cx(defaults.toolItemDot, overrides?.toolItemDot),
|
|
122
|
+
toolItemLine: cx(defaults.toolItemLine, overrides?.toolItemLine),
|
|
123
|
+
toolItemContent: cx(defaults.toolItemContent, overrides?.toolItemContent),
|
|
124
|
+
toolItemHeader: cx(defaults.toolItemHeader, overrides?.toolItemHeader),
|
|
125
|
+
toolItemIcon: cx(defaults.toolItemIcon, overrides?.toolItemIcon),
|
|
126
|
+
toolItemLabel: cx(defaults.toolItemLabel, overrides?.toolItemLabel),
|
|
127
|
+
toolItemSpinner: cx(defaults.toolItemSpinner, overrides?.toolItemSpinner),
|
|
128
|
+
toolItemLink: cx(defaults.toolItemLink, overrides?.toolItemLink),
|
|
129
|
+
toolItemChevron: cx(defaults.toolItemChevron, overrides?.toolItemChevron),
|
|
130
|
+
toolItemBody: cx(defaults.toolItemBody, overrides?.toolItemBody),
|
|
131
|
+
toolSection: cx(defaults.toolSection, overrides?.toolSection),
|
|
132
|
+
toolSectionTitle: cx(defaults.toolSectionTitle, overrides?.toolSectionTitle),
|
|
133
|
+
toolCode: cx(defaults.toolCode, overrides?.toolCode),
|
|
134
|
+
toolCodeMuted: cx(defaults.toolCodeMuted, overrides?.toolCodeMuted),
|
|
135
|
+
permissionPrompt: cx(defaults.permissionPrompt, overrides?.permissionPrompt),
|
|
136
|
+
permissionHeader: cx(defaults.permissionHeader, overrides?.permissionHeader),
|
|
137
|
+
permissionIcon: cx(defaults.permissionIcon, overrides?.permissionIcon),
|
|
138
|
+
permissionTitle: cx(defaults.permissionTitle, overrides?.permissionTitle),
|
|
139
|
+
permissionDescription: cx(defaults.permissionDescription, overrides?.permissionDescription),
|
|
140
|
+
permissionActions: cx(defaults.permissionActions, overrides?.permissionActions),
|
|
141
|
+
permissionButton: cx(defaults.permissionButton, overrides?.permissionButton),
|
|
142
|
+
permissionAutoResolved: cx(defaults.permissionAutoResolved, overrides?.permissionAutoResolved),
|
|
143
|
+
thinkingRow: cx(defaults.thinkingRow, overrides?.thinkingRow),
|
|
144
|
+
thinkingAvatar: cx(defaults.thinkingAvatar, overrides?.thinkingAvatar),
|
|
145
|
+
thinkingAvatarImage: cx(defaults.thinkingAvatarImage, overrides?.thinkingAvatarImage),
|
|
146
|
+
thinkingAvatarLabel: cx(defaults.thinkingAvatarLabel, overrides?.thinkingAvatarLabel),
|
|
147
|
+
thinkingIndicator: cx(defaults.thinkingIndicator, overrides?.thinkingIndicator),
|
|
148
|
+
thinkingDot: cx(defaults.thinkingDot, overrides?.thinkingDot),
|
|
149
|
+
endAnchor: cx(defaults.endAnchor, overrides?.endAnchor)
|
|
150
|
+
});
|
|
151
|
+
var getMessageVariant = (entry) => {
|
|
152
|
+
if (entry.kind === "tool") return "tool";
|
|
153
|
+
if (entry.kind === "meta") return entry.meta?.severity === "error" ? "error" : "system";
|
|
154
|
+
if (entry.kind === "reasoning") return "assistant";
|
|
155
|
+
if (entry.kind === "permission") return "system";
|
|
156
|
+
if (entry.role === "user") return "user";
|
|
157
|
+
return "assistant";
|
|
158
|
+
};
|
|
159
|
+
var getToolItemLabel = (entry) => {
|
|
160
|
+
if (entry.kind === "tool") {
|
|
161
|
+
const statusLabel = entry.toolStatus && entry.toolStatus !== "completed" ? ` (${entry.toolStatus.replaceAll("_", " ")})` : "";
|
|
162
|
+
return `${entry.toolName ?? "tool"}${statusLabel}`;
|
|
163
|
+
}
|
|
164
|
+
if (entry.kind === "reasoning") {
|
|
165
|
+
return `Reasoning${entry.reasoning?.visibility ? ` (${entry.reasoning.visibility})` : ""}`;
|
|
166
|
+
}
|
|
167
|
+
return entry.meta?.title ?? "Status";
|
|
168
|
+
};
|
|
169
|
+
var getDefaultToolItemIcon = (entry) => {
|
|
170
|
+
if (entry.kind === "tool") return "Tool";
|
|
171
|
+
if (entry.kind === "reasoning") return "Thought";
|
|
172
|
+
return entry.meta?.severity === "error" ? "Error" : "Info";
|
|
173
|
+
};
|
|
174
|
+
var getDefaultToolGroupSummary = (entries) => {
|
|
175
|
+
const count = entries.length;
|
|
176
|
+
return `${count} Event${count === 1 ? "" : "s"}`;
|
|
177
|
+
};
|
|
178
|
+
var getPermissionReplyForOption = (kind) => {
|
|
179
|
+
if (kind === "allow_once") return "once";
|
|
180
|
+
if (kind === "allow_always") return "always";
|
|
181
|
+
return "reject";
|
|
182
|
+
};
|
|
183
|
+
var getPermissionOptionLabel = (option) => {
|
|
184
|
+
if (option.name) return option.name;
|
|
185
|
+
if (option.kind === "allow_once") return "Allow Once";
|
|
186
|
+
if (option.kind === "allow_always") return "Always Allow";
|
|
187
|
+
if (option.kind === "reject_once") return "Reject";
|
|
188
|
+
if (option.kind === "reject_always") return "Reject Always";
|
|
189
|
+
return option.kind;
|
|
190
|
+
};
|
|
191
|
+
var getPermissionOptionTone = (kind) => kind.startsWith("allow") ? "allow" : "reject";
|
|
192
|
+
var defaultRenderMessageText = (entry) => entry.text;
|
|
193
|
+
var defaultRenderPendingIndicator = () => "...";
|
|
194
|
+
var defaultRenderChevron = (expanded) => expanded ? "\u25BE" : "\u25B8";
|
|
195
|
+
var defaultRenderEventLinkContent = () => "Open";
|
|
196
|
+
var defaultRenderPermissionIcon = () => "Permission";
|
|
197
|
+
var defaultRenderPermissionOptionContent = ({ label }) => label;
|
|
198
|
+
var defaultIsDividerEntry = (entry) => entry.kind === "meta" && DEFAULT_DIVIDER_TITLES.has(entry.meta?.title ?? "");
|
|
199
|
+
var defaultCanOpenEvent = (entry) => Boolean(entry.eventId);
|
|
200
|
+
var buildGroupedEntries = (entries, isDividerEntry) => {
|
|
201
|
+
const groupedEntries = [];
|
|
202
|
+
let currentToolGroup = [];
|
|
203
|
+
const flushToolGroup = () => {
|
|
204
|
+
if (currentToolGroup.length === 0) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
groupedEntries.push({ type: "tool-group", entries: currentToolGroup });
|
|
208
|
+
currentToolGroup = [];
|
|
209
|
+
};
|
|
210
|
+
for (const entry of entries) {
|
|
211
|
+
if (isDividerEntry(entry)) {
|
|
212
|
+
flushToolGroup();
|
|
213
|
+
groupedEntries.push({ type: "divider", entries: [entry] });
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (entry.kind === "permission") {
|
|
217
|
+
flushToolGroup();
|
|
218
|
+
groupedEntries.push({ type: "permission", entries: [entry] });
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (entry.kind === "tool" || entry.kind === "reasoning" || entry.kind === "meta") {
|
|
222
|
+
currentToolGroup.push(entry);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
flushToolGroup();
|
|
226
|
+
groupedEntries.push({ type: "message", entries: [entry] });
|
|
227
|
+
}
|
|
228
|
+
flushToolGroup();
|
|
229
|
+
return groupedEntries;
|
|
230
|
+
};
|
|
231
|
+
var getGroupedEntryKey = (group, index) => {
|
|
232
|
+
const firstEntry = group.entries[0];
|
|
233
|
+
if (group.type === "tool-group") {
|
|
234
|
+
return `tool-group:${firstEntry?.id ?? index}`;
|
|
235
|
+
}
|
|
236
|
+
return firstEntry?.id ?? `${group.type}:${index}`;
|
|
237
|
+
};
|
|
238
|
+
var ToolItem = ({
|
|
239
|
+
entry,
|
|
240
|
+
isLast,
|
|
241
|
+
expanded,
|
|
242
|
+
onExpandedChange,
|
|
243
|
+
classNames,
|
|
244
|
+
onEventClick,
|
|
245
|
+
canOpenEvent,
|
|
246
|
+
renderInlinePendingIndicator,
|
|
247
|
+
renderToolItemIcon,
|
|
248
|
+
renderChevron,
|
|
249
|
+
renderEventLinkContent
|
|
250
|
+
}) => {
|
|
251
|
+
const isTool = entry.kind === "tool";
|
|
252
|
+
const isReasoning = entry.kind === "reasoning";
|
|
253
|
+
const isMeta = entry.kind === "meta";
|
|
254
|
+
const isComplete = isTool && (entry.toolStatus === "completed" || entry.toolStatus === "failed");
|
|
255
|
+
const isFailed = isTool && entry.toolStatus === "failed";
|
|
256
|
+
const isInProgress = isTool && entry.toolStatus === "in_progress";
|
|
257
|
+
const hasContent = isTool ? Boolean(entry.toolInput || entry.toolOutput) : isReasoning ? Boolean(entry.reasoning?.text?.trim()) : Boolean(entry.meta?.detail?.trim());
|
|
258
|
+
const showEventLink = Boolean(entry.eventId && onEventClick && canOpenEvent(entry));
|
|
259
|
+
return /* @__PURE__ */ jsxs(
|
|
260
|
+
"div",
|
|
261
|
+
{
|
|
262
|
+
className: cx(classNames.toolItem, isLast && "last", isFailed && "failed"),
|
|
263
|
+
"data-slot": "tool-item",
|
|
264
|
+
"data-kind": entry.kind,
|
|
265
|
+
"data-state": entry.toolStatus,
|
|
266
|
+
"data-last": isLast ? "true" : void 0,
|
|
267
|
+
"data-failed": isFailed ? "true" : void 0,
|
|
268
|
+
children: [
|
|
269
|
+
/* @__PURE__ */ jsxs("div", { className: classNames.toolItemConnector, "data-slot": "tool-item-connector", children: [
|
|
270
|
+
/* @__PURE__ */ jsx("div", { className: classNames.toolItemDot, "data-slot": "tool-item-dot" }),
|
|
271
|
+
!isLast ? /* @__PURE__ */ jsx("div", { className: classNames.toolItemLine, "data-slot": "tool-item-line" }) : null
|
|
272
|
+
] }),
|
|
273
|
+
/* @__PURE__ */ jsxs("div", { className: classNames.toolItemContent, "data-slot": "tool-item-content", children: [
|
|
274
|
+
/* @__PURE__ */ jsxs(
|
|
275
|
+
"button",
|
|
276
|
+
{
|
|
277
|
+
type: "button",
|
|
278
|
+
className: cx(classNames.toolItemHeader, expanded && "expanded"),
|
|
279
|
+
"data-slot": "tool-item-header",
|
|
280
|
+
"data-expanded": expanded ? "true" : void 0,
|
|
281
|
+
"data-has-content": hasContent ? "true" : void 0,
|
|
282
|
+
disabled: !hasContent,
|
|
283
|
+
onClick: () => {
|
|
284
|
+
if (hasContent) {
|
|
285
|
+
onExpandedChange(!expanded);
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
children: [
|
|
289
|
+
/* @__PURE__ */ jsx("span", { className: classNames.toolItemIcon, "data-slot": "tool-item-icon", children: renderToolItemIcon(entry) }),
|
|
290
|
+
/* @__PURE__ */ jsx("span", { className: classNames.toolItemLabel, "data-slot": "tool-item-label", children: getToolItemLabel(entry) }),
|
|
291
|
+
isInProgress ? /* @__PURE__ */ jsx("span", { className: classNames.toolItemSpinner, "data-slot": "tool-item-spinner", children: renderInlinePendingIndicator() }) : null,
|
|
292
|
+
showEventLink ? /* @__PURE__ */ jsx(
|
|
293
|
+
"span",
|
|
294
|
+
{
|
|
295
|
+
className: classNames.toolItemLink,
|
|
296
|
+
"data-slot": "tool-item-link",
|
|
297
|
+
role: "button",
|
|
298
|
+
tabIndex: 0,
|
|
299
|
+
onClick: (event) => {
|
|
300
|
+
event.stopPropagation();
|
|
301
|
+
onEventClick?.(entry.eventId);
|
|
302
|
+
},
|
|
303
|
+
onKeyDown: (event) => {
|
|
304
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
305
|
+
event.preventDefault();
|
|
306
|
+
event.stopPropagation();
|
|
307
|
+
onEventClick?.(entry.eventId);
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
children: renderEventLinkContent(entry)
|
|
311
|
+
}
|
|
312
|
+
) : null,
|
|
313
|
+
hasContent ? /* @__PURE__ */ jsx("span", { className: classNames.toolItemChevron, "data-slot": "tool-item-chevron", children: renderChevron(expanded) }) : null
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
),
|
|
317
|
+
expanded && hasContent ? /* @__PURE__ */ jsxs("div", { className: classNames.toolItemBody, "data-slot": "tool-item-body", children: [
|
|
318
|
+
isTool && entry.toolInput ? /* @__PURE__ */ jsxs("div", { className: classNames.toolSection, "data-slot": "tool-section", "data-section": "input", children: [
|
|
319
|
+
/* @__PURE__ */ jsx("div", { className: classNames.toolSectionTitle, "data-slot": "tool-section-title", children: "Input" }),
|
|
320
|
+
/* @__PURE__ */ jsx("pre", { className: classNames.toolCode, "data-slot": "tool-code", children: entry.toolInput })
|
|
321
|
+
] }) : null,
|
|
322
|
+
isTool && isComplete && entry.toolOutput ? /* @__PURE__ */ jsxs("div", { className: classNames.toolSection, "data-slot": "tool-section", "data-section": "output", children: [
|
|
323
|
+
/* @__PURE__ */ jsx("div", { className: classNames.toolSectionTitle, "data-slot": "tool-section-title", children: "Output" }),
|
|
324
|
+
/* @__PURE__ */ jsx("pre", { className: classNames.toolCode, "data-slot": "tool-code", children: entry.toolOutput })
|
|
325
|
+
] }) : null,
|
|
326
|
+
isReasoning && entry.reasoning?.text ? /* @__PURE__ */ jsx("div", { className: classNames.toolSection, "data-slot": "tool-section", "data-section": "reasoning", children: /* @__PURE__ */ jsx("pre", { className: cx(classNames.toolCode, classNames.toolCodeMuted), "data-slot": "tool-code", children: entry.reasoning.text }) }) : null,
|
|
327
|
+
isMeta && entry.meta?.detail ? /* @__PURE__ */ jsx("div", { className: classNames.toolSection, "data-slot": "tool-section", "data-section": "meta", children: /* @__PURE__ */ jsx("pre", { className: classNames.toolCode, "data-slot": "tool-code", children: entry.meta.detail }) }) : null
|
|
328
|
+
] }) : null
|
|
329
|
+
] })
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
);
|
|
333
|
+
};
|
|
334
|
+
var ToolGroup = ({
|
|
335
|
+
entries,
|
|
336
|
+
expanded,
|
|
337
|
+
onExpandedChange,
|
|
338
|
+
expandedItemIds,
|
|
339
|
+
onToolItemExpandedChange,
|
|
340
|
+
classNames,
|
|
341
|
+
onEventClick,
|
|
342
|
+
canOpenEvent,
|
|
343
|
+
getToolGroupSummary,
|
|
344
|
+
renderInlinePendingIndicator,
|
|
345
|
+
renderToolItemIcon,
|
|
346
|
+
renderToolGroupIcon,
|
|
347
|
+
renderChevron,
|
|
348
|
+
renderEventLinkContent
|
|
349
|
+
}) => {
|
|
350
|
+
const hasFailed = entries.some((entry) => entry.kind === "tool" && entry.toolStatus === "failed");
|
|
351
|
+
if (entries.length === 1) {
|
|
352
|
+
return /* @__PURE__ */ jsx("div", { className: classNames.toolGroupSingle, "data-slot": "tool-group-single", children: /* @__PURE__ */ jsx(
|
|
353
|
+
ToolItem,
|
|
354
|
+
{
|
|
355
|
+
entry: entries[0],
|
|
356
|
+
isLast: true,
|
|
357
|
+
expanded: Boolean(expandedItemIds[entries[0].id]),
|
|
358
|
+
onExpandedChange: (nextExpanded) => onToolItemExpandedChange(entries[0].id, nextExpanded),
|
|
359
|
+
classNames,
|
|
360
|
+
onEventClick,
|
|
361
|
+
canOpenEvent,
|
|
362
|
+
renderInlinePendingIndicator,
|
|
363
|
+
renderToolItemIcon,
|
|
364
|
+
renderChevron,
|
|
365
|
+
renderEventLinkContent
|
|
366
|
+
}
|
|
367
|
+
) });
|
|
368
|
+
}
|
|
369
|
+
return /* @__PURE__ */ jsxs("div", { className: cx(classNames.toolGroupContainer, hasFailed && "failed"), "data-slot": "tool-group", "data-failed": hasFailed ? "true" : void 0, children: [
|
|
370
|
+
/* @__PURE__ */ jsxs(
|
|
371
|
+
"button",
|
|
372
|
+
{
|
|
373
|
+
type: "button",
|
|
374
|
+
className: cx(classNames.toolGroupHeader, expanded && "expanded"),
|
|
375
|
+
"data-slot": "tool-group-header",
|
|
376
|
+
"data-expanded": expanded ? "true" : void 0,
|
|
377
|
+
onClick: () => onExpandedChange(!expanded),
|
|
378
|
+
children: [
|
|
379
|
+
/* @__PURE__ */ jsx("span", { className: classNames.toolGroupIcon, "data-slot": "tool-group-icon", children: renderToolGroupIcon(entries, expanded) }),
|
|
380
|
+
/* @__PURE__ */ jsx("span", { className: classNames.toolGroupLabel, "data-slot": "tool-group-label", children: getToolGroupSummary(entries) }),
|
|
381
|
+
/* @__PURE__ */ jsx("span", { className: classNames.toolGroupChevron, "data-slot": "tool-group-chevron", children: renderChevron(expanded) })
|
|
382
|
+
]
|
|
383
|
+
}
|
|
384
|
+
),
|
|
385
|
+
expanded ? /* @__PURE__ */ jsx("div", { className: classNames.toolGroupBody, "data-slot": "tool-group-body", children: entries.map((entry, index) => /* @__PURE__ */ jsx(
|
|
386
|
+
ToolItem,
|
|
387
|
+
{
|
|
388
|
+
entry,
|
|
389
|
+
isLast: index === entries.length - 1,
|
|
390
|
+
expanded: Boolean(expandedItemIds[entry.id]),
|
|
391
|
+
onExpandedChange: (nextExpanded) => onToolItemExpandedChange(entry.id, nextExpanded),
|
|
392
|
+
classNames,
|
|
393
|
+
onEventClick,
|
|
394
|
+
canOpenEvent,
|
|
395
|
+
renderInlinePendingIndicator,
|
|
396
|
+
renderToolItemIcon,
|
|
397
|
+
renderChevron,
|
|
398
|
+
renderEventLinkContent
|
|
399
|
+
},
|
|
400
|
+
entry.id
|
|
401
|
+
)) }) : null
|
|
402
|
+
] });
|
|
403
|
+
};
|
|
404
|
+
var PermissionPrompt = ({
|
|
405
|
+
entry,
|
|
406
|
+
classNames,
|
|
407
|
+
onPermissionReply,
|
|
408
|
+
renderPermissionIcon,
|
|
409
|
+
renderPermissionOptionContent
|
|
410
|
+
}) => {
|
|
411
|
+
const permission = entry.permission;
|
|
412
|
+
if (!permission) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
const resolved = Boolean(permission.resolved);
|
|
416
|
+
const selectedOptionId = permission.selectedOptionId;
|
|
417
|
+
const canReply = Boolean(onPermissionReply) && !resolved;
|
|
418
|
+
return /* @__PURE__ */ jsxs("div", { className: cx(classNames.permissionPrompt, resolved && "resolved"), "data-slot": "permission-prompt", "data-resolved": resolved ? "true" : void 0, children: [
|
|
419
|
+
/* @__PURE__ */ jsxs("div", { className: classNames.permissionHeader, "data-slot": "permission-header", children: [
|
|
420
|
+
/* @__PURE__ */ jsx("span", { className: classNames.permissionIcon, "data-slot": "permission-icon", children: renderPermissionIcon(entry) }),
|
|
421
|
+
/* @__PURE__ */ jsx("span", { className: classNames.permissionTitle, "data-slot": "permission-title", children: permission.title })
|
|
422
|
+
] }),
|
|
423
|
+
permission.description ? /* @__PURE__ */ jsx("div", { className: classNames.permissionDescription, "data-slot": "permission-description", children: permission.description }) : null,
|
|
424
|
+
/* @__PURE__ */ jsxs("div", { className: classNames.permissionActions, "data-slot": "permission-actions", children: [
|
|
425
|
+
permission.options.map((option) => {
|
|
426
|
+
const reply = getPermissionReplyForOption(option.kind);
|
|
427
|
+
const label = getPermissionOptionLabel(option);
|
|
428
|
+
const selected = resolved && selectedOptionId === option.optionId;
|
|
429
|
+
const dimmed = resolved && !selected && selectedOptionId != null;
|
|
430
|
+
const tone = getPermissionOptionTone(option.kind);
|
|
431
|
+
return /* @__PURE__ */ jsx(
|
|
432
|
+
"button",
|
|
433
|
+
{
|
|
434
|
+
type: "button",
|
|
435
|
+
className: cx(classNames.permissionButton, tone, selected && "selected", dimmed && "dimmed"),
|
|
436
|
+
"data-slot": "permission-button",
|
|
437
|
+
"data-tone": tone,
|
|
438
|
+
"data-selected": selected ? "true" : void 0,
|
|
439
|
+
"data-dimmed": dimmed ? "true" : void 0,
|
|
440
|
+
disabled: !canReply,
|
|
441
|
+
onClick: () => onPermissionReply?.(permission.permissionId, reply),
|
|
442
|
+
children: renderPermissionOptionContent({
|
|
443
|
+
entry,
|
|
444
|
+
option,
|
|
445
|
+
label,
|
|
446
|
+
reply,
|
|
447
|
+
selected,
|
|
448
|
+
dimmed,
|
|
449
|
+
resolved
|
|
450
|
+
})
|
|
451
|
+
},
|
|
452
|
+
option.optionId
|
|
453
|
+
);
|
|
454
|
+
}),
|
|
455
|
+
resolved && !selectedOptionId ? /* @__PURE__ */ jsx("span", { className: classNames.permissionAutoResolved, "data-slot": "permission-auto-resolved", children: "Auto-resolved" }) : null
|
|
456
|
+
] })
|
|
457
|
+
] });
|
|
458
|
+
};
|
|
459
|
+
var AgentTranscript = ({
|
|
460
|
+
entries,
|
|
461
|
+
className,
|
|
462
|
+
classNames: classNameOverrides,
|
|
463
|
+
endRef,
|
|
464
|
+
scrollRef,
|
|
465
|
+
scrollToEntryId,
|
|
466
|
+
sessionError,
|
|
467
|
+
eventError,
|
|
468
|
+
isThinking,
|
|
469
|
+
agentId,
|
|
470
|
+
virtualize = false,
|
|
471
|
+
onAtBottomChange,
|
|
472
|
+
onEventClick,
|
|
473
|
+
onPermissionReply,
|
|
474
|
+
isDividerEntry = defaultIsDividerEntry,
|
|
475
|
+
canOpenEvent = defaultCanOpenEvent,
|
|
476
|
+
getToolGroupSummary = getDefaultToolGroupSummary,
|
|
477
|
+
renderMessageText = defaultRenderMessageText,
|
|
478
|
+
renderInlinePendingIndicator = defaultRenderPendingIndicator,
|
|
479
|
+
renderThinkingState,
|
|
480
|
+
renderToolItemIcon = getDefaultToolItemIcon,
|
|
481
|
+
renderToolGroupIcon = () => null,
|
|
482
|
+
renderChevron = defaultRenderChevron,
|
|
483
|
+
renderEventLinkContent = defaultRenderEventLinkContent,
|
|
484
|
+
renderPermissionIcon = defaultRenderPermissionIcon,
|
|
485
|
+
renderPermissionOptionContent = defaultRenderPermissionOptionContent
|
|
486
|
+
}) => {
|
|
487
|
+
const resolvedClassNames = useMemo(() => mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides), [classNameOverrides]);
|
|
488
|
+
const groupedEntries = useMemo(() => buildGroupedEntries(entries, isDividerEntry), [entries, isDividerEntry]);
|
|
489
|
+
const [expandedToolGroups, setExpandedToolGroups] = useState({});
|
|
490
|
+
const [expandedToolItems, setExpandedToolItems] = useState({});
|
|
491
|
+
const lastScrollTargetRef = useRef2(null);
|
|
492
|
+
const isVirtualized = virtualize && Boolean(scrollRef);
|
|
493
|
+
const { virtualizer, isFollowingRef } = useTranscriptVirtualizer(groupedEntries, isVirtualized ? scrollRef : void 0, onAtBottomChange);
|
|
494
|
+
useEffect2(() => {
|
|
495
|
+
if (!scrollToEntryId) {
|
|
496
|
+
lastScrollTargetRef.current = null;
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
if (!isVirtualized || scrollToEntryId === lastScrollTargetRef.current) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const targetIndex = groupedEntries.findIndex((group) => group.entries.some((entry) => entry.id === scrollToEntryId));
|
|
503
|
+
if (targetIndex < 0) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
lastScrollTargetRef.current = scrollToEntryId;
|
|
507
|
+
const frameId = requestAnimationFrame(() => {
|
|
508
|
+
virtualizer.scrollToIndex(targetIndex, {
|
|
509
|
+
align: "center",
|
|
510
|
+
behavior: "smooth"
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
return () => {
|
|
514
|
+
cancelAnimationFrame(frameId);
|
|
515
|
+
};
|
|
516
|
+
}, [groupedEntries, isVirtualized, scrollToEntryId, virtualizer]);
|
|
517
|
+
useEffect2(() => {
|
|
518
|
+
if (!isVirtualized || !scrollRef?.current || !isFollowingRef.current) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
const scrollElement = scrollRef.current;
|
|
522
|
+
const frameId = requestAnimationFrame(() => {
|
|
523
|
+
scrollElement.scrollTo({ top: scrollElement.scrollHeight });
|
|
524
|
+
});
|
|
525
|
+
return () => {
|
|
526
|
+
cancelAnimationFrame(frameId);
|
|
527
|
+
};
|
|
528
|
+
}, [eventError, isFollowingRef, isThinking, isVirtualized, scrollRef, sessionError]);
|
|
529
|
+
const setToolGroupExpanded = (groupKey, expanded) => {
|
|
530
|
+
setExpandedToolGroups((current) => {
|
|
531
|
+
if (current[groupKey] === expanded) {
|
|
532
|
+
return current;
|
|
533
|
+
}
|
|
534
|
+
return { ...current, [groupKey]: expanded };
|
|
535
|
+
});
|
|
536
|
+
};
|
|
537
|
+
const setToolItemExpanded = (entryId, expanded) => {
|
|
538
|
+
setExpandedToolItems((current) => {
|
|
539
|
+
if (current[entryId] === expanded) {
|
|
540
|
+
return current;
|
|
541
|
+
}
|
|
542
|
+
return { ...current, [entryId]: expanded };
|
|
543
|
+
});
|
|
544
|
+
};
|
|
545
|
+
const renderGroup = (group, index) => {
|
|
546
|
+
if (group.type === "divider") {
|
|
547
|
+
const entry2 = group.entries[0];
|
|
548
|
+
const title = entry2.meta?.title ?? "Status";
|
|
549
|
+
return /* @__PURE__ */ jsxs("div", { className: resolvedClassNames.divider, "data-slot": "divider", children: [
|
|
550
|
+
/* @__PURE__ */ jsx("div", { className: resolvedClassNames.dividerLine, "data-slot": "divider-line" }),
|
|
551
|
+
/* @__PURE__ */ jsx("span", { className: resolvedClassNames.dividerText, "data-slot": "divider-text", children: title }),
|
|
552
|
+
/* @__PURE__ */ jsx("div", { className: resolvedClassNames.dividerLine, "data-slot": "divider-line" })
|
|
553
|
+
] }, entry2.id);
|
|
554
|
+
}
|
|
555
|
+
if (group.type === "tool-group") {
|
|
556
|
+
const groupKey = getGroupedEntryKey(group, index);
|
|
557
|
+
return /* @__PURE__ */ jsx(
|
|
558
|
+
ToolGroup,
|
|
559
|
+
{
|
|
560
|
+
entries: group.entries,
|
|
561
|
+
expanded: Boolean(expandedToolGroups[groupKey]),
|
|
562
|
+
onExpandedChange: (expanded) => setToolGroupExpanded(groupKey, expanded),
|
|
563
|
+
expandedItemIds: expandedToolItems,
|
|
564
|
+
onToolItemExpandedChange: setToolItemExpanded,
|
|
565
|
+
classNames: resolvedClassNames,
|
|
566
|
+
onEventClick,
|
|
567
|
+
canOpenEvent,
|
|
568
|
+
getToolGroupSummary,
|
|
569
|
+
renderInlinePendingIndicator,
|
|
570
|
+
renderToolItemIcon,
|
|
571
|
+
renderToolGroupIcon,
|
|
572
|
+
renderChevron,
|
|
573
|
+
renderEventLinkContent
|
|
574
|
+
},
|
|
575
|
+
groupKey
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
if (group.type === "permission") {
|
|
579
|
+
const entry2 = group.entries[0];
|
|
580
|
+
return /* @__PURE__ */ jsx(
|
|
581
|
+
PermissionPrompt,
|
|
582
|
+
{
|
|
583
|
+
entry: entry2,
|
|
584
|
+
classNames: resolvedClassNames,
|
|
585
|
+
onPermissionReply,
|
|
586
|
+
renderPermissionIcon,
|
|
587
|
+
renderPermissionOptionContent
|
|
588
|
+
},
|
|
589
|
+
entry2.id
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
const entry = group.entries[0];
|
|
593
|
+
const messageVariant = getMessageVariant(entry);
|
|
594
|
+
return /* @__PURE__ */ jsx(
|
|
595
|
+
"div",
|
|
596
|
+
{
|
|
597
|
+
className: cx(resolvedClassNames.message, messageVariant, "no-avatar"),
|
|
598
|
+
"data-slot": "message",
|
|
599
|
+
"data-kind": entry.kind,
|
|
600
|
+
"data-role": entry.role,
|
|
601
|
+
"data-variant": messageVariant,
|
|
602
|
+
"data-severity": entry.meta?.severity,
|
|
603
|
+
children: /* @__PURE__ */ jsx("div", { className: resolvedClassNames.messageContent, "data-slot": "message-content", children: entry.text ? /* @__PURE__ */ jsx("div", { className: resolvedClassNames.messageText, "data-slot": "message-text", children: renderMessageText(entry) }) : /* @__PURE__ */ jsx("span", { className: resolvedClassNames.thinkingIndicator, "data-slot": "thinking-indicator", children: renderInlinePendingIndicator() }) })
|
|
604
|
+
},
|
|
605
|
+
entry.id
|
|
606
|
+
);
|
|
607
|
+
};
|
|
608
|
+
return /* @__PURE__ */ jsxs("div", { className: cx(resolvedClassNames.root, className), "data-slot": "root", "data-virtualized": isVirtualized ? "true" : void 0, children: [
|
|
609
|
+
isVirtualized ? /* @__PURE__ */ jsx(
|
|
610
|
+
"div",
|
|
611
|
+
{
|
|
612
|
+
"data-slot": "virtual-list",
|
|
613
|
+
style: {
|
|
614
|
+
height: `${virtualizer.getTotalSize()}px`,
|
|
615
|
+
position: "relative",
|
|
616
|
+
width: "100%"
|
|
617
|
+
},
|
|
618
|
+
children: virtualizer.getVirtualItems().map((virtualItem) => {
|
|
619
|
+
const group = groupedEntries[virtualItem.index];
|
|
620
|
+
if (!group) {
|
|
621
|
+
return null;
|
|
622
|
+
}
|
|
623
|
+
return /* @__PURE__ */ jsx(
|
|
624
|
+
"div",
|
|
625
|
+
{
|
|
626
|
+
"data-index": virtualItem.index,
|
|
627
|
+
ref: (node) => {
|
|
628
|
+
if (node) {
|
|
629
|
+
virtualizer.measureElement(node);
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
style: {
|
|
633
|
+
left: 0,
|
|
634
|
+
position: "absolute",
|
|
635
|
+
top: 0,
|
|
636
|
+
transform: `translateY(${virtualItem.start}px)`,
|
|
637
|
+
width: "100%"
|
|
638
|
+
},
|
|
639
|
+
children: /* @__PURE__ */ jsx("div", { style: { paddingBottom: virtualItem.index === groupedEntries.length - 1 ? 0 : `${VIRTUAL_GROUP_GAP_PX}px` }, children: renderGroup(group, virtualItem.index) })
|
|
640
|
+
},
|
|
641
|
+
getGroupedEntryKey(group, virtualItem.index)
|
|
642
|
+
);
|
|
643
|
+
})
|
|
644
|
+
}
|
|
645
|
+
) : groupedEntries.map((group, index) => renderGroup(group, index)),
|
|
646
|
+
sessionError ? /* @__PURE__ */ jsx("div", { className: resolvedClassNames.error, "data-slot": "error", "data-source": "session", children: sessionError }) : null,
|
|
647
|
+
eventError ? /* @__PURE__ */ jsx("div", { className: resolvedClassNames.error, "data-slot": "error", "data-source": "event", children: eventError }) : null,
|
|
648
|
+
isThinking ? renderThinkingState?.({ agentId }) ?? /* @__PURE__ */ jsx("div", { className: resolvedClassNames.thinkingRow, "data-slot": "thinking-row", children: /* @__PURE__ */ jsx("span", { className: resolvedClassNames.thinkingIndicator, "data-slot": "thinking-indicator", children: "Thinking..." }) }) : null,
|
|
649
|
+
!isVirtualized ? /* @__PURE__ */ jsx("div", { ref: endRef, className: resolvedClassNames.endAnchor, "data-slot": "end-anchor" }) : null
|
|
650
|
+
] });
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
// src/ChatComposer.tsx
|
|
654
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
655
|
+
var DEFAULT_CLASS_NAMES2 = {
|
|
656
|
+
root: "sa-chat-composer",
|
|
657
|
+
form: "sa-chat-composer-form",
|
|
658
|
+
input: "sa-chat-composer-input",
|
|
659
|
+
submit: "sa-chat-composer-submit",
|
|
660
|
+
submitContent: "sa-chat-composer-submit-content"
|
|
661
|
+
};
|
|
662
|
+
var cx2 = (...values) => values.filter(Boolean).join(" ");
|
|
663
|
+
var mergeClassNames2 = (defaults, overrides) => ({
|
|
664
|
+
root: cx2(defaults.root, overrides?.root),
|
|
665
|
+
form: cx2(defaults.form, overrides?.form),
|
|
666
|
+
input: cx2(defaults.input, overrides?.input),
|
|
667
|
+
submit: cx2(defaults.submit, overrides?.submit),
|
|
668
|
+
submitContent: cx2(defaults.submitContent, overrides?.submitContent)
|
|
669
|
+
});
|
|
670
|
+
var ChatComposer = ({
|
|
671
|
+
message,
|
|
672
|
+
onMessageChange,
|
|
673
|
+
onSubmit,
|
|
674
|
+
onKeyDown,
|
|
675
|
+
placeholder,
|
|
676
|
+
disabled = false,
|
|
677
|
+
submitDisabled = false,
|
|
678
|
+
allowEmptySubmit = false,
|
|
679
|
+
submitLabel = "Send",
|
|
680
|
+
className,
|
|
681
|
+
classNames: classNameOverrides,
|
|
682
|
+
inputRef,
|
|
683
|
+
rows = 1,
|
|
684
|
+
textareaProps,
|
|
685
|
+
renderSubmitContent,
|
|
686
|
+
renderFooter
|
|
687
|
+
}) => {
|
|
688
|
+
const resolvedClassNames = mergeClassNames2(DEFAULT_CLASS_NAMES2, classNameOverrides);
|
|
689
|
+
const isSubmitDisabled = disabled || submitDisabled || !allowEmptySubmit && message.trim().length === 0;
|
|
690
|
+
return /* @__PURE__ */ jsx2("div", { className: cx2(resolvedClassNames.root, className), "data-slot": "root", children: /* @__PURE__ */ jsxs2(
|
|
691
|
+
"form",
|
|
692
|
+
{
|
|
693
|
+
className: resolvedClassNames.form,
|
|
694
|
+
"data-slot": "form",
|
|
695
|
+
onSubmit: (event) => {
|
|
696
|
+
event.preventDefault();
|
|
697
|
+
if (!isSubmitDisabled) {
|
|
698
|
+
onSubmit();
|
|
699
|
+
}
|
|
700
|
+
},
|
|
701
|
+
children: [
|
|
702
|
+
/* @__PURE__ */ jsx2(
|
|
703
|
+
"textarea",
|
|
704
|
+
{
|
|
705
|
+
...textareaProps,
|
|
706
|
+
ref: inputRef,
|
|
707
|
+
className: resolvedClassNames.input,
|
|
708
|
+
"data-slot": "input",
|
|
709
|
+
"data-disabled": disabled ? "true" : void 0,
|
|
710
|
+
"data-empty": message.trim().length === 0 ? "true" : void 0,
|
|
711
|
+
value: message,
|
|
712
|
+
onChange: (event) => onMessageChange(event.target.value),
|
|
713
|
+
onKeyDown,
|
|
714
|
+
placeholder,
|
|
715
|
+
rows,
|
|
716
|
+
disabled
|
|
717
|
+
}
|
|
718
|
+
),
|
|
719
|
+
renderFooter?.(),
|
|
720
|
+
/* @__PURE__ */ jsx2(
|
|
721
|
+
"button",
|
|
722
|
+
{
|
|
723
|
+
type: "submit",
|
|
724
|
+
className: resolvedClassNames.submit,
|
|
725
|
+
"data-slot": "submit",
|
|
726
|
+
"data-disabled": isSubmitDisabled ? "true" : void 0,
|
|
727
|
+
disabled: isSubmitDisabled,
|
|
728
|
+
"aria-label": submitLabel,
|
|
729
|
+
title: submitLabel,
|
|
730
|
+
children: /* @__PURE__ */ jsx2("span", { className: resolvedClassNames.submitContent, "data-slot": "submit-content", children: renderSubmitContent?.() ?? submitLabel })
|
|
731
|
+
}
|
|
732
|
+
)
|
|
733
|
+
]
|
|
734
|
+
}
|
|
735
|
+
) });
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
// src/AgentConversation.tsx
|
|
739
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
740
|
+
var DEFAULT_CLASS_NAMES3 = {
|
|
741
|
+
root: "sa-agent-conversation",
|
|
742
|
+
transcript: "sa-agent-conversation-transcript",
|
|
743
|
+
emptyState: "sa-agent-conversation-empty-state",
|
|
744
|
+
composer: "sa-agent-conversation-composer"
|
|
745
|
+
};
|
|
746
|
+
var cx3 = (...values) => values.filter(Boolean).join(" ");
|
|
747
|
+
var mergeClassNames3 = (defaults, overrides) => ({
|
|
748
|
+
root: cx3(defaults.root, overrides?.root),
|
|
749
|
+
transcript: cx3(defaults.transcript, overrides?.transcript),
|
|
750
|
+
emptyState: cx3(defaults.emptyState, overrides?.emptyState),
|
|
751
|
+
composer: cx3(defaults.composer, overrides?.composer)
|
|
752
|
+
});
|
|
753
|
+
var AgentConversation = ({
|
|
754
|
+
entries,
|
|
755
|
+
className,
|
|
756
|
+
classNames: classNameOverrides,
|
|
757
|
+
emptyState,
|
|
758
|
+
transcriptClassName,
|
|
759
|
+
transcriptClassNames,
|
|
760
|
+
scrollRef,
|
|
761
|
+
composerClassName,
|
|
762
|
+
composerClassNames,
|
|
763
|
+
transcriptProps,
|
|
764
|
+
composerProps
|
|
765
|
+
}) => {
|
|
766
|
+
const resolvedClassNames = mergeClassNames3(DEFAULT_CLASS_NAMES3, classNameOverrides);
|
|
767
|
+
const hasTranscriptContent = entries.length > 0 || Boolean(transcriptProps?.sessionError) || Boolean(transcriptProps?.eventError);
|
|
768
|
+
return /* @__PURE__ */ jsxs3("div", { className: cx3(resolvedClassNames.root, className), "data-slot": "root", children: [
|
|
769
|
+
hasTranscriptContent ? scrollRef ? /* @__PURE__ */ jsx3("div", { className: cx3(resolvedClassNames.transcript, transcriptClassName), "data-slot": "transcript", ref: scrollRef, children: /* @__PURE__ */ jsx3(AgentTranscript, { entries, classNames: transcriptClassNames, ...transcriptProps }) }) : /* @__PURE__ */ jsx3(
|
|
770
|
+
AgentTranscript,
|
|
771
|
+
{
|
|
772
|
+
entries,
|
|
773
|
+
className: cx3(resolvedClassNames.transcript, transcriptClassName),
|
|
774
|
+
classNames: transcriptClassNames,
|
|
775
|
+
...transcriptProps
|
|
776
|
+
}
|
|
777
|
+
) : emptyState ? /* @__PURE__ */ jsx3("div", { className: resolvedClassNames.emptyState, "data-slot": "empty-state", children: emptyState }) : null,
|
|
778
|
+
composerProps ? /* @__PURE__ */ jsx3(ChatComposer, { className: cx3(resolvedClassNames.composer, composerClassName), classNames: composerClassNames, ...composerProps }) : null
|
|
779
|
+
] });
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
// src/ProcessTerminal.tsx
|
|
783
|
+
import { useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
784
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4
785
|
var terminalTheme = {
|
|
5
786
|
background: "#09090b",
|
|
6
787
|
foreground: "#f4f4f5",
|
|
@@ -71,15 +852,17 @@ var ProcessTerminal = ({
|
|
|
71
852
|
className,
|
|
72
853
|
style,
|
|
73
854
|
terminalStyle,
|
|
855
|
+
statusBarStyleOverride,
|
|
74
856
|
height = 360,
|
|
857
|
+
showStatusBar = true,
|
|
75
858
|
onExit,
|
|
76
859
|
onError
|
|
77
860
|
}) => {
|
|
78
|
-
const hostRef =
|
|
79
|
-
const [connectionState, setConnectionState] =
|
|
80
|
-
const [statusMessage, setStatusMessage] =
|
|
81
|
-
const [exitCode, setExitCode] =
|
|
82
|
-
|
|
861
|
+
const hostRef = useRef3(null);
|
|
862
|
+
const [connectionState, setConnectionState] = useState2("connecting");
|
|
863
|
+
const [statusMessage, setStatusMessage] = useState2("Connecting to PTY...");
|
|
864
|
+
const [exitCode, setExitCode] = useState2(null);
|
|
865
|
+
useEffect3(() => {
|
|
83
866
|
let cancelled = false;
|
|
84
867
|
let terminal = null;
|
|
85
868
|
let fitAddon = null;
|
|
@@ -157,9 +940,7 @@ var ProcessTerminal = ({
|
|
|
157
940
|
}
|
|
158
941
|
setConnectionState("closed");
|
|
159
942
|
setExitCode(frame.exitCode ?? null);
|
|
160
|
-
setStatusMessage(
|
|
161
|
-
frame.exitCode == null ? "Process exited." : `Process exited with code ${frame.exitCode}.`
|
|
162
|
-
);
|
|
943
|
+
setStatusMessage(frame.exitCode == null ? "Process exited." : `Process exited with code ${frame.exitCode}.`);
|
|
163
944
|
onExit?.(frame);
|
|
164
945
|
});
|
|
165
946
|
nextSession.onError((error) => {
|
|
@@ -199,15 +980,15 @@ var ProcessTerminal = ({
|
|
|
199
980
|
terminal?.dispose();
|
|
200
981
|
};
|
|
201
982
|
}, [client, onError, onExit, processId]);
|
|
202
|
-
return /* @__PURE__ */
|
|
203
|
-
/* @__PURE__ */
|
|
204
|
-
/* @__PURE__ */
|
|
205
|
-
exitCode != null ? /* @__PURE__ */
|
|
983
|
+
return /* @__PURE__ */ jsxs4("div", { className, style: { ...shellStyle, ...style }, children: [
|
|
984
|
+
showStatusBar ? /* @__PURE__ */ jsxs4("div", { style: { ...statusBarStyle, ...statusBarStyleOverride }, children: [
|
|
985
|
+
/* @__PURE__ */ jsx4("span", { style: { color: getStatusColor(connectionState) }, children: statusMessage }),
|
|
986
|
+
exitCode != null ? /* @__PURE__ */ jsxs4("span", { style: exitCodeStyle, children: [
|
|
206
987
|
"exit=",
|
|
207
988
|
exitCode
|
|
208
989
|
] }) : null
|
|
209
|
-
] }),
|
|
210
|
-
/* @__PURE__ */
|
|
990
|
+
] }) : null,
|
|
991
|
+
/* @__PURE__ */ jsx4(
|
|
211
992
|
"div",
|
|
212
993
|
{
|
|
213
994
|
ref: hostRef,
|
|
@@ -225,6 +1006,10 @@ var ProcessTerminal = ({
|
|
|
225
1006
|
] });
|
|
226
1007
|
};
|
|
227
1008
|
export {
|
|
228
|
-
|
|
1009
|
+
AgentConversation,
|
|
1010
|
+
AgentTranscript,
|
|
1011
|
+
ChatComposer,
|
|
1012
|
+
ProcessTerminal,
|
|
1013
|
+
useTranscriptVirtualizer
|
|
229
1014
|
};
|
|
230
1015
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ProcessTerminal.tsx"],"sourcesContent":["\"use client\";\n\nimport type { FitAddon as GhosttyFitAddon, Terminal as GhosttyTerminal } from \"ghostty-web\";\nimport type { CSSProperties } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { SandboxAgent, TerminalErrorStatus, TerminalExitStatus } from \"sandbox-agent\";\n\ntype ConnectionState = \"connecting\" | \"ready\" | \"closed\" | \"error\";\n\nexport type ProcessTerminalClient = Pick<SandboxAgent, \"connectProcessTerminal\">;\n\nexport interface ProcessTerminalProps {\n client: ProcessTerminalClient;\n processId: string;\n className?: string;\n style?: CSSProperties;\n terminalStyle?: CSSProperties;\n height?: number | string;\n onExit?: (status: TerminalExitStatus) => void;\n onError?: (error: TerminalErrorStatus | Error) => void;\n}\n\nconst terminalTheme = {\n background: \"#09090b\",\n foreground: \"#f4f4f5\",\n cursor: \"#f97316\",\n cursorAccent: \"#09090b\",\n selectionBackground: \"#27272a\",\n black: \"#18181b\",\n red: \"#f87171\",\n green: \"#4ade80\",\n yellow: \"#fbbf24\",\n blue: \"#60a5fa\",\n magenta: \"#f472b6\",\n cyan: \"#22d3ee\",\n white: \"#e4e4e7\",\n brightBlack: \"#3f3f46\",\n brightRed: \"#fb7185\",\n brightGreen: \"#86efac\",\n brightYellow: \"#fde047\",\n brightBlue: \"#93c5fd\",\n brightMagenta: \"#f9a8d4\",\n brightCyan: \"#67e8f9\",\n brightWhite: \"#fafafa\",\n};\n\nconst shellStyle: CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 10,\n background: \"rgba(0, 0, 0, 0.3)\",\n};\n\nconst statusBarStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: 12,\n padding: \"8px 12px\",\n borderBottom: \"1px solid rgba(255, 255, 255, 0.08)\",\n background: \"rgba(0, 0, 0, 0.2)\",\n color: \"rgba(244, 244, 245, 0.86)\",\n fontSize: 11,\n lineHeight: 1.4,\n};\n\nconst hostBaseStyle: CSSProperties = {\n minHeight: 320,\n padding: 10,\n overflow: \"hidden\",\n};\n\nconst exitCodeStyle: CSSProperties = {\n fontFamily: \"ui-monospace, SFMono-Regular, SF Mono, Menlo, monospace\",\n opacity: 0.72,\n};\n\nconst getStatusColor = (state: ConnectionState): string => {\n switch (state) {\n case \"ready\":\n return \"#4ade80\";\n case \"error\":\n return \"#fb7185\";\n case \"closed\":\n return \"#fbbf24\";\n default:\n return \"rgba(244, 244, 245, 0.72)\";\n }\n};\n\nexport const ProcessTerminal = ({\n client,\n processId,\n className,\n style,\n terminalStyle,\n height = 360,\n onExit,\n onError,\n}: ProcessTerminalProps) => {\n const hostRef = useRef<HTMLDivElement | null>(null);\n const [connectionState, setConnectionState] = useState<ConnectionState>(\"connecting\");\n const [statusMessage, setStatusMessage] = useState(\"Connecting to PTY...\");\n const [exitCode, setExitCode] = useState<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n let terminal: GhosttyTerminal | null = null;\n let fitAddon: GhosttyFitAddon | null = null;\n let session: ReturnType<ProcessTerminalClient[\"connectProcessTerminal\"]> | null = null;\n let resizeRaf = 0;\n let removeDataListener: { dispose(): void } | null = null;\n let removeResizeListener: { dispose(): void } | null = null;\n\n setConnectionState(\"connecting\");\n setStatusMessage(\"Connecting to PTY...\");\n setExitCode(null);\n\n const syncSize = () => {\n if (!terminal || !session) {\n return;\n }\n\n session.resize({\n cols: terminal.cols,\n rows: terminal.rows,\n });\n };\n\n const connect = async () => {\n try {\n const ghostty = await import(\"ghostty-web\");\n await ghostty.init();\n\n if (cancelled || !hostRef.current) {\n return;\n }\n\n terminal = new ghostty.Terminal({\n allowTransparency: true,\n cursorBlink: true,\n cursorStyle: \"block\",\n fontFamily: \"ui-monospace, SFMono-Regular, SF Mono, Menlo, monospace\",\n fontSize: 13,\n smoothScrollDuration: 90,\n theme: terminalTheme,\n });\n fitAddon = new ghostty.FitAddon();\n\n terminal.open(hostRef.current);\n const terminalRoot = hostRef.current.firstElementChild;\n if (terminalRoot instanceof HTMLElement) {\n terminalRoot.style.width = \"100%\";\n terminalRoot.style.height = \"100%\";\n }\n terminal.loadAddon(fitAddon);\n fitAddon.fit();\n fitAddon.observeResize();\n terminal.focus();\n\n removeDataListener = terminal.onData((data) => {\n session?.sendInput(data);\n });\n\n removeResizeListener = terminal.onResize(() => {\n if (resizeRaf) {\n window.cancelAnimationFrame(resizeRaf);\n }\n resizeRaf = window.requestAnimationFrame(syncSize);\n });\n\n const nextSession = client.connectProcessTerminal(processId);\n session = nextSession;\n\n nextSession.onReady((frame) => {\n if (cancelled || frame.type !== \"ready\") {\n return;\n }\n\n setConnectionState(\"ready\");\n setStatusMessage(\"Connected\");\n syncSize();\n });\n\n nextSession.onData((bytes) => {\n if (cancelled || !terminal) {\n return;\n }\n terminal.write(bytes);\n });\n\n nextSession.onExit((frame) => {\n if (cancelled || frame.type !== \"exit\") {\n return;\n }\n\n setConnectionState(\"closed\");\n setExitCode(frame.exitCode ?? null);\n setStatusMessage(\n frame.exitCode == null ? \"Process exited.\" : `Process exited with code ${frame.exitCode}.`\n );\n onExit?.(frame);\n });\n\n nextSession.onError((error) => {\n if (cancelled) {\n return;\n }\n\n setConnectionState(\"error\");\n setStatusMessage(error instanceof Error ? error.message : error.message);\n onError?.(error);\n });\n\n nextSession.onClose(() => {\n if (cancelled) {\n return;\n }\n\n setConnectionState((current) => (current === \"error\" ? current : \"closed\"));\n setStatusMessage((current) => (current === \"Connected\" ? \"Terminal disconnected.\" : current));\n });\n } catch (error) {\n if (cancelled) {\n return;\n }\n\n const nextError = error instanceof Error ? error : new Error(\"Failed to initialize terminal.\");\n setConnectionState(\"error\");\n setStatusMessage(nextError.message);\n onError?.(nextError);\n }\n };\n\n void connect();\n\n return () => {\n cancelled = true;\n if (resizeRaf) {\n window.cancelAnimationFrame(resizeRaf);\n }\n removeDataListener?.dispose();\n removeResizeListener?.dispose();\n session?.close();\n terminal?.dispose();\n };\n }, [client, onError, onExit, processId]);\n\n return (\n <div className={className} style={{ ...shellStyle, ...style }}>\n <div style={statusBarStyle}>\n <span style={{ color: getStatusColor(connectionState) }}>{statusMessage}</span>\n {exitCode != null ? <span style={exitCodeStyle}>exit={exitCode}</span> : null}\n </div>\n <div\n ref={hostRef}\n role=\"presentation\"\n style={{\n ...hostBaseStyle,\n height,\n ...terminalStyle,\n }}\n onClick={() => {\n hostRef.current?.querySelector(\"textarea\")?.focus();\n }}\n />\n </div>\n );\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/AgentTranscript.tsx","../src/useTranscriptVirtualizer.ts","../src/ChatComposer.tsx","../src/AgentConversation.tsx","../src/ProcessTerminal.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode, RefObject } from \"react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useTranscriptVirtualizer } from \"./useTranscriptVirtualizer.ts\";\n\nexport type PermissionReply = \"once\" | \"always\" | \"reject\";\n\nexport type PermissionOption = {\n optionId: string;\n name: string;\n kind: string;\n};\n\nexport type TranscriptEntry = {\n id: string;\n eventId?: string;\n kind: \"message\" | \"tool\" | \"meta\" | \"reasoning\" | \"permission\";\n time: string;\n role?: \"user\" | \"assistant\";\n text?: string;\n toolName?: string;\n toolInput?: string;\n toolOutput?: string;\n toolStatus?: string;\n reasoning?: { text: string; visibility?: string };\n meta?: { title: string; detail?: string; severity?: \"info\" | \"error\" };\n permission?: {\n permissionId: string;\n title: string;\n description?: string;\n options: PermissionOption[];\n resolved?: boolean;\n selectedOptionId?: string;\n };\n};\n\nexport interface AgentTranscriptClassNames {\n root: string;\n divider: string;\n dividerLine: string;\n dividerText: string;\n message: string;\n messageContent: string;\n messageText: string;\n error: string;\n toolGroupSingle: string;\n toolGroupContainer: string;\n toolGroupHeader: string;\n toolGroupIcon: string;\n toolGroupLabel: string;\n toolGroupChevron: string;\n toolGroupBody: string;\n toolItem: string;\n toolItemConnector: string;\n toolItemDot: string;\n toolItemLine: string;\n toolItemContent: string;\n toolItemHeader: string;\n toolItemIcon: string;\n toolItemLabel: string;\n toolItemSpinner: string;\n toolItemLink: string;\n toolItemChevron: string;\n toolItemBody: string;\n toolSection: string;\n toolSectionTitle: string;\n toolCode: string;\n toolCodeMuted: string;\n permissionPrompt: string;\n permissionHeader: string;\n permissionIcon: string;\n permissionTitle: string;\n permissionDescription: string;\n permissionActions: string;\n permissionButton: string;\n permissionAutoResolved: string;\n thinkingRow: string;\n thinkingAvatar: string;\n thinkingAvatarImage: string;\n thinkingAvatarLabel: string;\n thinkingIndicator: string;\n thinkingDot: string;\n endAnchor: string;\n}\n\nexport interface PermissionOptionRenderContext {\n entry: TranscriptEntry;\n option: PermissionOption;\n label: string;\n reply: PermissionReply;\n selected: boolean;\n dimmed: boolean;\n resolved: boolean;\n}\n\nexport interface AgentTranscriptProps {\n entries: TranscriptEntry[];\n className?: string;\n classNames?: Partial<AgentTranscriptClassNames>;\n endRef?: RefObject<HTMLDivElement>;\n scrollRef?: RefObject<HTMLDivElement>;\n scrollToEntryId?: string | null;\n sessionError?: string | null;\n eventError?: string | null;\n isThinking?: boolean;\n agentId?: string;\n virtualize?: boolean;\n onAtBottomChange?: (atBottom: boolean) => void;\n onEventClick?: (eventId: string) => void;\n onPermissionReply?: (permissionId: string, reply: PermissionReply) => void;\n isDividerEntry?: (entry: TranscriptEntry) => boolean;\n canOpenEvent?: (entry: TranscriptEntry) => boolean;\n getToolGroupSummary?: (entries: TranscriptEntry[]) => string;\n renderMessageText?: (entry: TranscriptEntry) => ReactNode;\n renderInlinePendingIndicator?: () => ReactNode;\n renderThinkingState?: (context: { agentId?: string }) => ReactNode;\n renderToolItemIcon?: (entry: TranscriptEntry) => ReactNode;\n renderToolGroupIcon?: (entries: TranscriptEntry[], expanded: boolean) => ReactNode;\n renderChevron?: (expanded: boolean) => ReactNode;\n renderEventLinkContent?: (entry: TranscriptEntry) => ReactNode;\n renderPermissionIcon?: (entry: TranscriptEntry) => ReactNode;\n renderPermissionOptionContent?: (context: PermissionOptionRenderContext) => ReactNode;\n}\n\ntype GroupedEntries =\n | { type: \"message\"; entries: TranscriptEntry[] }\n | { type: \"tool-group\"; entries: TranscriptEntry[] }\n | { type: \"divider\"; entries: TranscriptEntry[] }\n | { type: \"permission\"; entries: TranscriptEntry[] };\n\nconst VIRTUAL_GROUP_GAP_PX = 12;\n\nconst DEFAULT_CLASS_NAMES: AgentTranscriptClassNames = {\n root: \"sa-agent-transcript\",\n divider: \"sa-agent-transcript-divider\",\n dividerLine: \"sa-agent-transcript-divider-line\",\n dividerText: \"sa-agent-transcript-divider-text\",\n message: \"sa-agent-transcript-message\",\n messageContent: \"sa-agent-transcript-message-content\",\n messageText: \"sa-agent-transcript-message-text\",\n error: \"sa-agent-transcript-error\",\n toolGroupSingle: \"sa-agent-transcript-tool-group-single\",\n toolGroupContainer: \"sa-agent-transcript-tool-group\",\n toolGroupHeader: \"sa-agent-transcript-tool-group-header\",\n toolGroupIcon: \"sa-agent-transcript-tool-group-icon\",\n toolGroupLabel: \"sa-agent-transcript-tool-group-label\",\n toolGroupChevron: \"sa-agent-transcript-tool-group-chevron\",\n toolGroupBody: \"sa-agent-transcript-tool-group-body\",\n toolItem: \"sa-agent-transcript-tool-item\",\n toolItemConnector: \"sa-agent-transcript-tool-item-connector\",\n toolItemDot: \"sa-agent-transcript-tool-item-dot\",\n toolItemLine: \"sa-agent-transcript-tool-item-line\",\n toolItemContent: \"sa-agent-transcript-tool-item-content\",\n toolItemHeader: \"sa-agent-transcript-tool-item-header\",\n toolItemIcon: \"sa-agent-transcript-tool-item-icon\",\n toolItemLabel: \"sa-agent-transcript-tool-item-label\",\n toolItemSpinner: \"sa-agent-transcript-tool-item-spinner\",\n toolItemLink: \"sa-agent-transcript-tool-item-link\",\n toolItemChevron: \"sa-agent-transcript-tool-item-chevron\",\n toolItemBody: \"sa-agent-transcript-tool-item-body\",\n toolSection: \"sa-agent-transcript-tool-section\",\n toolSectionTitle: \"sa-agent-transcript-tool-section-title\",\n toolCode: \"sa-agent-transcript-tool-code\",\n toolCodeMuted: \"sa-agent-transcript-tool-code-muted\",\n permissionPrompt: \"sa-agent-transcript-permission-prompt\",\n permissionHeader: \"sa-agent-transcript-permission-header\",\n permissionIcon: \"sa-agent-transcript-permission-icon\",\n permissionTitle: \"sa-agent-transcript-permission-title\",\n permissionDescription: \"sa-agent-transcript-permission-description\",\n permissionActions: \"sa-agent-transcript-permission-actions\",\n permissionButton: \"sa-agent-transcript-permission-button\",\n permissionAutoResolved: \"sa-agent-transcript-permission-auto-resolved\",\n thinkingRow: \"sa-agent-transcript-thinking-row\",\n thinkingAvatar: \"sa-agent-transcript-thinking-avatar\",\n thinkingAvatarImage: \"sa-agent-transcript-thinking-avatar-image\",\n thinkingAvatarLabel: \"sa-agent-transcript-thinking-avatar-label\",\n thinkingIndicator: \"sa-agent-transcript-thinking-indicator\",\n thinkingDot: \"sa-agent-transcript-thinking-dot\",\n endAnchor: \"sa-agent-transcript-end\",\n};\n\nconst DEFAULT_DIVIDER_TITLES = new Set([\"Session Started\", \"Turn Started\", \"Turn Ended\"]);\n\nconst cx = (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(\" \");\n\nconst mergeClassNames = (defaults: AgentTranscriptClassNames, overrides?: Partial<AgentTranscriptClassNames>): AgentTranscriptClassNames => ({\n root: cx(defaults.root, overrides?.root),\n divider: cx(defaults.divider, overrides?.divider),\n dividerLine: cx(defaults.dividerLine, overrides?.dividerLine),\n dividerText: cx(defaults.dividerText, overrides?.dividerText),\n message: cx(defaults.message, overrides?.message),\n messageContent: cx(defaults.messageContent, overrides?.messageContent),\n messageText: cx(defaults.messageText, overrides?.messageText),\n error: cx(defaults.error, overrides?.error),\n toolGroupSingle: cx(defaults.toolGroupSingle, overrides?.toolGroupSingle),\n toolGroupContainer: cx(defaults.toolGroupContainer, overrides?.toolGroupContainer),\n toolGroupHeader: cx(defaults.toolGroupHeader, overrides?.toolGroupHeader),\n toolGroupIcon: cx(defaults.toolGroupIcon, overrides?.toolGroupIcon),\n toolGroupLabel: cx(defaults.toolGroupLabel, overrides?.toolGroupLabel),\n toolGroupChevron: cx(defaults.toolGroupChevron, overrides?.toolGroupChevron),\n toolGroupBody: cx(defaults.toolGroupBody, overrides?.toolGroupBody),\n toolItem: cx(defaults.toolItem, overrides?.toolItem),\n toolItemConnector: cx(defaults.toolItemConnector, overrides?.toolItemConnector),\n toolItemDot: cx(defaults.toolItemDot, overrides?.toolItemDot),\n toolItemLine: cx(defaults.toolItemLine, overrides?.toolItemLine),\n toolItemContent: cx(defaults.toolItemContent, overrides?.toolItemContent),\n toolItemHeader: cx(defaults.toolItemHeader, overrides?.toolItemHeader),\n toolItemIcon: cx(defaults.toolItemIcon, overrides?.toolItemIcon),\n toolItemLabel: cx(defaults.toolItemLabel, overrides?.toolItemLabel),\n toolItemSpinner: cx(defaults.toolItemSpinner, overrides?.toolItemSpinner),\n toolItemLink: cx(defaults.toolItemLink, overrides?.toolItemLink),\n toolItemChevron: cx(defaults.toolItemChevron, overrides?.toolItemChevron),\n toolItemBody: cx(defaults.toolItemBody, overrides?.toolItemBody),\n toolSection: cx(defaults.toolSection, overrides?.toolSection),\n toolSectionTitle: cx(defaults.toolSectionTitle, overrides?.toolSectionTitle),\n toolCode: cx(defaults.toolCode, overrides?.toolCode),\n toolCodeMuted: cx(defaults.toolCodeMuted, overrides?.toolCodeMuted),\n permissionPrompt: cx(defaults.permissionPrompt, overrides?.permissionPrompt),\n permissionHeader: cx(defaults.permissionHeader, overrides?.permissionHeader),\n permissionIcon: cx(defaults.permissionIcon, overrides?.permissionIcon),\n permissionTitle: cx(defaults.permissionTitle, overrides?.permissionTitle),\n permissionDescription: cx(defaults.permissionDescription, overrides?.permissionDescription),\n permissionActions: cx(defaults.permissionActions, overrides?.permissionActions),\n permissionButton: cx(defaults.permissionButton, overrides?.permissionButton),\n permissionAutoResolved: cx(defaults.permissionAutoResolved, overrides?.permissionAutoResolved),\n thinkingRow: cx(defaults.thinkingRow, overrides?.thinkingRow),\n thinkingAvatar: cx(defaults.thinkingAvatar, overrides?.thinkingAvatar),\n thinkingAvatarImage: cx(defaults.thinkingAvatarImage, overrides?.thinkingAvatarImage),\n thinkingAvatarLabel: cx(defaults.thinkingAvatarLabel, overrides?.thinkingAvatarLabel),\n thinkingIndicator: cx(defaults.thinkingIndicator, overrides?.thinkingIndicator),\n thinkingDot: cx(defaults.thinkingDot, overrides?.thinkingDot),\n endAnchor: cx(defaults.endAnchor, overrides?.endAnchor),\n});\n\nconst getMessageVariant = (entry: TranscriptEntry) => {\n if (entry.kind === \"tool\") return \"tool\";\n if (entry.kind === \"meta\") return entry.meta?.severity === \"error\" ? \"error\" : \"system\";\n if (entry.kind === \"reasoning\") return \"assistant\";\n if (entry.kind === \"permission\") return \"system\";\n if (entry.role === \"user\") return \"user\";\n return \"assistant\";\n};\n\nconst getToolItemLabel = (entry: TranscriptEntry) => {\n if (entry.kind === \"tool\") {\n const statusLabel = entry.toolStatus && entry.toolStatus !== \"completed\" ? ` (${entry.toolStatus.replaceAll(\"_\", \" \")})` : \"\";\n return `${entry.toolName ?? \"tool\"}${statusLabel}`;\n }\n\n if (entry.kind === \"reasoning\") {\n return `Reasoning${entry.reasoning?.visibility ? ` (${entry.reasoning.visibility})` : \"\"}`;\n }\n\n return entry.meta?.title ?? \"Status\";\n};\n\nconst getDefaultToolItemIcon = (entry: TranscriptEntry) => {\n if (entry.kind === \"tool\") return \"Tool\";\n if (entry.kind === \"reasoning\") return \"Thought\";\n return entry.meta?.severity === \"error\" ? \"Error\" : \"Info\";\n};\n\nconst getDefaultToolGroupSummary = (entries: TranscriptEntry[]) => {\n const count = entries.length;\n return `${count} Event${count === 1 ? \"\" : \"s\"}`;\n};\n\nconst getPermissionReplyForOption = (kind: string): PermissionReply => {\n if (kind === \"allow_once\") return \"once\";\n if (kind === \"allow_always\") return \"always\";\n return \"reject\";\n};\n\nconst getPermissionOptionLabel = (option: PermissionOption) => {\n if (option.name) return option.name;\n if (option.kind === \"allow_once\") return \"Allow Once\";\n if (option.kind === \"allow_always\") return \"Always Allow\";\n if (option.kind === \"reject_once\") return \"Reject\";\n if (option.kind === \"reject_always\") return \"Reject Always\";\n return option.kind;\n};\n\nconst getPermissionOptionTone = (kind: string) => (kind.startsWith(\"allow\") ? \"allow\" : \"reject\");\n\nconst defaultRenderMessageText = (entry: TranscriptEntry) => entry.text;\nconst defaultRenderPendingIndicator = () => \"...\";\nconst defaultRenderChevron = (expanded: boolean) => (expanded ? \"▾\" : \"▸\");\nconst defaultRenderEventLinkContent = () => \"Open\";\nconst defaultRenderPermissionIcon = () => \"Permission\";\nconst defaultRenderPermissionOptionContent = ({ label }: PermissionOptionRenderContext) => label;\nconst defaultIsDividerEntry = (entry: TranscriptEntry) => entry.kind === \"meta\" && DEFAULT_DIVIDER_TITLES.has(entry.meta?.title ?? \"\");\n\nconst defaultCanOpenEvent = (entry: TranscriptEntry) => Boolean(entry.eventId);\n\nconst buildGroupedEntries = (entries: TranscriptEntry[], isDividerEntry: (entry: TranscriptEntry) => boolean): GroupedEntries[] => {\n const groupedEntries: GroupedEntries[] = [];\n let currentToolGroup: TranscriptEntry[] = [];\n\n const flushToolGroup = () => {\n if (currentToolGroup.length === 0) {\n return;\n }\n groupedEntries.push({ type: \"tool-group\", entries: currentToolGroup });\n currentToolGroup = [];\n };\n\n for (const entry of entries) {\n if (isDividerEntry(entry)) {\n flushToolGroup();\n groupedEntries.push({ type: \"divider\", entries: [entry] });\n continue;\n }\n\n if (entry.kind === \"permission\") {\n flushToolGroup();\n groupedEntries.push({ type: \"permission\", entries: [entry] });\n continue;\n }\n\n if (entry.kind === \"tool\" || entry.kind === \"reasoning\" || entry.kind === \"meta\") {\n currentToolGroup.push(entry);\n continue;\n }\n\n flushToolGroup();\n groupedEntries.push({ type: \"message\", entries: [entry] });\n }\n\n flushToolGroup();\n return groupedEntries;\n};\n\nconst getGroupedEntryKey = (group: GroupedEntries, index: number): string => {\n const firstEntry = group.entries[0];\n\n if (group.type === \"tool-group\") {\n return `tool-group:${firstEntry?.id ?? index}`;\n }\n\n return firstEntry?.id ?? `${group.type}:${index}`;\n};\n\nconst ToolItem = ({\n entry,\n isLast,\n expanded,\n onExpandedChange,\n classNames,\n onEventClick,\n canOpenEvent,\n renderInlinePendingIndicator,\n renderToolItemIcon,\n renderChevron,\n renderEventLinkContent,\n}: {\n entry: TranscriptEntry;\n isLast: boolean;\n expanded: boolean;\n onExpandedChange: (expanded: boolean) => void;\n classNames: AgentTranscriptClassNames;\n onEventClick?: (eventId: string) => void;\n canOpenEvent: (entry: TranscriptEntry) => boolean;\n renderInlinePendingIndicator: () => ReactNode;\n renderToolItemIcon: (entry: TranscriptEntry) => ReactNode;\n renderChevron: (expanded: boolean) => ReactNode;\n renderEventLinkContent: (entry: TranscriptEntry) => ReactNode;\n}) => {\n const isTool = entry.kind === \"tool\";\n const isReasoning = entry.kind === \"reasoning\";\n const isMeta = entry.kind === \"meta\";\n const isComplete = isTool && (entry.toolStatus === \"completed\" || entry.toolStatus === \"failed\");\n const isFailed = isTool && entry.toolStatus === \"failed\";\n const isInProgress = isTool && entry.toolStatus === \"in_progress\";\n const hasContent = isTool\n ? Boolean(entry.toolInput || entry.toolOutput)\n : isReasoning\n ? Boolean(entry.reasoning?.text?.trim())\n : Boolean(entry.meta?.detail?.trim());\n const showEventLink = Boolean(entry.eventId && onEventClick && canOpenEvent(entry));\n\n return (\n <div\n className={cx(classNames.toolItem, isLast && \"last\", isFailed && \"failed\")}\n data-slot=\"tool-item\"\n data-kind={entry.kind}\n data-state={entry.toolStatus}\n data-last={isLast ? \"true\" : undefined}\n data-failed={isFailed ? \"true\" : undefined}\n >\n <div className={classNames.toolItemConnector} data-slot=\"tool-item-connector\">\n <div className={classNames.toolItemDot} data-slot=\"tool-item-dot\" />\n {!isLast ? <div className={classNames.toolItemLine} data-slot=\"tool-item-line\" /> : null}\n </div>\n <div className={classNames.toolItemContent} data-slot=\"tool-item-content\">\n <button\n type=\"button\"\n className={cx(classNames.toolItemHeader, expanded && \"expanded\")}\n data-slot=\"tool-item-header\"\n data-expanded={expanded ? \"true\" : undefined}\n data-has-content={hasContent ? \"true\" : undefined}\n disabled={!hasContent}\n onClick={() => {\n if (hasContent) {\n onExpandedChange(!expanded);\n }\n }}\n >\n <span className={classNames.toolItemIcon} data-slot=\"tool-item-icon\">\n {renderToolItemIcon(entry)}\n </span>\n <span className={classNames.toolItemLabel} data-slot=\"tool-item-label\">\n {getToolItemLabel(entry)}\n </span>\n {isInProgress ? (\n <span className={classNames.toolItemSpinner} data-slot=\"tool-item-spinner\">\n {renderInlinePendingIndicator()}\n </span>\n ) : null}\n {showEventLink ? (\n <span\n className={classNames.toolItemLink}\n data-slot=\"tool-item-link\"\n role=\"button\"\n tabIndex={0}\n onClick={(event) => {\n event.stopPropagation();\n onEventClick?.(entry.eventId!);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n event.stopPropagation();\n onEventClick?.(entry.eventId!);\n }\n }}\n >\n {renderEventLinkContent(entry)}\n </span>\n ) : null}\n {hasContent ? (\n <span className={classNames.toolItemChevron} data-slot=\"tool-item-chevron\">\n {renderChevron(expanded)}\n </span>\n ) : null}\n </button>\n {expanded && hasContent ? (\n <div className={classNames.toolItemBody} data-slot=\"tool-item-body\">\n {isTool && entry.toolInput ? (\n <div className={classNames.toolSection} data-slot=\"tool-section\" data-section=\"input\">\n <div className={classNames.toolSectionTitle} data-slot=\"tool-section-title\">\n Input\n </div>\n <pre className={classNames.toolCode} data-slot=\"tool-code\">\n {entry.toolInput}\n </pre>\n </div>\n ) : null}\n {isTool && isComplete && entry.toolOutput ? (\n <div className={classNames.toolSection} data-slot=\"tool-section\" data-section=\"output\">\n <div className={classNames.toolSectionTitle} data-slot=\"tool-section-title\">\n Output\n </div>\n <pre className={classNames.toolCode} data-slot=\"tool-code\">\n {entry.toolOutput}\n </pre>\n </div>\n ) : null}\n {isReasoning && entry.reasoning?.text ? (\n <div className={classNames.toolSection} data-slot=\"tool-section\" data-section=\"reasoning\">\n <pre className={cx(classNames.toolCode, classNames.toolCodeMuted)} data-slot=\"tool-code\">\n {entry.reasoning.text}\n </pre>\n </div>\n ) : null}\n {isMeta && entry.meta?.detail ? (\n <div className={classNames.toolSection} data-slot=\"tool-section\" data-section=\"meta\">\n <pre className={classNames.toolCode} data-slot=\"tool-code\">\n {entry.meta.detail}\n </pre>\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n );\n};\n\nconst ToolGroup = ({\n entries,\n expanded,\n onExpandedChange,\n expandedItemIds,\n onToolItemExpandedChange,\n classNames,\n onEventClick,\n canOpenEvent,\n getToolGroupSummary,\n renderInlinePendingIndicator,\n renderToolItemIcon,\n renderToolGroupIcon,\n renderChevron,\n renderEventLinkContent,\n}: {\n entries: TranscriptEntry[];\n expanded: boolean;\n onExpandedChange: (expanded: boolean) => void;\n expandedItemIds: Record<string, boolean>;\n onToolItemExpandedChange: (entryId: string, expanded: boolean) => void;\n classNames: AgentTranscriptClassNames;\n onEventClick?: (eventId: string) => void;\n canOpenEvent: (entry: TranscriptEntry) => boolean;\n getToolGroupSummary: (entries: TranscriptEntry[]) => string;\n renderInlinePendingIndicator: () => ReactNode;\n renderToolItemIcon: (entry: TranscriptEntry) => ReactNode;\n renderToolGroupIcon: (entries: TranscriptEntry[], expanded: boolean) => ReactNode;\n renderChevron: (expanded: boolean) => ReactNode;\n renderEventLinkContent: (entry: TranscriptEntry) => ReactNode;\n}) => {\n const hasFailed = entries.some((entry) => entry.kind === \"tool\" && entry.toolStatus === \"failed\");\n\n if (entries.length === 1) {\n return (\n <div className={classNames.toolGroupSingle} data-slot=\"tool-group-single\">\n <ToolItem\n entry={entries[0]}\n isLast={true}\n expanded={Boolean(expandedItemIds[entries[0]!.id])}\n onExpandedChange={(nextExpanded) => onToolItemExpandedChange(entries[0]!.id, nextExpanded)}\n classNames={classNames}\n onEventClick={onEventClick}\n canOpenEvent={canOpenEvent}\n renderInlinePendingIndicator={renderInlinePendingIndicator}\n renderToolItemIcon={renderToolItemIcon}\n renderChevron={renderChevron}\n renderEventLinkContent={renderEventLinkContent}\n />\n </div>\n );\n }\n\n return (\n <div className={cx(classNames.toolGroupContainer, hasFailed && \"failed\")} data-slot=\"tool-group\" data-failed={hasFailed ? \"true\" : undefined}>\n <button\n type=\"button\"\n className={cx(classNames.toolGroupHeader, expanded && \"expanded\")}\n data-slot=\"tool-group-header\"\n data-expanded={expanded ? \"true\" : undefined}\n onClick={() => onExpandedChange(!expanded)}\n >\n <span className={classNames.toolGroupIcon} data-slot=\"tool-group-icon\">\n {renderToolGroupIcon(entries, expanded)}\n </span>\n <span className={classNames.toolGroupLabel} data-slot=\"tool-group-label\">\n {getToolGroupSummary(entries)}\n </span>\n <span className={classNames.toolGroupChevron} data-slot=\"tool-group-chevron\">\n {renderChevron(expanded)}\n </span>\n </button>\n {expanded ? (\n <div className={classNames.toolGroupBody} data-slot=\"tool-group-body\">\n {entries.map((entry, index) => (\n <ToolItem\n key={entry.id}\n entry={entry}\n isLast={index === entries.length - 1}\n expanded={Boolean(expandedItemIds[entry.id])}\n onExpandedChange={(nextExpanded) => onToolItemExpandedChange(entry.id, nextExpanded)}\n classNames={classNames}\n onEventClick={onEventClick}\n canOpenEvent={canOpenEvent}\n renderInlinePendingIndicator={renderInlinePendingIndicator}\n renderToolItemIcon={renderToolItemIcon}\n renderChevron={renderChevron}\n renderEventLinkContent={renderEventLinkContent}\n />\n ))}\n </div>\n ) : null}\n </div>\n );\n};\n\nconst PermissionPrompt = ({\n entry,\n classNames,\n onPermissionReply,\n renderPermissionIcon,\n renderPermissionOptionContent,\n}: {\n entry: TranscriptEntry;\n classNames: AgentTranscriptClassNames;\n onPermissionReply?: (permissionId: string, reply: PermissionReply) => void;\n renderPermissionIcon: (entry: TranscriptEntry) => ReactNode;\n renderPermissionOptionContent: (context: PermissionOptionRenderContext) => ReactNode;\n}) => {\n const permission = entry.permission;\n if (!permission) {\n return null;\n }\n\n const resolved = Boolean(permission.resolved);\n const selectedOptionId = permission.selectedOptionId;\n const canReply = Boolean(onPermissionReply) && !resolved;\n\n return (\n <div className={cx(classNames.permissionPrompt, resolved && \"resolved\")} data-slot=\"permission-prompt\" data-resolved={resolved ? \"true\" : undefined}>\n <div className={classNames.permissionHeader} data-slot=\"permission-header\">\n <span className={classNames.permissionIcon} data-slot=\"permission-icon\">\n {renderPermissionIcon(entry)}\n </span>\n <span className={classNames.permissionTitle} data-slot=\"permission-title\">\n {permission.title}\n </span>\n </div>\n {permission.description ? (\n <div className={classNames.permissionDescription} data-slot=\"permission-description\">\n {permission.description}\n </div>\n ) : null}\n <div className={classNames.permissionActions} data-slot=\"permission-actions\">\n {permission.options.map((option) => {\n const reply = getPermissionReplyForOption(option.kind);\n const label = getPermissionOptionLabel(option);\n const selected = resolved && selectedOptionId === option.optionId;\n const dimmed = resolved && !selected && selectedOptionId != null;\n const tone = getPermissionOptionTone(option.kind);\n\n return (\n <button\n key={option.optionId}\n type=\"button\"\n className={cx(classNames.permissionButton, tone, selected && \"selected\", dimmed && \"dimmed\")}\n data-slot=\"permission-button\"\n data-tone={tone}\n data-selected={selected ? \"true\" : undefined}\n data-dimmed={dimmed ? \"true\" : undefined}\n disabled={!canReply}\n onClick={() => onPermissionReply?.(permission.permissionId, reply)}\n >\n {renderPermissionOptionContent({\n entry,\n option,\n label,\n reply,\n selected,\n dimmed,\n resolved,\n })}\n </button>\n );\n })}\n {resolved && !selectedOptionId ? (\n <span className={classNames.permissionAutoResolved} data-slot=\"permission-auto-resolved\">\n Auto-resolved\n </span>\n ) : null}\n </div>\n </div>\n );\n};\n\nexport const AgentTranscript = ({\n entries,\n className,\n classNames: classNameOverrides,\n endRef,\n scrollRef,\n scrollToEntryId,\n sessionError,\n eventError,\n isThinking,\n agentId,\n virtualize = false,\n onAtBottomChange,\n onEventClick,\n onPermissionReply,\n isDividerEntry = defaultIsDividerEntry,\n canOpenEvent = defaultCanOpenEvent,\n getToolGroupSummary = getDefaultToolGroupSummary,\n renderMessageText = defaultRenderMessageText,\n renderInlinePendingIndicator = defaultRenderPendingIndicator,\n renderThinkingState,\n renderToolItemIcon = getDefaultToolItemIcon,\n renderToolGroupIcon = () => null,\n renderChevron = defaultRenderChevron,\n renderEventLinkContent = defaultRenderEventLinkContent,\n renderPermissionIcon = defaultRenderPermissionIcon,\n renderPermissionOptionContent = defaultRenderPermissionOptionContent,\n}: AgentTranscriptProps) => {\n const resolvedClassNames = useMemo(() => mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides), [classNameOverrides]);\n const groupedEntries = useMemo(() => buildGroupedEntries(entries, isDividerEntry), [entries, isDividerEntry]);\n const [expandedToolGroups, setExpandedToolGroups] = useState<Record<string, boolean>>({});\n const [expandedToolItems, setExpandedToolItems] = useState<Record<string, boolean>>({});\n const lastScrollTargetRef = useRef<string | null>(null);\n const isVirtualized = virtualize && Boolean(scrollRef);\n const { virtualizer, isFollowingRef } = useTranscriptVirtualizer(groupedEntries, isVirtualized ? scrollRef : undefined, onAtBottomChange);\n\n useEffect(() => {\n if (!scrollToEntryId) {\n lastScrollTargetRef.current = null;\n return;\n }\n\n if (!isVirtualized || scrollToEntryId === lastScrollTargetRef.current) {\n return;\n }\n\n const targetIndex = groupedEntries.findIndex((group) => group.entries.some((entry) => entry.id === scrollToEntryId));\n if (targetIndex < 0) {\n return;\n }\n\n lastScrollTargetRef.current = scrollToEntryId;\n\n const frameId = requestAnimationFrame(() => {\n virtualizer.scrollToIndex(targetIndex, {\n align: \"center\",\n behavior: \"smooth\",\n });\n });\n\n return () => {\n cancelAnimationFrame(frameId);\n };\n }, [groupedEntries, isVirtualized, scrollToEntryId, virtualizer]);\n\n useEffect(() => {\n if (!isVirtualized || !scrollRef?.current || !isFollowingRef.current) {\n return;\n }\n\n const scrollElement = scrollRef.current;\n const frameId = requestAnimationFrame(() => {\n scrollElement.scrollTo({ top: scrollElement.scrollHeight });\n });\n\n return () => {\n cancelAnimationFrame(frameId);\n };\n }, [eventError, isFollowingRef, isThinking, isVirtualized, scrollRef, sessionError]);\n\n const setToolGroupExpanded = (groupKey: string, expanded: boolean) => {\n setExpandedToolGroups((current) => {\n if (current[groupKey] === expanded) {\n return current;\n }\n return { ...current, [groupKey]: expanded };\n });\n };\n\n const setToolItemExpanded = (entryId: string, expanded: boolean) => {\n setExpandedToolItems((current) => {\n if (current[entryId] === expanded) {\n return current;\n }\n return { ...current, [entryId]: expanded };\n });\n };\n\n const renderGroup = (group: GroupedEntries, index: number) => {\n if (group.type === \"divider\") {\n const entry = group.entries[0];\n const title = entry.meta?.title ?? \"Status\";\n return (\n <div key={entry.id} className={resolvedClassNames.divider} data-slot=\"divider\">\n <div className={resolvedClassNames.dividerLine} data-slot=\"divider-line\" />\n <span className={resolvedClassNames.dividerText} data-slot=\"divider-text\">\n {title}\n </span>\n <div className={resolvedClassNames.dividerLine} data-slot=\"divider-line\" />\n </div>\n );\n }\n\n if (group.type === \"tool-group\") {\n const groupKey = getGroupedEntryKey(group, index);\n\n return (\n <ToolGroup\n key={groupKey}\n entries={group.entries}\n expanded={Boolean(expandedToolGroups[groupKey])}\n onExpandedChange={(expanded) => setToolGroupExpanded(groupKey, expanded)}\n expandedItemIds={expandedToolItems}\n onToolItemExpandedChange={setToolItemExpanded}\n classNames={resolvedClassNames}\n onEventClick={onEventClick}\n canOpenEvent={canOpenEvent}\n getToolGroupSummary={getToolGroupSummary}\n renderInlinePendingIndicator={renderInlinePendingIndicator}\n renderToolItemIcon={renderToolItemIcon}\n renderToolGroupIcon={renderToolGroupIcon}\n renderChevron={renderChevron}\n renderEventLinkContent={renderEventLinkContent}\n />\n );\n }\n\n if (group.type === \"permission\") {\n const entry = group.entries[0];\n return (\n <PermissionPrompt\n key={entry.id}\n entry={entry}\n classNames={resolvedClassNames}\n onPermissionReply={onPermissionReply}\n renderPermissionIcon={renderPermissionIcon}\n renderPermissionOptionContent={renderPermissionOptionContent}\n />\n );\n }\n\n const entry = group.entries[0];\n const messageVariant = getMessageVariant(entry);\n\n return (\n <div\n key={entry.id}\n className={cx(resolvedClassNames.message, messageVariant, \"no-avatar\")}\n data-slot=\"message\"\n data-kind={entry.kind}\n data-role={entry.role}\n data-variant={messageVariant}\n data-severity={entry.meta?.severity}\n >\n <div className={resolvedClassNames.messageContent} data-slot=\"message-content\">\n {entry.text ? (\n <div className={resolvedClassNames.messageText} data-slot=\"message-text\">\n {renderMessageText(entry)}\n </div>\n ) : (\n <span className={resolvedClassNames.thinkingIndicator} data-slot=\"thinking-indicator\">\n {renderInlinePendingIndicator()}\n </span>\n )}\n </div>\n </div>\n );\n };\n\n return (\n <div className={cx(resolvedClassNames.root, className)} data-slot=\"root\" data-virtualized={isVirtualized ? \"true\" : undefined}>\n {isVirtualized ? (\n <div\n data-slot=\"virtual-list\"\n style={{\n height: `${virtualizer.getTotalSize()}px`,\n position: \"relative\",\n width: \"100%\",\n }}\n >\n {virtualizer.getVirtualItems().map((virtualItem) => {\n const group = groupedEntries[virtualItem.index];\n if (!group) {\n return null;\n }\n\n return (\n <div\n key={getGroupedEntryKey(group, virtualItem.index)}\n data-index={virtualItem.index}\n ref={(node) => {\n if (node) {\n virtualizer.measureElement(node);\n }\n }}\n style={{\n left: 0,\n position: \"absolute\",\n top: 0,\n transform: `translateY(${virtualItem.start}px)`,\n width: \"100%\",\n }}\n >\n <div style={{ paddingBottom: virtualItem.index === groupedEntries.length - 1 ? 0 : `${VIRTUAL_GROUP_GAP_PX}px` }}>\n {renderGroup(group, virtualItem.index)}\n </div>\n </div>\n );\n })}\n </div>\n ) : (\n groupedEntries.map((group, index) => renderGroup(group, index))\n )}\n {sessionError ? (\n <div className={resolvedClassNames.error} data-slot=\"error\" data-source=\"session\">\n {sessionError}\n </div>\n ) : null}\n {eventError ? (\n <div className={resolvedClassNames.error} data-slot=\"error\" data-source=\"event\">\n {eventError}\n </div>\n ) : null}\n {isThinking\n ? (renderThinkingState?.({ agentId }) ?? (\n <div className={resolvedClassNames.thinkingRow} data-slot=\"thinking-row\">\n <span className={resolvedClassNames.thinkingIndicator} data-slot=\"thinking-indicator\">\n Thinking...\n </span>\n </div>\n ))\n : null}\n {!isVirtualized ? <div ref={endRef} className={resolvedClassNames.endAnchor} data-slot=\"end-anchor\" /> : null}\n </div>\n );\n};\n","\"use client\";\n\nimport type { RefObject } from \"react\";\nimport { useEffect, useRef } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\n\nexport function useTranscriptVirtualizer<T>(items: T[], scrollElementRef?: RefObject<HTMLDivElement>, onAtBottomChange?: (atBottom: boolean) => void) {\n const isFollowingRef = useRef(true);\n\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => scrollElementRef?.current ?? null,\n estimateSize: () => 80,\n measureElement: (element) => element.getBoundingClientRect().height,\n overscan: 10,\n });\n\n virtualizer.shouldAdjustScrollPositionOnItemSizeChange = () => isFollowingRef.current;\n\n useEffect(() => {\n const scrollElement = scrollElementRef?.current;\n if (!scrollElement) {\n return;\n }\n\n const updateFollowState = () => {\n const atBottom = scrollElement.scrollHeight - scrollElement.scrollTop - scrollElement.clientHeight < 50;\n isFollowingRef.current = atBottom;\n onAtBottomChange?.(atBottom);\n };\n\n updateFollowState();\n scrollElement.addEventListener(\"scroll\", updateFollowState, { passive: true });\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", updateFollowState);\n };\n }, [onAtBottomChange, scrollElementRef]);\n\n useEffect(() => {\n if (!isFollowingRef.current || items.length === 0) {\n return;\n }\n\n const frameId = requestAnimationFrame(() => {\n virtualizer.scrollToIndex(items.length - 1, {\n align: \"end\",\n behavior: \"smooth\",\n });\n });\n\n return () => {\n cancelAnimationFrame(frameId);\n };\n }, [items.length, virtualizer]);\n\n return { virtualizer, isFollowingRef };\n}\n","\"use client\";\n\nimport type { KeyboardEvent, ReactNode, Ref, TextareaHTMLAttributes } from \"react\";\n\nexport interface ChatComposerClassNames {\n root: string;\n form: string;\n input: string;\n submit: string;\n submitContent: string;\n}\n\nexport interface ChatComposerProps {\n message: string;\n onMessageChange: (value: string) => void;\n onSubmit: () => void;\n onKeyDown?: (event: KeyboardEvent<HTMLTextAreaElement>) => void;\n placeholder?: string;\n disabled?: boolean;\n submitDisabled?: boolean;\n allowEmptySubmit?: boolean;\n submitLabel?: string;\n className?: string;\n classNames?: Partial<ChatComposerClassNames>;\n inputRef?: Ref<HTMLTextAreaElement>;\n rows?: number;\n textareaProps?: Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\" | \"disabled\" | \"onChange\" | \"onKeyDown\" | \"placeholder\" | \"rows\" | \"value\">;\n renderSubmitContent?: () => ReactNode;\n renderFooter?: () => ReactNode;\n}\n\nconst DEFAULT_CLASS_NAMES: ChatComposerClassNames = {\n root: \"sa-chat-composer\",\n form: \"sa-chat-composer-form\",\n input: \"sa-chat-composer-input\",\n submit: \"sa-chat-composer-submit\",\n submitContent: \"sa-chat-composer-submit-content\",\n};\n\nconst cx = (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(\" \");\n\nconst mergeClassNames = (defaults: ChatComposerClassNames, overrides?: Partial<ChatComposerClassNames>): ChatComposerClassNames => ({\n root: cx(defaults.root, overrides?.root),\n form: cx(defaults.form, overrides?.form),\n input: cx(defaults.input, overrides?.input),\n submit: cx(defaults.submit, overrides?.submit),\n submitContent: cx(defaults.submitContent, overrides?.submitContent),\n});\n\nexport const ChatComposer = ({\n message,\n onMessageChange,\n onSubmit,\n onKeyDown,\n placeholder,\n disabled = false,\n submitDisabled = false,\n allowEmptySubmit = false,\n submitLabel = \"Send\",\n className,\n classNames: classNameOverrides,\n inputRef,\n rows = 1,\n textareaProps,\n renderSubmitContent,\n renderFooter,\n}: ChatComposerProps) => {\n const resolvedClassNames = mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides);\n const isSubmitDisabled = disabled || submitDisabled || (!allowEmptySubmit && message.trim().length === 0);\n\n return (\n <div className={cx(resolvedClassNames.root, className)} data-slot=\"root\">\n <form\n className={resolvedClassNames.form}\n data-slot=\"form\"\n onSubmit={(event) => {\n event.preventDefault();\n if (!isSubmitDisabled) {\n onSubmit();\n }\n }}\n >\n <textarea\n {...textareaProps}\n ref={inputRef}\n className={resolvedClassNames.input}\n data-slot=\"input\"\n data-disabled={disabled ? \"true\" : undefined}\n data-empty={message.trim().length === 0 ? \"true\" : undefined}\n value={message}\n onChange={(event) => onMessageChange(event.target.value)}\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n rows={rows}\n disabled={disabled}\n />\n {renderFooter?.()}\n <button\n type=\"submit\"\n className={resolvedClassNames.submit}\n data-slot=\"submit\"\n data-disabled={isSubmitDisabled ? \"true\" : undefined}\n disabled={isSubmitDisabled}\n aria-label={submitLabel}\n title={submitLabel}\n >\n <span className={resolvedClassNames.submitContent} data-slot=\"submit-content\">\n {renderSubmitContent?.() ?? submitLabel}\n </span>\n </button>\n </form>\n </div>\n );\n};\n","\"use client\";\n\nimport type { ReactNode, RefObject } from \"react\";\nimport { AgentTranscript, type AgentTranscriptClassNames, type AgentTranscriptProps, type TranscriptEntry } from \"./AgentTranscript.tsx\";\nimport { ChatComposer, type ChatComposerClassNames, type ChatComposerProps } from \"./ChatComposer.tsx\";\n\nexport interface AgentConversationClassNames {\n root: string;\n transcript: string;\n emptyState: string;\n composer: string;\n}\n\nexport interface AgentConversationProps {\n entries: TranscriptEntry[];\n className?: string;\n classNames?: Partial<AgentConversationClassNames>;\n emptyState?: ReactNode;\n transcriptClassName?: string;\n transcriptClassNames?: Partial<AgentTranscriptClassNames>;\n scrollRef?: RefObject<HTMLDivElement>;\n composerClassName?: string;\n composerClassNames?: Partial<ChatComposerClassNames>;\n transcriptProps?: Omit<AgentTranscriptProps, \"entries\" | \"className\" | \"classNames\" | \"scrollRef\">;\n composerProps?: Omit<ChatComposerProps, \"className\" | \"classNames\">;\n}\n\nconst DEFAULT_CLASS_NAMES: AgentConversationClassNames = {\n root: \"sa-agent-conversation\",\n transcript: \"sa-agent-conversation-transcript\",\n emptyState: \"sa-agent-conversation-empty-state\",\n composer: \"sa-agent-conversation-composer\",\n};\n\nconst cx = (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(\" \");\n\nconst mergeClassNames = (defaults: AgentConversationClassNames, overrides?: Partial<AgentConversationClassNames>): AgentConversationClassNames => ({\n root: cx(defaults.root, overrides?.root),\n transcript: cx(defaults.transcript, overrides?.transcript),\n emptyState: cx(defaults.emptyState, overrides?.emptyState),\n composer: cx(defaults.composer, overrides?.composer),\n});\n\nexport const AgentConversation = ({\n entries,\n className,\n classNames: classNameOverrides,\n emptyState,\n transcriptClassName,\n transcriptClassNames,\n scrollRef,\n composerClassName,\n composerClassNames,\n transcriptProps,\n composerProps,\n}: AgentConversationProps) => {\n const resolvedClassNames = mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides);\n const hasTranscriptContent = entries.length > 0 || Boolean(transcriptProps?.sessionError) || Boolean(transcriptProps?.eventError);\n\n return (\n <div className={cx(resolvedClassNames.root, className)} data-slot=\"root\">\n {hasTranscriptContent ? (\n scrollRef ? (\n <div className={cx(resolvedClassNames.transcript, transcriptClassName)} data-slot=\"transcript\" ref={scrollRef}>\n <AgentTranscript entries={entries} classNames={transcriptClassNames} {...transcriptProps} />\n </div>\n ) : (\n <AgentTranscript\n entries={entries}\n className={cx(resolvedClassNames.transcript, transcriptClassName)}\n classNames={transcriptClassNames}\n {...transcriptProps}\n />\n )\n ) : emptyState ? (\n <div className={resolvedClassNames.emptyState} data-slot=\"empty-state\">\n {emptyState}\n </div>\n ) : null}\n {composerProps ? (\n <ChatComposer className={cx(resolvedClassNames.composer, composerClassName)} classNames={composerClassNames} {...composerProps} />\n ) : null}\n </div>\n );\n};\n","\"use client\";\n\nimport type { FitAddon as GhosttyFitAddon, Terminal as GhosttyTerminal } from \"ghostty-web\";\nimport type { CSSProperties } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type {\n SandboxAgent,\n TerminalErrorStatus,\n TerminalExitStatus,\n TerminalReadyStatus,\n} from \"sandbox-agent\";\n\ntype ConnectionState = \"connecting\" | \"ready\" | \"closed\" | \"error\";\n\nexport type ProcessTerminalClient = Pick<SandboxAgent, \"connectProcessTerminal\">;\n\nexport interface ProcessTerminalProps {\n client: ProcessTerminalClient;\n processId: string;\n className?: string;\n style?: CSSProperties;\n terminalStyle?: CSSProperties;\n statusBarStyleOverride?: CSSProperties;\n height?: number | string;\n showStatusBar?: boolean;\n onExit?: (status: TerminalExitStatus) => void;\n onError?: (error: TerminalErrorStatus | Error) => void;\n}\n\nconst terminalTheme = {\n background: \"#09090b\",\n foreground: \"#f4f4f5\",\n cursor: \"#f97316\",\n cursorAccent: \"#09090b\",\n selectionBackground: \"#27272a\",\n black: \"#18181b\",\n red: \"#f87171\",\n green: \"#4ade80\",\n yellow: \"#fbbf24\",\n blue: \"#60a5fa\",\n magenta: \"#f472b6\",\n cyan: \"#22d3ee\",\n white: \"#e4e4e7\",\n brightBlack: \"#3f3f46\",\n brightRed: \"#fb7185\",\n brightGreen: \"#86efac\",\n brightYellow: \"#fde047\",\n brightBlue: \"#93c5fd\",\n brightMagenta: \"#f9a8d4\",\n brightCyan: \"#67e8f9\",\n brightWhite: \"#fafafa\",\n};\n\nconst shellStyle: CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 10,\n background: \"rgba(0, 0, 0, 0.3)\",\n};\n\nconst statusBarStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: 12,\n padding: \"8px 12px\",\n borderBottom: \"1px solid rgba(255, 255, 255, 0.08)\",\n background: \"rgba(0, 0, 0, 0.2)\",\n color: \"rgba(244, 244, 245, 0.86)\",\n fontSize: 11,\n lineHeight: 1.4,\n};\n\nconst hostBaseStyle: CSSProperties = {\n minHeight: 320,\n padding: 10,\n overflow: \"hidden\",\n};\n\nconst exitCodeStyle: CSSProperties = {\n fontFamily: \"ui-monospace, SFMono-Regular, SF Mono, Menlo, monospace\",\n opacity: 0.72,\n};\n\nconst getStatusColor = (state: ConnectionState): string => {\n switch (state) {\n case \"ready\":\n return \"#4ade80\";\n case \"error\":\n return \"#fb7185\";\n case \"closed\":\n return \"#fbbf24\";\n default:\n return \"rgba(244, 244, 245, 0.72)\";\n }\n};\n\nexport const ProcessTerminal = ({\n client,\n processId,\n className,\n style,\n terminalStyle,\n statusBarStyleOverride,\n height = 360,\n showStatusBar = true,\n onExit,\n onError,\n}: ProcessTerminalProps) => {\n const hostRef = useRef<HTMLDivElement | null>(null);\n const [connectionState, setConnectionState] = useState<ConnectionState>(\"connecting\");\n const [statusMessage, setStatusMessage] = useState(\"Connecting to PTY...\");\n const [exitCode, setExitCode] = useState<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n let terminal: GhosttyTerminal | null = null;\n let fitAddon: GhosttyFitAddon | null = null;\n let session: ReturnType<ProcessTerminalClient[\"connectProcessTerminal\"]> | null = null;\n let resizeRaf = 0;\n let removeDataListener: { dispose(): void } | null = null;\n let removeResizeListener: { dispose(): void } | null = null;\n\n setConnectionState(\"connecting\");\n setStatusMessage(\"Connecting to PTY...\");\n setExitCode(null);\n\n const syncSize = () => {\n if (!terminal || !session) {\n return;\n }\n\n session.resize({\n cols: terminal.cols,\n rows: terminal.rows,\n });\n };\n\n const connect = async () => {\n try {\n const ghostty = await import(\"ghostty-web\");\n await ghostty.init();\n\n if (cancelled || !hostRef.current) {\n return;\n }\n\n terminal = new ghostty.Terminal({\n allowTransparency: true,\n cursorBlink: true,\n cursorStyle: \"block\",\n fontFamily: \"ui-monospace, SFMono-Regular, SF Mono, Menlo, monospace\",\n fontSize: 13,\n smoothScrollDuration: 90,\n theme: terminalTheme,\n });\n fitAddon = new ghostty.FitAddon();\n\n terminal.open(hostRef.current);\n const terminalRoot = hostRef.current.firstElementChild;\n if (terminalRoot instanceof HTMLElement) {\n terminalRoot.style.width = \"100%\";\n terminalRoot.style.height = \"100%\";\n }\n terminal.loadAddon(fitAddon);\n fitAddon.fit();\n fitAddon.observeResize();\n terminal.focus();\n\n removeDataListener = terminal.onData((data) => {\n session?.sendInput(data);\n });\n\n removeResizeListener = terminal.onResize(() => {\n if (resizeRaf) {\n window.cancelAnimationFrame(resizeRaf);\n }\n resizeRaf = window.requestAnimationFrame(syncSize);\n });\n\n const nextSession = client.connectProcessTerminal(processId);\n session = nextSession;\n\n nextSession.onReady((frame: TerminalReadyStatus) => {\n if (cancelled || frame.type !== \"ready\") {\n return;\n }\n\n setConnectionState(\"ready\");\n setStatusMessage(\"Connected\");\n syncSize();\n });\n\n nextSession.onData((bytes: Uint8Array) => {\n if (cancelled || !terminal) {\n return;\n }\n terminal.write(bytes);\n });\n\n nextSession.onExit((frame: TerminalExitStatus) => {\n if (cancelled || frame.type !== \"exit\") {\n return;\n }\n\n setConnectionState(\"closed\");\n setExitCode(frame.exitCode ?? null);\n setStatusMessage(frame.exitCode == null ? \"Process exited.\" : `Process exited with code ${frame.exitCode}.`);\n onExit?.(frame);\n });\n\n nextSession.onError((error: TerminalErrorStatus | Error) => {\n if (cancelled) {\n return;\n }\n\n setConnectionState(\"error\");\n setStatusMessage(error instanceof Error ? error.message : error.message);\n onError?.(error);\n });\n\n nextSession.onClose(() => {\n if (cancelled) {\n return;\n }\n\n setConnectionState((current) => (current === \"error\" ? current : \"closed\"));\n setStatusMessage((current) => (current === \"Connected\" ? \"Terminal disconnected.\" : current));\n });\n } catch (error) {\n if (cancelled) {\n return;\n }\n\n const nextError = error instanceof Error ? error : new Error(\"Failed to initialize terminal.\");\n setConnectionState(\"error\");\n setStatusMessage(nextError.message);\n onError?.(nextError);\n }\n };\n\n void connect();\n\n return () => {\n cancelled = true;\n if (resizeRaf) {\n window.cancelAnimationFrame(resizeRaf);\n }\n removeDataListener?.dispose();\n removeResizeListener?.dispose();\n session?.close();\n terminal?.dispose();\n };\n }, [client, onError, onExit, processId]);\n\n return (\n <div className={className} style={{ ...shellStyle, ...style }}>\n {showStatusBar ? (\n <div style={{ ...statusBarStyle, ...statusBarStyleOverride }}>\n <span style={{ color: getStatusColor(connectionState) }}>{statusMessage}</span>\n {exitCode != null ? <span style={exitCodeStyle}>exit={exitCode}</span> : null}\n </div>\n ) : null}\n <div\n ref={hostRef}\n role=\"presentation\"\n style={{\n ...hostBaseStyle,\n height,\n ...terminalStyle,\n }}\n onClick={() => {\n hostRef.current?.querySelector(\"textarea\")?.focus();\n }}\n />\n </div>\n );\n};\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","entry","jsx","jsxs","DEFAULT_CLASS_NAMES","cx","mergeClassNames","jsx","jsxs","DEFAULT_CLASS_NAMES","cx","mergeClassNames","useEffect","useRef","useState","jsx","jsxs"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sandbox-agent/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-rc.1",
|
|
4
4
|
"description": "React components for Sandbox Agent frontend integrations",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"sandbox-agent": "^0.2.2"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@tanstack/react-virtual": "^3.13.22",
|
|
27
28
|
"ghostty-web": "^0.4.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"react": "^18.3.1",
|
|
32
33
|
"tsup": "^8.0.0",
|
|
33
34
|
"typescript": "^5.7.0",
|
|
34
|
-
"sandbox-agent": "0.
|
|
35
|
+
"sandbox-agent": "0.4.0-rc.1"
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
|
37
38
|
"build": "tsup",
|