@parallelworks/ui 0.51.0 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +197 -17
- package/dist/ai/agent/toolStrings.d.ts +2 -0
- package/dist/ai/agent/toolStrings.js +20 -18
- package/dist/ai/ai.css +17 -3
- package/dist/ai/components/AllocationSelector.js +5 -1
- package/dist/ai/components/AttachmentManager.js +51 -42
- package/dist/ai/components/AttachmentUpload.d.ts +4 -2
- package/dist/ai/components/AttachmentUpload.js +9 -9
- package/dist/ai/components/BlockedGroupBanner.js +8 -14
- package/dist/ai/components/BranchNavigator.js +11 -12
- package/dist/ai/components/ChatEmptyState.js +12 -19
- package/dist/ai/components/ChatInput.d.ts +4 -3
- package/dist/ai/components/ChatInput.js +27 -13
- package/dist/ai/components/ChatMessage.js +45 -121
- package/dist/ai/components/ChatMessageList.d.ts +5 -2
- package/dist/ai/components/ChatMessageList.js +89 -51
- package/dist/ai/components/ChatSidebar.js +11 -7
- package/dist/ai/components/ChatThread.js +1 -13
- package/dist/ai/components/DragOverlay.js +3 -3
- package/dist/ai/components/MessageAttachments.d.ts +10 -0
- package/dist/ai/components/MessageAttachments.js +78 -0
- package/dist/ai/components/ModelSelector.js +3 -3
- package/dist/ai/components/PastedText.js +2 -2
- package/dist/ai/components/ProviderIssueBanner.js +19 -23
- package/dist/ai/components/ShareDialog.js +2 -2
- package/dist/ai/components/agent/ActivityLine.d.ts +0 -2
- package/dist/ai/components/agent/ActivityLine.js +8 -51
- package/dist/ai/components/agent/AgentMessageParts.js +114 -53
- package/dist/ai/core/ChatProvider.d.ts +16 -5
- package/dist/ai/core/ChatProvider.js +41 -8
- package/dist/ai/core/config.js +4 -3
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.js +3 -3
- package/dist/ai/strings.d.ts +29 -3
- package/dist/ai/strings.js +80 -26
- package/dist/ai/types.d.ts +4 -0
- package/dist/ai/ui/Notice.d.ts +2 -2
- package/dist/ai/ui/Notice.js +29 -62
- package/dist/ai/ui/sidebar.d.ts +5 -3
- package/dist/ai/ui/sidebar.js +22 -10
- package/dist/components/ActionMenu.d.ts +1 -0
- package/dist/components/ActionMenu.js +6 -1
- package/dist/components/AppLink.d.ts +26 -0
- package/dist/components/AppLink.js +51 -0
- package/dist/components/Avatar.d.ts +2 -1
- package/dist/components/Avatar.js +4 -2
- package/dist/components/Button.d.ts +15 -5
- package/dist/components/Button.js +47 -40
- package/dist/components/Callout.d.ts +31 -7
- package/dist/components/Callout.js +50 -19
- package/dist/components/Card.d.ts +11 -6
- package/dist/components/Card.js +14 -8
- package/dist/components/Checkbox.js +2 -1
- package/dist/components/ColorInput.js +5 -3
- package/dist/components/Combobox.js +49 -19
- package/dist/components/ConfirmModal.d.ts +19 -8
- package/dist/components/ConfirmModal.js +31 -53
- package/dist/components/CopyButton.d.ts +38 -0
- package/dist/components/CopyButton.js +68 -0
- package/dist/components/CreateModal.js +118 -111
- package/dist/components/DatePicker.js +12 -8
- package/dist/components/DescriptionList.d.ts +25 -5
- package/dist/components/DescriptionList.js +56 -22
- package/dist/components/Disclosure.js +1 -1
- package/dist/components/Drawer.js +10 -16
- package/dist/components/Field.d.ts +16 -5
- package/dist/components/Field.js +63 -8
- package/dist/components/IconButton.d.ts +14 -5
- package/dist/components/IconButton.js +25 -14
- package/dist/components/InfoTip.d.ts +12 -1
- package/dist/components/InfoTip.js +13 -2
- package/dist/components/Input.d.ts +14 -8
- package/dist/components/Input.js +46 -31
- package/dist/components/Loader.js +1 -1
- package/dist/components/MarkdownImpl.d.ts +1 -0
- package/dist/components/MarkdownImpl.js +1 -0
- package/dist/components/MenuEntries.d.ts +4 -0
- package/dist/components/MenuEntries.js +11 -12
- package/dist/components/Meter.js +5 -4
- package/dist/components/Modal.d.ts +28 -4
- package/dist/components/Modal.js +37 -14
- package/dist/components/Overview.d.ts +20 -12
- package/dist/components/Overview.js +14 -9
- package/dist/components/PageHeader.d.ts +47 -65
- package/dist/components/PageHeader.js +275 -153
- package/dist/components/PageHeaderAction.d.ts +67 -0
- package/dist/components/PageHeaderAction.js +107 -0
- package/dist/components/Pagination.js +6 -16
- package/dist/components/Popover.d.ts +4 -1
- package/dist/components/Popover.js +5 -3
- package/dist/components/Provider.d.ts +79 -19
- package/dist/components/Provider.js +140 -130
- package/dist/components/Radio.js +2 -1
- package/dist/components/RefreshButton.js +7 -8
- package/dist/components/RequiredMark.js +1 -1
- package/dist/components/Section.js +1 -1
- package/dist/components/Select.d.ts +4 -9
- package/dist/components/Select.js +24 -11
- package/dist/components/SettingModeOption.d.ts +1 -1
- package/dist/components/SettingModeOption.js +7 -1
- package/dist/components/SettingsCard.d.ts +5 -3
- package/dist/components/SettingsCard.js +27 -20
- package/dist/components/Slider.js +1 -1
- package/dist/components/StatusBadge.js +2 -2
- package/dist/components/Switch.js +5 -4
- package/dist/components/Table.d.ts +30 -20
- package/dist/components/Table.js +50 -73
- package/dist/components/Tabs.d.ts +3 -7
- package/dist/components/Tabs.js +6 -10
- package/dist/components/ThemeEditor.js +18 -8
- package/dist/components/Toast.d.ts +11 -3
- package/dist/components/Toast.js +45 -20
- package/dist/components/buttonClasses.js +1 -1
- package/dist/components/comboboxItems.d.ts +4 -0
- package/dist/components/comboboxItems.js +6 -1
- package/dist/components/dismiss.d.ts +12 -0
- package/dist/components/dismiss.js +19 -0
- package/dist/components/fieldBox.d.ts +4 -0
- package/dist/components/fieldBox.js +7 -3
- package/dist/components/floating.d.ts +3 -3
- package/dist/components/floating.js +1 -1
- package/dist/components/focus.d.ts +5 -0
- package/dist/components/focus.js +21 -1
- package/dist/components/markdownCodeBreaks.js +3 -4
- package/dist/components/pageHeaderStore.d.ts +41 -0
- package/dist/components/pageHeaderStore.js +67 -0
- package/dist/components/pathBreaks.d.ts +8 -0
- package/dist/components/pathBreaks.js +28 -0
- package/dist/components/segmented.js +1 -1
- package/dist/components/shortcutKey.d.ts +2 -1
- package/dist/components/shortcutKey.js +19 -2
- package/dist/components/splitter.js +1 -1
- package/dist/components/useCssIsDark.js +40 -18
- package/dist/components/useTheme.js +9 -10
- package/dist/dev.d.ts +9 -0
- package/dist/dev.js +14 -0
- package/dist/editor/Editor.d.ts +3 -2
- package/dist/editor/Editor.js +24 -5
- package/dist/editor/EditorField.d.ts +2 -1
- package/dist/editor/EditorField.js +11 -29
- package/dist/editor/FormCodePanel.d.ts +7 -3
- package/dist/editor/FormCodePanel.js +14 -7
- package/dist/editor/Monaco.d.ts +22 -6
- package/dist/editor/Monaco.js +177 -113
- package/dist/editor/editorModel.d.ts +1 -1
- package/dist/editor/editorModel.js +1 -1
- package/dist/editor/index.d.ts +6 -5
- package/dist/editor/index.js +5 -4
- package/dist/editor/languages.d.ts +24 -0
- package/dist/editor/languages.js +31 -0
- package/dist/editor/monacoFeatures.d.ts +7 -0
- package/dist/editor/monacoFeatures.js +19 -0
- package/dist/editor/themes.d.ts +8 -5
- package/dist/editor/themes.js +65 -32
- package/dist/editor/workers.d.ts +3 -3
- package/dist/editor/workers.js +8 -4
- package/dist/editor/yaml.d.ts +6 -2
- package/dist/editor/yaml.js +11 -2
- package/dist/editor/yamlLanguage.js +55 -38
- package/dist/file-explorer/FileExplorer.d.ts +18 -4
- package/dist/file-explorer/FileExplorer.js +204 -142
- package/dist/file-explorer/FileExplorerContext.js +1 -1
- package/dist/file-explorer/FilePreview/StreamedBadge.js +3 -1
- package/dist/file-explorer/FilePreview/Viewer.js +14 -10
- package/dist/file-explorer/FilePreview/index.js +4 -4
- package/dist/file-explorer/FileRow.d.ts +6 -2
- package/dist/file-explorer/FileRow.js +35 -17
- package/dist/file-explorer/FileRowsWindow.d.ts +2 -1
- package/dist/file-explorer/FileRowsWindow.js +36 -4
- package/dist/file-explorer/FileTable.d.ts +3 -1
- package/dist/file-explorer/FileTable.js +6 -3
- package/dist/file-explorer/TreeView.d.ts +5 -1
- package/dist/file-explorer/TreeView.js +86 -39
- package/dist/file-explorer/helpers.d.ts +2 -1
- package/dist/file-explorer/helpers.js +24 -23
- package/dist/file-explorer/lib/utils.d.ts +3 -0
- package/dist/file-explorer/lib/utils.js +6 -1
- package/dist/file-explorer/toasts.js +27 -19
- package/dist/file-explorer/treeRows.d.ts +6 -0
- package/dist/file-explorer/treeRows.js +19 -1
- package/dist/file-explorer/useNearEnd.js +3 -6
- package/dist/form/Fields/CheckboxGroupField.js +12 -5
- package/dist/form/Fields/DurationField.js +1 -1
- package/dist/form/Fields/LabelField.js +1 -1
- package/dist/form/Fields/ObjectField.d.ts +1 -1
- package/dist/form/Fields/ObjectField.js +3 -2
- package/dist/form/Fields/StringField.js +16 -29
- package/dist/form/Fields/TextAreaField.js +3 -4
- package/dist/form/Form.js +3 -8
- package/dist/form/Wizard/WizardNavigation.js +0 -3
- package/dist/form/Wizard/utils.js +2 -1
- package/dist/form/fieldFrame.d.ts +1 -1
- package/dist/form/fieldFrame.js +2 -2
- package/dist/form/types/fieldComponentTypes.d.ts +2 -1
- package/dist/graph/AnnotationBanner.d.ts +1 -2
- package/dist/graph/AnnotationBanner.js +30 -32
- package/dist/graph/Connectors.js +4 -1
- package/dist/graph/DependencyGraph.js +2 -2
- package/dist/graph/GraphEditor.js +11 -9
- package/dist/graph/GraphEditorDialogs.js +1 -1
- package/dist/graph/GraphNode.js +7 -4
- package/dist/graph/InputDialog.js +1 -1
- package/dist/graph/InputsEditor.js +14 -11
- package/dist/graph/MatrixGroup.js +9 -3
- package/dist/graph/Reveal.js +18 -10
- package/dist/graph/ShortcutsButton.d.ts +11 -2
- package/dist/graph/ShortcutsButton.js +14 -3
- package/dist/graph/TreeView.js +35 -18
- package/dist/graph/WorkflowSettingsDialog.js +1 -1
- package/dist/graph/editorFields.js +1 -1
- package/dist/graph/editorRows.js +16 -10
- package/dist/graph/editorStrings.d.ts +7 -0
- package/dist/graph/editorStrings.js +8 -1
- package/dist/graph/inputRefs.js +1 -1
- package/dist/graph/settingsViews.js +11 -18
- package/dist/graph/stepWith.js +1 -1
- package/dist/icons.d.ts +2 -0
- package/dist/icons.js +4 -2
- package/dist/index.d.ts +12 -12
- package/dist/index.js +16 -16
- package/dist/list/ActionToolbar.d.ts +42 -6
- package/dist/list/ActionToolbar.js +298 -101
- package/dist/list/ListPage.d.ts +15 -23
- package/dist/list/ListPage.js +42 -43
- package/dist/list/ListTable.d.ts +37 -7
- package/dist/list/ListTable.js +52 -12
- package/dist/list/ListViewControls.js +1 -1
- package/dist/list/UserHoverCard.js +7 -15
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.js +2 -2
- package/dist/list/listSearch.js +12 -10
- package/dist/list/listView.d.ts +10 -1
- package/dist/list/listView.js +15 -1
- package/dist/logviewer/LogViewer.d.ts +4 -2
- package/dist/logviewer/LogViewer.js +87 -69
- package/dist/logviewer/logviewer.css +3 -2
- package/dist/reducedMotion.d.ts +5 -0
- package/dist/reducedMotion.js +20 -0
- package/dist/safeUrl.d.ts +1 -1
- package/dist/safeUrl.js +4 -2
- package/dist/styles.css +1 -1
- package/package.json +5 -2
- package/dist/components/Breadcrumbs.d.ts +0 -37
- package/dist/components/Breadcrumbs.js +0 -90
- package/dist/components/CopyToClipboard.d.ts +0 -17
- package/dist/components/CopyToClipboard.js +0 -66
- package/dist/components/Sort.d.ts +0 -9
- package/dist/components/Sort.js +0 -42
- package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +0 -6
- package/dist/file-explorer/FilePreview/CodePreviewEditor.js +0 -64
|
@@ -4,17 +4,36 @@ import { useStrings } from "../../components/Provider.js";
|
|
|
4
4
|
import { formatDuration } from "../../format.js";
|
|
5
5
|
import { useElapsed } from "../../components/relativeTime.js";
|
|
6
6
|
import { useChatConfig } from "../core/config.js";
|
|
7
|
-
import { useChat } from "../core/ChatProvider.js";
|
|
7
|
+
import { useChat, useChatStream } from "../core/ChatProvider.js";
|
|
8
8
|
import Markdown from "../ui/Markdown.js";
|
|
9
9
|
import { Reasoning, ReasoningBody } from "./Reasoning.js";
|
|
10
10
|
import AgentMessageParts from "./agent/AgentMessageParts.js";
|
|
11
11
|
import ChatMessage_default from "./ChatMessage.js";
|
|
12
12
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
-
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
13
|
+
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
14
14
|
//#region src/ai/components/ChatMessageList.tsx
|
|
15
|
-
function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessages, onRemoveQueued, canRemoveQueued, queueDelivery = "afterReply", editingMessageId, showAuthor, currentUsername, onNavigateBranch, onEditMessage, onSaveEdit, onCancelEdit, onRegenerateMessage, onRetryMessage, onOpenReasoning, onApprovalAnswer, inputElement, isStreaming: isStreamingProp, flush, label, footer, workingIndicator = true }) {
|
|
16
|
-
const { adapter, isStreaming: providerStreaming
|
|
15
|
+
function ChatMessageList({ messages, allMessages, streamingMessage: streamingMessageProp, queuedMessages, onRemoveQueued, canRemoveQueued, queueDelivery = "afterReply", editingMessageId, showAuthor, currentUsername, onNavigateBranch, onEditMessage, onSaveEdit, onCancelEdit, onRegenerateMessage, onRetryMessage, onOpenReasoning, onApprovalAnswer, inputElement, isStreaming: isStreamingProp, flush, label, footer, workingIndicator = true }) {
|
|
16
|
+
const { adapter, isStreaming: providerStreaming } = useChat();
|
|
17
|
+
const { isThinking, streamingContent, streamingReasoning, streamingParts, thinkingStartTime } = useChatStream();
|
|
17
18
|
const isStreaming = isStreamingProp ?? providerStreaming;
|
|
19
|
+
const conversationId = messages[0]?.conversationId;
|
|
20
|
+
const providerStreamingMessage = useMemo(() => providerStreaming && streamingContent ? {
|
|
21
|
+
id: "streaming",
|
|
22
|
+
role: "assistant",
|
|
23
|
+
content: streamingContent,
|
|
24
|
+
timestamp: "",
|
|
25
|
+
...conversationId ? { conversationId } : {}
|
|
26
|
+
} : null, [
|
|
27
|
+
providerStreaming,
|
|
28
|
+
streamingContent,
|
|
29
|
+
conversationId
|
|
30
|
+
]);
|
|
31
|
+
const streamingMessage = streamingMessageProp === void 0 ? providerStreamingMessage : streamingMessageProp;
|
|
32
|
+
const streamingPartsMessage = useMemo(() => ({
|
|
33
|
+
id: "streaming-parts",
|
|
34
|
+
role: "assistant",
|
|
35
|
+
parts: streamingParts
|
|
36
|
+
}), [streamingParts]);
|
|
18
37
|
const { strings } = useChatConfig();
|
|
19
38
|
const { common } = useStrings();
|
|
20
39
|
const tThinking = strings.thinking;
|
|
@@ -29,15 +48,8 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
|
|
|
29
48
|
const bottomRef = useRef(null);
|
|
30
49
|
const containerRef = useRef(null);
|
|
31
50
|
const reasoningScrollRef = useRef(null);
|
|
32
|
-
const knownMessageIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
33
|
-
const prevMessageCountRef = useRef(messages.length);
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
const prev = prevMessageCountRef.current;
|
|
36
|
-
if (messages.length > 0 && (prev === 0 || messages.length < prev)) knownMessageIdsRef.current = new Set(messages.map((m) => m.id));
|
|
37
|
-
prevMessageCountRef.current = messages.length;
|
|
38
|
-
}, [messages]);
|
|
39
51
|
const messageCount = messages.length;
|
|
40
|
-
const
|
|
52
|
+
const streamingText = streamingMessage?.content;
|
|
41
53
|
const streamingMessageParts = streamingMessage?.parts;
|
|
42
54
|
const [finalThinkingDuration, setFinalThinkingDuration] = useState(null);
|
|
43
55
|
const [reasoningOpen, setReasoningOpen] = useState(false);
|
|
@@ -124,7 +136,7 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
|
|
|
124
136
|
if (!containerRef.current || !isNearBottomRef.current || !isStreaming || hasQueuedMessages) return;
|
|
125
137
|
containerRef.current.scrollTop = containerRef.current.scrollHeight;
|
|
126
138
|
}, [
|
|
127
|
-
|
|
139
|
+
streamingText,
|
|
128
140
|
streamingParts,
|
|
129
141
|
streamingMessageParts,
|
|
130
142
|
messageCount,
|
|
@@ -133,9 +145,8 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
|
|
|
133
145
|
]);
|
|
134
146
|
useEffect(() => {
|
|
135
147
|
if (!containerRef.current || !isNearBottomRef.current || isStreaming || !hadMessagesRef.current) return;
|
|
136
|
-
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
148
|
+
bottomRef.current?.scrollIntoView({ behavior: prefersReducedMotion() ? "auto" : "smooth" });
|
|
137
149
|
}, [messageCount, isStreaming]);
|
|
138
|
-
const lastIndex = messages.findLastIndex((m) => !m.pseudo);
|
|
139
150
|
if (messages.length === 0 && !streamingMessage && !hasQueuedMessages) return /* @__PURE__ */ jsxs("div", {
|
|
140
151
|
className: "chat-thread flex-1 overflow-y-auto flex flex-col bg-(--theme-panel-bg)",
|
|
141
152
|
children: [
|
|
@@ -152,42 +163,33 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
|
|
|
152
163
|
});
|
|
153
164
|
return /* @__PURE__ */ jsxs("div", {
|
|
154
165
|
ref: containerRef,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
} : {},
|
|
166
|
+
role: "log",
|
|
167
|
+
"aria-relevant": "additions",
|
|
168
|
+
"aria-label": label ?? strings.thread.label,
|
|
169
|
+
"aria-busy": isStreaming || void 0,
|
|
160
170
|
className: "chat-thread flex-1 overflow-y-auto theme-scrollbar flex flex-col bg-(--theme-panel-bg)",
|
|
161
171
|
children: [
|
|
162
172
|
/* @__PURE__ */ jsxs("div", {
|
|
163
173
|
className: "w-full max-w-[var(--chat-column,50rem)] mx-auto pt-4 pb-6 flex-1 px-4",
|
|
164
174
|
children: [
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
onSaveEdit,
|
|
184
|
-
onCancelEdit,
|
|
185
|
-
onRegenerate: onRegenerateMessage,
|
|
186
|
-
onRetry: onRetryMessage,
|
|
187
|
-
onOpenReasoning,
|
|
188
|
-
onApprovalAnswer
|
|
189
|
-
})
|
|
190
|
-
}, message.id);
|
|
175
|
+
/* @__PURE__ */ jsx(MessageRows, {
|
|
176
|
+
messages,
|
|
177
|
+
allMessages,
|
|
178
|
+
streaming: !!streamingMessage,
|
|
179
|
+
flush,
|
|
180
|
+
editingMessageId,
|
|
181
|
+
showAuthor,
|
|
182
|
+
currentUsername,
|
|
183
|
+
attachmentDownloadUrl,
|
|
184
|
+
onOpenAttachment,
|
|
185
|
+
onNavigateBranch,
|
|
186
|
+
onEditMessage,
|
|
187
|
+
onSaveEdit,
|
|
188
|
+
onCancelEdit,
|
|
189
|
+
onRegenerateMessage,
|
|
190
|
+
onRetryMessage,
|
|
191
|
+
onOpenReasoning,
|
|
192
|
+
onApprovalAnswer
|
|
191
193
|
}),
|
|
192
194
|
isStreaming && streamingReasoning && /* @__PURE__ */ jsx("div", {
|
|
193
195
|
className: "animate-chat-enter",
|
|
@@ -223,11 +225,7 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
|
|
|
223
225
|
isStreaming && streamingParts.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
224
226
|
className: cx("animate-chat-enter py-1", !flush && "px-4"),
|
|
225
227
|
children: /* @__PURE__ */ jsx(AgentMessageParts, {
|
|
226
|
-
message:
|
|
227
|
-
id: "streaming-parts",
|
|
228
|
-
role: "assistant",
|
|
229
|
-
parts: streamingParts
|
|
230
|
-
},
|
|
228
|
+
message: streamingPartsMessage,
|
|
231
229
|
isStreaming
|
|
232
230
|
})
|
|
233
231
|
}, "streaming-parts"),
|
|
@@ -307,6 +305,9 @@ function ChatMessageList({ messages, allMessages, streamingMessage, queuedMessag
|
|
|
307
305
|
]
|
|
308
306
|
});
|
|
309
307
|
}
|
|
308
|
+
function prefersReducedMotion() {
|
|
309
|
+
return typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
310
|
+
}
|
|
310
311
|
/** "Thinking (12s)" while it thinks, then how long it took. Its own component,
|
|
311
312
|
* so the clock re-renders only this label, not the list. */
|
|
312
313
|
function ThinkingLabel({ startedAt, finalDuration }) {
|
|
@@ -315,5 +316,42 @@ function ThinkingLabel({ startedAt, finalDuration }) {
|
|
|
315
316
|
if (startedAt) return elapsed ? `${t.label} (${formatDuration(elapsed)})` : t.ellipsis;
|
|
316
317
|
return t.thoughtFor(formatDuration(finalDuration ?? 0));
|
|
317
318
|
}
|
|
319
|
+
/** The conversation so far. Memoized apart from the list, which re-renders
|
|
320
|
+
* for every streamed token, so a long conversation is not walked per token. */
|
|
321
|
+
var MessageRows = memo(function MessageRows({ messages, allMessages, streaming, flush, editingMessageId, showAuthor, currentUsername, attachmentDownloadUrl, onOpenAttachment, onNavigateBranch, onEditMessage, onSaveEdit, onCancelEdit, onRegenerateMessage, onRetryMessage, onOpenReasoning, onApprovalAnswer }) {
|
|
322
|
+
const shownRef = useRef(/* @__PURE__ */ new Set());
|
|
323
|
+
const shown = shownRef.current;
|
|
324
|
+
const appended = shown.size > 0 && messages.some((m) => shown.has(m.id));
|
|
325
|
+
useLayoutEffect(() => {
|
|
326
|
+
shownRef.current = new Set(messages.map((m) => m.id));
|
|
327
|
+
}, [messages]);
|
|
328
|
+
const lastIndex = messages.findLastIndex((m) => !m.pseudo);
|
|
329
|
+
return messages.map((message, i) => {
|
|
330
|
+
if (message.pseudo) return null;
|
|
331
|
+
const isNew = appended && !shown.has(message.id);
|
|
332
|
+
return /* @__PURE__ */ jsx("div", {
|
|
333
|
+
className: isNew ? "animate-chat-enter" : void 0,
|
|
334
|
+
children: /* @__PURE__ */ jsx(ChatMessage_default, {
|
|
335
|
+
message,
|
|
336
|
+
allMessages,
|
|
337
|
+
flush,
|
|
338
|
+
latest: i === lastIndex && !streaming,
|
|
339
|
+
isEditing: editingMessageId === message.id,
|
|
340
|
+
showAuthor,
|
|
341
|
+
currentUsername,
|
|
342
|
+
attachmentDownloadUrl,
|
|
343
|
+
onOpenAttachment,
|
|
344
|
+
onNavigateBranch,
|
|
345
|
+
onEdit: onEditMessage,
|
|
346
|
+
onSaveEdit,
|
|
347
|
+
onCancelEdit,
|
|
348
|
+
onRegenerate: onRegenerateMessage,
|
|
349
|
+
onRetry: onRetryMessage,
|
|
350
|
+
onOpenReasoning,
|
|
351
|
+
onApprovalAnswer
|
|
352
|
+
})
|
|
353
|
+
}, message.id);
|
|
354
|
+
});
|
|
355
|
+
});
|
|
318
356
|
//#endregion
|
|
319
357
|
export { ChatMessageList as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cx } from "../../cx.js";
|
|
2
2
|
import { ImageIcon, NewChatIcon, UsersIcon } from "../../icons.js";
|
|
3
|
+
import { isPlainClick } from "../../components/AppLink.js";
|
|
3
4
|
import { EmptyState } from "../../components/EmptyState.js";
|
|
4
5
|
import { RelativeTime } from "../../components/relativeTime.js";
|
|
5
6
|
import { SearchInput } from "../../components/SearchInput.js";
|
|
@@ -26,7 +27,9 @@ function ConversationRow({ conv, isCurrent, menuItems, openMenu, onOpen }) {
|
|
|
26
27
|
id: conv.id
|
|
27
28
|
},
|
|
28
29
|
className: "flex min-w-0 flex-1 items-center gap-1.5 py-1 text-left",
|
|
29
|
-
onClick:
|
|
30
|
+
onClick: (e) => {
|
|
31
|
+
if (isPlainClick(e)) onOpen();
|
|
32
|
+
},
|
|
30
33
|
children: [conv.isOwner === false && /* @__PURE__ */ jsx(UsersIcon, {
|
|
31
34
|
className: "h-3 w-3 shrink-0 theme-muted-text",
|
|
32
35
|
title: t.sharedWithYou
|
|
@@ -82,10 +85,11 @@ function ChatSidebar({ actions = true, top }) {
|
|
|
82
85
|
label: tSidebar[key],
|
|
83
86
|
items
|
|
84
87
|
})), [filteredConversations, tSidebar]);
|
|
85
|
-
const handleNewChat = () => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
const handleNewChat = (e) => {
|
|
89
|
+
if (isPlainClick(e)) {
|
|
90
|
+
closeDrawer();
|
|
91
|
+
clearCurrentConversation();
|
|
92
|
+
}
|
|
89
93
|
};
|
|
90
94
|
const list = /* @__PURE__ */ jsx(ConversationSidebar, {
|
|
91
95
|
collapsed: sidebarCollapsed,
|
|
@@ -123,8 +127,8 @@ function ChatSidebar({ actions = true, top }) {
|
|
|
123
127
|
},
|
|
124
128
|
top: (top || actions) && /* @__PURE__ */ jsxs(Fragment, { children: [top?.({ collapsed: sidebarCollapsed }), actions && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
125
129
|
className: "flex flex-col gap-0.5 px-2 pt-2 pb-1",
|
|
126
|
-
children: [/* @__PURE__ */ jsxs(
|
|
127
|
-
|
|
130
|
+
children: [/* @__PURE__ */ jsxs(LinkComponent, {
|
|
131
|
+
target: { kind: "newChat" },
|
|
128
132
|
onClick: handleNewChat,
|
|
129
133
|
className: "flex items-center h-9 px-2 gap-3 rounded-lg font-medium transition-colors hover:chat-tint",
|
|
130
134
|
title: tSidebar.newChat,
|
|
@@ -14,7 +14,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
14
14
|
function ChatThread({ conversationId }) {
|
|
15
15
|
const chatInputRef = useRef(null);
|
|
16
16
|
const [editingState, setEditingState] = useState(null);
|
|
17
|
-
const { adapter, currentUser, currentConversation, loadConversation, loadProviders, sendMessage, retryMessage, isLoadingConversation,
|
|
17
|
+
const { adapter, currentUser, currentConversation, loadConversation, loadProviders, sendMessage, retryMessage, isLoadingConversation, navigateToBranch, queuedMessages, removeQueuedMessage } = useChat();
|
|
18
18
|
const { slots, strings } = useChatConfig();
|
|
19
19
|
const requestedConversationIdRef = useRef(null);
|
|
20
20
|
useEffect(() => {
|
|
@@ -69,17 +69,6 @@ function ChatThread({ conversationId }) {
|
|
|
69
69
|
}, []);
|
|
70
70
|
const { isDragging, dragHandlers } = useDragDrop({ onFilesDropped: handleFilesDropped });
|
|
71
71
|
const attachmentsAvailable = !!adapter.attachments;
|
|
72
|
-
const streamingMessage = useMemo(() => isStreaming && streamingContent ? {
|
|
73
|
-
id: "streaming",
|
|
74
|
-
conversationId,
|
|
75
|
-
role: "assistant",
|
|
76
|
-
content: streamingContent,
|
|
77
|
-
timestamp: ""
|
|
78
|
-
} : null, [
|
|
79
|
-
isStreaming,
|
|
80
|
-
streamingContent,
|
|
81
|
-
conversationId
|
|
82
|
-
]);
|
|
83
72
|
const messages = currentConversation?.messages || [];
|
|
84
73
|
const showAuthor = useMemo(() => {
|
|
85
74
|
return new Set(messages.flatMap((m) => m.author ? [m.author.username] : [])).size > 1 || currentConversation?.isOwner === false;
|
|
@@ -107,7 +96,6 @@ function ChatThread({ conversationId }) {
|
|
|
107
96
|
/* @__PURE__ */ jsx(ChatMessageList, {
|
|
108
97
|
messages,
|
|
109
98
|
allMessages: messages,
|
|
110
|
-
streamingMessage,
|
|
111
99
|
queuedMessages,
|
|
112
100
|
onRemoveQueued: removeQueuedMessage,
|
|
113
101
|
editingMessageId: editingState?.messageId,
|
|
@@ -5,14 +5,14 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
5
5
|
function DragOverlay({ className }) {
|
|
6
6
|
const t = useChatConfig().strings.attachmentUpload;
|
|
7
7
|
return /* @__PURE__ */ jsx("div", {
|
|
8
|
-
className: cx("absolute inset-0 z-50 flex items-center justify-center bg-
|
|
8
|
+
className: cx("absolute inset-0 z-50 flex items-center justify-center bg-(--theme-accent)/10 border-2 border-dashed border-(--theme-accent) backdrop-blur-sm pointer-events-none", className),
|
|
9
9
|
children: /* @__PURE__ */ jsxs("div", {
|
|
10
10
|
className: "text-center",
|
|
11
11
|
children: [/* @__PURE__ */ jsx("p", {
|
|
12
|
-
className: "text-lg font-medium text
|
|
12
|
+
className: "text-lg font-medium theme-text",
|
|
13
13
|
children: t.dropFilesHere
|
|
14
14
|
}), /* @__PURE__ */ jsx("p", {
|
|
15
|
-
className: "text-sm
|
|
15
|
+
className: "text-sm theme-muted-text",
|
|
16
16
|
children: t.releaseToUpload
|
|
17
17
|
})]
|
|
18
18
|
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AttachmentRef } from '../types.js';
|
|
2
|
+
/** The files sent with a message. One the reader can download is a link to
|
|
3
|
+
* it, so it can be saved or opened in a new tab like any other; a host that
|
|
4
|
+
* previews attachments takes the plain click. */
|
|
5
|
+
export default function MessageAttachments({ attachments, downloadUrl, onOpen, className, }: {
|
|
6
|
+
attachments: AttachmentRef[];
|
|
7
|
+
downloadUrl?: ((id: string) => string) | undefined;
|
|
8
|
+
onOpen?: ((attachment: AttachmentRef) => void) | undefined;
|
|
9
|
+
className?: string | undefined;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { cx } from "../../cx.js";
|
|
2
|
+
import { DownloadIcon, FileIcon } from "../../icons.js";
|
|
3
|
+
import { safeUrl } from "../../safeUrl.js";
|
|
4
|
+
import { isPlainClick } from "../../components/AppLink.js";
|
|
5
|
+
import { formatBytes } from "../../format.js";
|
|
6
|
+
import { useChatConfig } from "../core/config.js";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/ai/components/MessageAttachments.tsx
|
|
9
|
+
var chipClasses = "inline-flex items-center gap-1.5 text-xs px-2.5 py-1.5 rounded-lg bg-(--theme-muted-panel-bg)";
|
|
10
|
+
/** The files sent with a message. One the reader can download is a link to
|
|
11
|
+
* it, so it can be saved or opened in a new tab like any other; a host that
|
|
12
|
+
* previews attachments takes the plain click. */
|
|
13
|
+
function MessageAttachments({ attachments, downloadUrl, onOpen, className }) {
|
|
14
|
+
const t = useChatConfig().strings.attachmentManager;
|
|
15
|
+
return /* @__PURE__ */ jsx("div", {
|
|
16
|
+
className: cx("mt-3 flex flex-wrap items-start gap-2", className),
|
|
17
|
+
children: attachments.map((att) => {
|
|
18
|
+
const isImage = att.contentType?.startsWith("image/");
|
|
19
|
+
const name = att.filename || (isImage ? t.unnamedImage : t.unnamedFile);
|
|
20
|
+
const url = att.id && downloadUrl ? downloadUrl(att.id) : void 0;
|
|
21
|
+
const href = safeUrl(url);
|
|
22
|
+
const thumbnail = isImage && url;
|
|
23
|
+
const body = thumbnail ? /* @__PURE__ */ jsx("img", {
|
|
24
|
+
src: url,
|
|
25
|
+
alt: name,
|
|
26
|
+
className: "max-h-[200px] max-w-[200px] object-cover",
|
|
27
|
+
loading: "lazy"
|
|
28
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29
|
+
/* @__PURE__ */ jsx(FileIcon, {
|
|
30
|
+
"aria-hidden": "true",
|
|
31
|
+
className: "h-3.5 w-3.5 flex-shrink-0"
|
|
32
|
+
}),
|
|
33
|
+
/* @__PURE__ */ jsx("span", {
|
|
34
|
+
className: "max-w-[150px] truncate",
|
|
35
|
+
children: name
|
|
36
|
+
}),
|
|
37
|
+
att.size ? /* @__PURE__ */ jsxs("span", {
|
|
38
|
+
className: "theme-muted-text",
|
|
39
|
+
children: [
|
|
40
|
+
"(",
|
|
41
|
+
formatBytes(att.size),
|
|
42
|
+
")"
|
|
43
|
+
]
|
|
44
|
+
}) : null,
|
|
45
|
+
href && /* @__PURE__ */ jsx(DownloadIcon, {
|
|
46
|
+
"aria-hidden": "true",
|
|
47
|
+
className: "h-3 w-3 flex-shrink-0"
|
|
48
|
+
})
|
|
49
|
+
] });
|
|
50
|
+
const className = thumbnail ? "block overflow-hidden rounded-lg border theme-border" : cx(chipClasses, !href && "theme-muted-text", (href || onOpen) && "transition-colors hover:theme-hover");
|
|
51
|
+
if (href) return /* @__PURE__ */ jsx("a", {
|
|
52
|
+
href,
|
|
53
|
+
download: att.filename || true,
|
|
54
|
+
onClick: onOpen && ((e) => {
|
|
55
|
+
if (isPlainClick(e)) {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
onOpen(att);
|
|
58
|
+
}
|
|
59
|
+
}),
|
|
60
|
+
className,
|
|
61
|
+
children: body
|
|
62
|
+
}, att.id);
|
|
63
|
+
if (onOpen) return /* @__PURE__ */ jsx("button", {
|
|
64
|
+
type: "button",
|
|
65
|
+
onClick: () => onOpen(att),
|
|
66
|
+
"aria-label": thumbnail ? void 0 : t.open(name),
|
|
67
|
+
className,
|
|
68
|
+
children: body
|
|
69
|
+
}, att.id);
|
|
70
|
+
return /* @__PURE__ */ jsx("span", {
|
|
71
|
+
className,
|
|
72
|
+
children: body
|
|
73
|
+
}, att.id);
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { MessageAttachments as default };
|
|
@@ -21,7 +21,7 @@ function CspIcon({ cspKind, className }) {
|
|
|
21
21
|
const { slots } = useChatConfig();
|
|
22
22
|
const custom = slots.providerIcon?.(cspKind, className);
|
|
23
23
|
if (custom) return /* @__PURE__ */ jsx(Fragment, { children: custom });
|
|
24
|
-
return /* @__PURE__ */ jsx(CloudIcon, { className: cx("
|
|
24
|
+
return /* @__PURE__ */ jsx(CloudIcon, { className: cx("theme-muted-text", className) });
|
|
25
25
|
}
|
|
26
26
|
function getProviderKeyFromModelId(modelId) {
|
|
27
27
|
const idx = modelId.indexOf("/");
|
|
@@ -60,7 +60,7 @@ function ModelSelector({ targetSession }) {
|
|
|
60
60
|
const groups = useMemo(() => {
|
|
61
61
|
const status = (label, description) => ({
|
|
62
62
|
label,
|
|
63
|
-
icon: /* @__PURE__ */ jsx(CloudIcon, { className: "h-3 w-3 text-
|
|
63
|
+
icon: /* @__PURE__ */ jsx(CloudIcon, { className: "h-3 w-3 text-(--theme-warning)" }),
|
|
64
64
|
description,
|
|
65
65
|
items: []
|
|
66
66
|
});
|
|
@@ -143,7 +143,7 @@ function ModelSelector({ targetSession }) {
|
|
|
143
143
|
className: "max-w-[45%] shrink-0 truncate text-xs",
|
|
144
144
|
children: selected.provider
|
|
145
145
|
}),
|
|
146
|
-
issue && /* @__PURE__ */ jsx(WarningIcon, { className: "h-3.5 w-3.5 shrink-0 text-
|
|
146
|
+
issue && /* @__PURE__ */ jsx(WarningIcon, { className: "h-3.5 w-3.5 shrink-0 text-(--theme-warning)" })
|
|
147
147
|
] }) : /* @__PURE__ */ jsx("span", {
|
|
148
148
|
className: cx("truncate", targetSessionStatus === "connecting" && "animate-pulse"),
|
|
149
149
|
children: targetSessionStatus === "connecting" ? t.connecting : t.select
|
|
@@ -15,7 +15,7 @@ function PasteFileCard({ id, lines, bytes, saving = false, error, onRemove }) {
|
|
|
15
15
|
const detail = error ?? (saving ? t.saving : `${t.lines(lines)} · ${formatBytes(bytes)}`);
|
|
16
16
|
return /* @__PURE__ */ jsxs("div", {
|
|
17
17
|
"data-testid": "paste-file-card",
|
|
18
|
-
className: cx("inline-flex max-w-full items-center gap-2.5 rounded-xl px-3 py-2 align-top whitespace-normal", "bg-(--theme-panel-bg)", error ? "border border-
|
|
18
|
+
className: cx("inline-flex max-w-full items-center gap-2.5 rounded-xl px-3 py-2 align-top whitespace-normal", "bg-(--theme-panel-bg)", error ? "border border-(--theme-error)" : "chat-hairline"),
|
|
19
19
|
children: [
|
|
20
20
|
/* @__PURE__ */ jsx(FileIcon, { className: "h-5 w-5 flex-shrink-0 theme-muted-text" }),
|
|
21
21
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -24,7 +24,7 @@ function PasteFileCard({ id, lines, bytes, saving = false, error, onRemove }) {
|
|
|
24
24
|
className: "truncate text-sm font-medium theme-text",
|
|
25
25
|
children: id ? `paste-${id}.txt` : t.title
|
|
26
26
|
}), /* @__PURE__ */ jsx("div", {
|
|
27
|
-
className: cx("truncate text-xs", error ? "text-
|
|
27
|
+
className: cx("truncate text-xs", error ? "text-(--theme-error-text)" : "theme-muted-text"),
|
|
28
28
|
children: detail
|
|
29
29
|
})]
|
|
30
30
|
}),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buttonClasses } from "../../components/buttonClasses.js";
|
|
2
|
+
import { SettingsIcon } from "../../icons.js";
|
|
3
|
+
import { Callout } from "../../components/Callout.js";
|
|
2
4
|
import { useChatConfig } from "../core/config.js";
|
|
3
5
|
import { issueDetail, providerIssueFor } from "../core/providerIssues.js";
|
|
4
6
|
import { useChat } from "../core/ChatProvider.js";
|
|
@@ -18,29 +20,23 @@ function ProviderIssueBanner() {
|
|
|
18
20
|
const providerKey = getProviderKeyFromModelId(selectedModel.id);
|
|
19
21
|
const provider = providers.find((p) => `${p.user}:${p.name}` === providerKey);
|
|
20
22
|
const settingsHref = provider?.user === currentUser.username ? extraLinks.providerSettings?.(provider.user, provider.name) : void 0;
|
|
21
|
-
return /* @__PURE__ */
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
return /* @__PURE__ */ jsx(Callout, {
|
|
24
|
+
tone: "warning",
|
|
25
|
+
size: "sm",
|
|
26
|
+
className: "mx-4 mt-2",
|
|
27
|
+
title,
|
|
28
|
+
action: settingsHref && /* @__PURE__ */ jsxs(LinkComponent, {
|
|
29
|
+
target: {
|
|
30
|
+
kind: "external",
|
|
31
|
+
href: settingsHref
|
|
32
|
+
},
|
|
33
|
+
className: buttonClasses({
|
|
34
|
+
variant: "outline",
|
|
35
|
+
size: "sm"
|
|
34
36
|
}),
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
href: settingsHref
|
|
39
|
-
},
|
|
40
|
-
className: "flex shrink-0 items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-amber-700 transition-colors hover:bg-amber-500/10",
|
|
41
|
-
children: [/* @__PURE__ */ jsx(SettingsIcon, { className: "h-3.5 w-3.5" }), strings.modelPicker.manageProvider]
|
|
42
|
-
})
|
|
43
|
-
]
|
|
37
|
+
children: [/* @__PURE__ */ jsx(SettingsIcon, {}), strings.modelPicker.manageProvider]
|
|
38
|
+
}),
|
|
39
|
+
children: issueDetail(t, issue)
|
|
44
40
|
});
|
|
45
41
|
}
|
|
46
42
|
//#endregion
|
|
@@ -214,9 +214,9 @@ function ShareDialog({ conversationId, isOpen, onClose }) {
|
|
|
214
214
|
children: /* @__PURE__ */ jsx("button", {
|
|
215
215
|
type: "button",
|
|
216
216
|
onClick: () => handleRemoveTeam(perm.team),
|
|
217
|
-
className: "p-1 rounded hover:bg-
|
|
217
|
+
className: "p-1 rounded hover:bg-(--theme-error-muted)",
|
|
218
218
|
"aria-label": `${common.remove} ${perm.teamName || perm.team}`,
|
|
219
|
-
children: /* @__PURE__ */ jsx(TrashIcon, { className: "w-3 h-3 text-
|
|
219
|
+
children: /* @__PURE__ */ jsx(TrashIcon, { className: "w-3 h-3 text-(--theme-error)" })
|
|
220
220
|
})
|
|
221
221
|
})]
|
|
222
222
|
})]
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** The agent status words: one is picked per turn and held until it ends. */
|
|
2
|
-
export declare const activityWords: readonly ['Thinking', 'Cogitating', 'Pondering', 'Percolating', 'Ruminating', 'Noodling', 'Conjuring', 'Simmering', 'Marinating', 'Tinkering', 'Scheming', 'Brewing', 'Wrangling', 'Finagling', 'Spelunking', 'Puttering', 'Composing', 'Synthesizing', 'Deliberating', 'Mulling', 'Contemplating', 'Vibing', 'Whittling', 'Concocting', 'Formulating', 'Hatching', 'Herding', 'Ideating', 'Manifesting', 'Moseying', 'Musing', 'Percussing', 'Reticulating', 'Schlepping', 'Stewing', 'Transmuting', 'Wibbling', 'Crunching', 'Forging', 'Cooking'];
|
|
3
1
|
/** The terminal's "it's working" line for a running turn: spinner, status
|
|
4
2
|
* word, how long the turn has run, its token counts so far, and a way to
|
|
5
3
|
* stop it. */
|
|
@@ -7,63 +7,20 @@ import { useChatConfig } from "../../core/config.js";
|
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { useEffect, useRef, useState } from "react";
|
|
9
9
|
//#region src/ai/components/agent/ActivityLine.tsx
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"Thinking",
|
|
13
|
-
"Cogitating",
|
|
14
|
-
"Pondering",
|
|
15
|
-
"Percolating",
|
|
16
|
-
"Ruminating",
|
|
17
|
-
"Noodling",
|
|
18
|
-
"Conjuring",
|
|
19
|
-
"Simmering",
|
|
20
|
-
"Marinating",
|
|
21
|
-
"Tinkering",
|
|
22
|
-
"Scheming",
|
|
23
|
-
"Brewing",
|
|
24
|
-
"Wrangling",
|
|
25
|
-
"Finagling",
|
|
26
|
-
"Spelunking",
|
|
27
|
-
"Puttering",
|
|
28
|
-
"Composing",
|
|
29
|
-
"Synthesizing",
|
|
30
|
-
"Deliberating",
|
|
31
|
-
"Mulling",
|
|
32
|
-
"Contemplating",
|
|
33
|
-
"Vibing",
|
|
34
|
-
"Whittling",
|
|
35
|
-
"Concocting",
|
|
36
|
-
"Formulating",
|
|
37
|
-
"Hatching",
|
|
38
|
-
"Herding",
|
|
39
|
-
"Ideating",
|
|
40
|
-
"Manifesting",
|
|
41
|
-
"Moseying",
|
|
42
|
-
"Musing",
|
|
43
|
-
"Percussing",
|
|
44
|
-
"Reticulating",
|
|
45
|
-
"Schlepping",
|
|
46
|
-
"Stewing",
|
|
47
|
-
"Transmuting",
|
|
48
|
-
"Wibbling",
|
|
49
|
-
"Crunching",
|
|
50
|
-
"Forging",
|
|
51
|
-
"Cooking"
|
|
52
|
-
];
|
|
53
|
-
function randomActivityWord() {
|
|
54
|
-
return activityWords[Math.floor(Math.random() * activityWords.length)] ?? activityWords[0];
|
|
10
|
+
function randomIndex() {
|
|
11
|
+
return Math.floor(Math.random() * 1e6);
|
|
55
12
|
}
|
|
56
13
|
/** A status word held for the whole turn and re-rolled when a new one starts. */
|
|
57
|
-
function useTurnWord(startedAt) {
|
|
58
|
-
const [
|
|
14
|
+
function useTurnWord(startedAt, words) {
|
|
15
|
+
const [pick, setPick] = useState(randomIndex);
|
|
59
16
|
const turn = useRef(startedAt);
|
|
60
17
|
useEffect(() => {
|
|
61
18
|
if (turn.current !== startedAt) {
|
|
62
19
|
turn.current = startedAt;
|
|
63
|
-
|
|
20
|
+
setPick(randomIndex());
|
|
64
21
|
}
|
|
65
22
|
}, [startedAt]);
|
|
66
|
-
return
|
|
23
|
+
return words.length > 0 ? words[pick % words.length] ?? "" : "";
|
|
67
24
|
}
|
|
68
25
|
/** The terminal's "it's working" line for a running turn: spinner, status
|
|
69
26
|
* word, how long the turn has run, its token counts so far, and a way to
|
|
@@ -71,7 +28,7 @@ function useTurnWord(startedAt) {
|
|
|
71
28
|
function ActivityLine({ startedAt, inputTokens, outputTokens, onStop, stopping = false, word, testId }) {
|
|
72
29
|
const { strings } = useChatConfig();
|
|
73
30
|
const elapsed = useElapsed(startedAt);
|
|
74
|
-
const turnWord = useTurnWord(startedAt);
|
|
31
|
+
const turnWord = useTurnWord(startedAt, strings.activity.words);
|
|
75
32
|
const meta = [];
|
|
76
33
|
if (elapsed !== null) meta.push(formatDuration(elapsed));
|
|
77
34
|
if (inputTokens || outputTokens) meta.push(strings.activity.tokens(formatCount(inputTokens ?? 0), formatCount(outputTokens ?? 0)));
|
|
@@ -112,4 +69,4 @@ function ActivityLine({ startedAt, inputTokens, outputTokens, onStop, stopping =
|
|
|
112
69
|
});
|
|
113
70
|
}
|
|
114
71
|
//#endregion
|
|
115
|
-
export {
|
|
72
|
+
export { ActivityLine as default };
|