@parallelworks/ui 0.20.0 → 0.21.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/dist/ai/adapter/openai/createOpenAIStream.js +3 -2
- package/dist/ai/agent/diff.d.ts +0 -1
- package/dist/ai/agent/diff.js +3 -2
- package/dist/ai/agent/toolfmt.js +2 -3
- package/dist/ai/ai.css +5 -0
- package/dist/ai/components/AllocationSelector.js +3 -2
- package/dist/ai/components/AttachmentManager.js +1 -1
- package/dist/ai/components/BranchNavigator.js +4 -2
- package/dist/ai/components/ChatInput.d.ts +2 -5
- package/dist/ai/components/ChatInput.js +10 -7
- package/dist/ai/components/ChatMessage.js +7 -7
- package/dist/ai/components/ChatSidebar.d.ts +0 -1
- package/dist/ai/components/ChatSidebar.js +4 -6
- package/dist/ai/components/ChatThread.js +5 -8
- package/dist/ai/components/ModelSelector.js +3 -2
- package/dist/ai/components/ShareDialog.js +6 -3
- package/dist/ai/components/SlashMenu.d.ts +0 -1
- package/dist/ai/components/agent/ActivityLine.d.ts +0 -1
- package/dist/ai/components/agent/ActivityLine.js +2 -2
- package/dist/ai/components/agent/AgentMessageParts.d.ts +1 -26
- package/dist/ai/components/agent/AgentMessageParts.js +4 -5
- package/dist/ai/core/ChatProvider.d.ts +2 -6
- package/dist/ai/core/ChatProvider.js +42 -67
- package/dist/ai/core/KeyboardShortcutsProvider.js +1 -1
- package/dist/ai/core/chatReducer.d.ts +0 -6
- package/dist/ai/core/chatReducer.js +1 -15
- package/dist/ai/core/useKeyboardShortcuts.d.ts +3 -1
- package/dist/ai/core/useKeyboardShortcuts.js +9 -11
- package/dist/ai/core/useSSEStream.d.ts +0 -1
- package/dist/ai/core/useSSEStream.js +5 -17
- package/dist/ai/strings.d.ts +0 -1
- package/dist/ai/strings.js +0 -1
- package/dist/ai/types.d.ts +1 -1
- package/dist/ai/ui/Avatar.d.ts +1 -2
- package/dist/ai/ui/Avatar.js +7 -18
- package/dist/ai/ui/Markdown.d.ts +1 -3
- package/dist/ai/ui/Markdown.js +1 -2
- package/dist/ai/ui/sidebar.d.ts +0 -1
- package/dist/ai/ui/sidebar.js +3 -1
- package/dist/ai/utils.js +1 -1
- package/dist/components/Avatar.js +4 -2
- package/dist/components/BareModal.js +1 -5
- package/dist/components/Breadcrumbs.js +21 -14
- package/dist/components/CollapsiblePanel.d.ts +1 -3
- package/dist/components/CollapsiblePanel.js +5 -5
- package/dist/components/Dropdown.d.ts +0 -4
- package/dist/components/Dropdown.js +5 -6
- package/dist/components/Listbox.js +14 -18
- package/dist/components/MultiSelect.js +5 -8
- package/dist/components/Pagination.js +1 -1
- package/dist/components/Provider.d.ts +0 -8
- package/dist/components/SwitchToggle.js +3 -5
- package/dist/components/Table.d.ts +1 -3
- package/dist/components/dropdownUtils.js +5 -6
- package/dist/components/relativeTime.d.ts +0 -7
- package/dist/components/relativeTime.js +1 -1
- package/dist/duration.js +1 -1
- package/dist/editor/Editor.d.ts +1 -1
- package/dist/editor/Editor.js +1 -1
- package/dist/editor/EditorField.d.ts +0 -1
- package/dist/editor/EditorField.js +8 -8
- package/dist/editor/FormCodePanel.js +14 -20
- package/dist/editor/yamlLanguage.js +2 -2
- package/dist/file-explorer/FileExplorer.js +56 -59
- package/dist/file-explorer/FileExplorerContext.d.ts +1 -2
- package/dist/file-explorer/FileExplorerContext.js +92 -125
- package/dist/file-explorer/FilePreview/Inline.d.ts +1 -2
- package/dist/file-explorer/FilePreview/Inline.js +2 -2
- package/dist/file-explorer/FilePreview/Viewer.js +0 -4
- package/dist/file-explorer/FilePreview/index.d.ts +1 -2
- package/dist/file-explorer/FilePreview/index.js +3 -3
- package/dist/file-explorer/FilePreview/parse.d.ts +2 -1
- package/dist/file-explorer/FilePreview/useObjectBlobUrl.d.ts +5 -4
- package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +23 -36
- package/dist/file-explorer/FilePreview/useObjectText.d.ts +1 -2
- package/dist/file-explorer/FilePreview/useObjectText.js +5 -7
- package/dist/file-explorer/FileRow.js +1 -1
- package/dist/file-explorer/FileRowsWindow.d.ts +5 -12
- package/dist/file-explorer/FileTable.d.ts +2 -6
- package/dist/file-explorer/LoadMoreRow.d.ts +8 -0
- package/dist/file-explorer/TreeView.d.ts +0 -1
- package/dist/file-explorer/TreeView.js +6 -6
- package/dist/file-explorer/helpers.js +2 -4
- package/dist/file-explorer/lib/fileExplorer.d.ts +0 -2
- package/dist/file-explorer/lib/types.d.ts +0 -1
- package/dist/file-explorer/lib/utils.js +15 -20
- package/dist/file-explorer/toasts.js +36 -34
- package/dist/form/Fields/BooleanField.js +5 -4
- package/dist/form/Fields/CheckboxGroupField.js +5 -4
- package/dist/form/Fields/ColorField.js +5 -4
- package/dist/form/Fields/DropdownField.d.ts +0 -1
- package/dist/form/Fields/DropdownField.js +10 -13
- package/dist/form/Fields/DurationField.js +2 -2
- package/dist/form/Fields/LabelField.js +5 -5
- package/dist/form/Fields/MultiDropdownField.d.ts +1 -1
- package/dist/form/Fields/MultiDropdownField.js +8 -11
- package/dist/form/Fields/NumberField.js +6 -5
- package/dist/form/Fields/ObjectField.d.ts +1 -2
- package/dist/form/Fields/ObjectField.js +22 -21
- package/dist/form/Fields/RadioField.js +4 -3
- package/dist/form/Fields/RangeField.js +7 -6
- package/dist/form/Fields/StringField.js +2 -1
- package/dist/form/Fields/TextAreaField.js +2 -1
- package/dist/form/Form.d.ts +7 -8
- package/dist/form/Form.js +52 -78
- package/dist/form/SpecialTypes/DropdownWrapper.d.ts +0 -2
- package/dist/form/SpecialTypes/DropdownWrapper.js +1 -3
- package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +1 -3
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +4 -7
- package/dist/form/SpecialTypes/FormikCustomInput.js +13 -11
- package/dist/form/Wizard/WizardContainer.js +8 -25
- package/dist/form/Wizard/WizardNavigation.d.ts +1 -1
- package/dist/form/Wizard/WizardNavigation.js +5 -6
- package/dist/form/Wizard/WizardStepContent.d.ts +1 -1
- package/dist/form/Wizard/WizardStepContent.js +2 -2
- package/dist/form/Wizard/WizardStepIndicator.js +7 -17
- package/dist/form/Wizard/types.d.ts +4 -46
- package/dist/form/Wizard/useWizardState.d.ts +2 -10
- package/dist/form/Wizard/useWizardState.js +42 -92
- package/dist/form/Wizard/utils.js +6 -11
- package/dist/form/lib.js +28 -54
- package/dist/form/types/fieldTypes.d.ts +4 -5
- package/dist/form/utils/dependentOptions.d.ts +6 -0
- package/dist/form/utils/dependentOptions.js +21 -0
- package/dist/form/utils/getParentValue.d.ts +2 -1
- package/dist/form/utils/getParentValue.js +10 -15
- package/dist/form/utils/getValueUsingPath.js +1 -1
- package/dist/graph/AnnotationBanner.d.ts +1 -1
- package/dist/graph/AnnotationBanner.js +1 -1
- package/dist/graph/Collapse.d.ts +3 -3
- package/dist/graph/Collapse.js +3 -8
- package/dist/graph/DependencyGraph.d.ts +5 -4
- package/dist/graph/DependencyGraph.js +172 -222
- package/dist/graph/JobSummary.d.ts +10 -8
- package/dist/graph/JobSummary.js +13 -13
- package/dist/graph/MatrixGroup.d.ts +5 -17
- package/dist/graph/MatrixGroup.js +11 -22
- package/dist/graph/TreeView.d.ts +1 -3
- package/dist/graph/TreeView.js +104 -491
- package/dist/graph/types.d.ts +3 -2
- package/dist/graph/util.d.ts +5 -0
- package/dist/graph/util.js +18 -0
- package/dist/icons.d.ts +2 -2
- package/dist/icons.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/list/ListViewControls.js +17 -35
- package/dist/list/RowContextMenu.js +7 -7
- package/dist/logviewer/LogViewer.js +7 -9
- package/dist/logviewer/segments.js +2 -2
- package/dist/styles/theme.css +1 -0
- package/dist/styles.css +1 -1
- package/dist/theme/index.js +5 -5
- package/package.json +28 -30
- package/dist/ai/ui/buttons.d.ts +0 -1
|
@@ -5,8 +5,9 @@ import { processSSEStream } from "./sse.js";
|
|
|
5
5
|
//#region src/ai/adapter/openai/createOpenAIStream.ts
|
|
6
6
|
function createOpenAICompatibleStream(config) {
|
|
7
7
|
return async (req, handlers, signal) => {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const responsesUrl = req.useResponses === true ? config.responsesUrl : void 0;
|
|
9
|
+
const useResponses = !!responsesUrl;
|
|
10
|
+
const url = responsesUrl || config.completionsUrl;
|
|
10
11
|
const body = useResponses ? buildResponsesRequestBody(req.model, req.messages) : {
|
|
11
12
|
model: req.model,
|
|
12
13
|
messages: req.messages,
|
package/dist/ai/agent/diff.d.ts
CHANGED
package/dist/ai/agent/diff.js
CHANGED
|
@@ -2,6 +2,7 @@ import { sanitizeLabel } from "./toolfmt.js";
|
|
|
2
2
|
//#region src/ai/agent/diff.ts
|
|
3
3
|
var MAX_EDIT_DIFF_LINES = 100;
|
|
4
4
|
var MAX_WRITE_DIFF_LINES = 50;
|
|
5
|
+
var DIFF_CONTEXT = 3;
|
|
5
6
|
function isEditDiffTool(name) {
|
|
6
7
|
return name === "EditFile" || name === "WriteFile";
|
|
7
8
|
}
|
|
@@ -133,8 +134,8 @@ function computeEditDiff(oldString, newString, startLine = 0) {
|
|
|
133
134
|
if (!op) continue;
|
|
134
135
|
if (op.tag === "e") {
|
|
135
136
|
const len = op.i2 - op.i1;
|
|
136
|
-
const leading = k > 0 ? Math.min(
|
|
137
|
-
const trailing = k < ops.length - 1 ? Math.min(
|
|
137
|
+
const leading = k > 0 ? Math.min(DIFF_CONTEXT, len) : 0;
|
|
138
|
+
const trailing = k < ops.length - 1 ? Math.min(DIFF_CONTEXT, len) : 0;
|
|
138
139
|
const showAll = len <= leading + trailing;
|
|
139
140
|
const emit = (offset) => {
|
|
140
141
|
const oldNo = op.i1 + offset + 1;
|
package/dist/ai/agent/toolfmt.js
CHANGED
|
@@ -53,7 +53,7 @@ function clip(s, max) {
|
|
|
53
53
|
const r = [...s];
|
|
54
54
|
if (r.length <= max) return s;
|
|
55
55
|
if (max <= 3) return r.slice(0, max).join("");
|
|
56
|
-
return r.slice(0, max - 3).join("")
|
|
56
|
+
return `${r.slice(0, max - 3).join("")}...`;
|
|
57
57
|
}
|
|
58
58
|
function sanitizeLabel(s) {
|
|
59
59
|
let out = "";
|
|
@@ -211,8 +211,7 @@ function grepMatchPath(line, lineNums) {
|
|
|
211
211
|
const i = line.indexOf(":");
|
|
212
212
|
return i >= 0 ? line.slice(0, i) : null;
|
|
213
213
|
}
|
|
214
|
-
|
|
215
|
-
return m ? m[1] ?? null : null;
|
|
214
|
+
return GREP_CONTENT_PATH.exec(line)?.[1] ?? null;
|
|
216
215
|
}
|
|
217
216
|
function grepSearchSummary(argsJSON, body) {
|
|
218
217
|
if (body === "No matches found." || body === "No results after applying offset.") return "No matches";
|
package/dist/ai/ai.css
CHANGED
|
@@ -208,6 +208,7 @@
|
|
|
208
208
|
|
|
209
209
|
/* Light mode: use the primary Shiki theme (--sdm-bg/--sdm-c) */
|
|
210
210
|
.markdown [data-streamdown="code-block-body"] pre {
|
|
211
|
+
/* biome-ignore lint/complexity/noImportantStyles: the highlighter sets the background as an inline style */
|
|
211
212
|
background-color: var(--sdm-bg, inherit) !important;
|
|
212
213
|
color: var(--sdm-fg, inherit);
|
|
213
214
|
}
|
|
@@ -217,6 +218,7 @@
|
|
|
217
218
|
|
|
218
219
|
/* Dark mode: switch to --shiki-dark variants */
|
|
219
220
|
.dark .markdown [data-streamdown="code-block-body"] pre {
|
|
221
|
+
/* biome-ignore lint/complexity/noImportantStyles: the highlighter sets the background as an inline style */
|
|
220
222
|
background-color: var(--shiki-dark-bg, var(--sdm-bg, inherit)) !important;
|
|
221
223
|
color: var(--shiki-dark, var(--sdm-fg, inherit));
|
|
222
224
|
}
|
|
@@ -233,6 +235,7 @@
|
|
|
233
235
|
/* Remove prose backtick pseudo-elements on inline code */
|
|
234
236
|
.markdown code::before,
|
|
235
237
|
.markdown code::after {
|
|
238
|
+
/* biome-ignore lint/complexity/noImportantStyles: the typography styles add these with a more specific selector */
|
|
236
239
|
content: none !important;
|
|
237
240
|
}
|
|
238
241
|
|
|
@@ -250,7 +253,9 @@
|
|
|
250
253
|
@media (hover: none) {
|
|
251
254
|
.chat-actions,
|
|
252
255
|
.chat-meta {
|
|
256
|
+
/* biome-ignore lint/complexity/noImportantStyles: must win over the utility classes that hide these until hover */
|
|
253
257
|
opacity: 1 !important;
|
|
258
|
+
/* biome-ignore lint/complexity/noImportantStyles: must win over the utility classes that hide these until hover */
|
|
254
259
|
pointer-events: auto !important;
|
|
255
260
|
}
|
|
256
261
|
}
|
|
@@ -10,9 +10,10 @@ function AllocationSelector({ variant = "default" } = {}) {
|
|
|
10
10
|
const { adapter, selectedProvider, selectedAllocation, setSelectedAllocation } = useChat();
|
|
11
11
|
const isOrgProvider = isOrgModel(selectedProvider);
|
|
12
12
|
const allocationsAdapter = adapter.allocations;
|
|
13
|
-
const { data: allocations } = useSWR(isOrgProvider && allocationsAdapter ? ["ai-chat-allocations"] : null, () => allocationsAdapter
|
|
13
|
+
const { data: allocations } = useSWR(isOrgProvider && allocationsAdapter ? ["ai-chat-allocations"] : null, () => allocationsAdapter?.list());
|
|
14
14
|
useEffect(() => {
|
|
15
|
-
|
|
15
|
+
const first = allocations?.[0];
|
|
16
|
+
if (isOrgProvider && first && !selectedAllocation) setSelectedAllocation(first.name);
|
|
16
17
|
}, [
|
|
17
18
|
isOrgProvider,
|
|
18
19
|
allocations,
|
|
@@ -32,7 +32,7 @@ function AttachmentManager() {
|
|
|
32
32
|
[attachmentId]: state
|
|
33
33
|
});
|
|
34
34
|
}, []);
|
|
35
|
-
const { data: pages, size, setSize, isLoading, isValidating, mutate } = useSWRInfinite(attachmentsAdapter ? attachmentsPageKey : () => null, ([, cursor]) => attachmentsAdapter
|
|
35
|
+
const { data: pages, size, setSize, isLoading, isValidating, mutate } = useSWRInfinite(attachmentsAdapter ? attachmentsPageKey : () => null, ([, cursor]) => attachmentsAdapter?.list({
|
|
36
36
|
limit: 24,
|
|
37
37
|
cursor
|
|
38
38
|
}));
|
|
@@ -16,10 +16,12 @@ function BranchNavigator({ messages, currentMessageId, onNavigate }) {
|
|
|
16
16
|
const hasPrev = currentIndex > 0;
|
|
17
17
|
const hasNext = currentIndex < siblings.length - 1;
|
|
18
18
|
const handlePrev = () => {
|
|
19
|
-
|
|
19
|
+
const prev = siblings[currentIndex - 1];
|
|
20
|
+
if (hasPrev && prev) onNavigate(prev.id);
|
|
20
21
|
};
|
|
21
22
|
const handleNext = () => {
|
|
22
|
-
|
|
23
|
+
const next = siblings[currentIndex + 1];
|
|
24
|
+
if (hasNext && next) onNavigate(next.id);
|
|
23
25
|
};
|
|
24
26
|
return /* @__PURE__ */ jsxs("div", {
|
|
25
27
|
className: "inline-flex items-center gap-1 text-xs theme-muted-text",
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
import type { AttachmentMeta } from '../types.js';
|
|
2
3
|
import { type SlashMenuConfig } from './SlashMenu.js';
|
|
3
4
|
interface ChatInputProps {
|
|
4
|
-
onSend: (content: string, attachmentIds?: string[], attachmentMeta?:
|
|
5
|
-
filename: string;
|
|
6
|
-
contentType: string;
|
|
7
|
-
size: number;
|
|
8
|
-
}>) => void;
|
|
5
|
+
onSend: (content: string, attachmentIds?: string[], attachmentMeta?: AttachmentMeta) => void;
|
|
9
6
|
disabled?: boolean;
|
|
10
7
|
placeholder?: string | undefined;
|
|
11
8
|
conversationId?: string;
|
|
@@ -139,14 +139,17 @@ var ChatInput = forwardRef(function ChatInput({ onSend, disabled = false, placeh
|
|
|
139
139
|
flushQueuedMessages();
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
142
|
-
const
|
|
143
|
-
const attachmentIds = uploaded.map((a) => a.id);
|
|
142
|
+
const attachmentIds = [];
|
|
144
143
|
const meta = {};
|
|
145
|
-
for (const a of
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
for (const a of attachments) {
|
|
145
|
+
if (!a.uploaded || !a.id) continue;
|
|
146
|
+
attachmentIds.push(a.id);
|
|
147
|
+
meta[a.id] = {
|
|
148
|
+
filename: a.filename,
|
|
149
|
+
contentType: a.mimeType,
|
|
150
|
+
size: a.size
|
|
151
|
+
};
|
|
152
|
+
}
|
|
150
153
|
onSend(input.trim(), attachmentIds.length > 0 ? attachmentIds : void 0, attachmentIds.length > 0 ? meta : void 0);
|
|
151
154
|
setInput("");
|
|
152
155
|
clearDraft(conversationId);
|
|
@@ -36,7 +36,8 @@ function triggerDownload(url, filename) {
|
|
|
36
36
|
function ChatMessage({ message, allMessages, isStreaming = false, isEditing = false, showAuthor = false, currentUsername, attachmentDownloadUrl, onOpenAttachment, onNavigateBranch, onEdit, onSaveEdit, onCancelEdit, onRegenerate, onRetry, onOpenReasoning, onApprovalAnswer, flush }) {
|
|
37
37
|
const isUser = message.role === "user";
|
|
38
38
|
const isTool = message.role === "tool";
|
|
39
|
-
const
|
|
39
|
+
const otherAuthor = isUser && showAuthor && message.author && currentUsername && message.author.username !== currentUsername ? message.author : void 0;
|
|
40
|
+
const isOtherUser = !!otherAuthor;
|
|
40
41
|
const isRightAligned = isUser && !isOtherUser;
|
|
41
42
|
const hasError = !!message.error;
|
|
42
43
|
const hasReasoning = !!message.reasoning;
|
|
@@ -169,16 +170,15 @@ function ChatMessage({ message, allMessages, isStreaming = false, isEditing = fa
|
|
|
169
170
|
onApprovalAnswer
|
|
170
171
|
})
|
|
171
172
|
}),
|
|
172
|
-
|
|
173
|
+
otherAuthor && /* @__PURE__ */ jsx("span", {
|
|
173
174
|
className: "text-xs theme-muted-text",
|
|
174
|
-
children:
|
|
175
|
+
children: otherAuthor.name || otherAuthor.username
|
|
175
176
|
}),
|
|
176
|
-
message.content ?
|
|
177
|
+
message.content ? otherAuthor ? /* @__PURE__ */ jsxs("div", {
|
|
177
178
|
className: "flex items-end gap-2",
|
|
178
179
|
children: [/* @__PURE__ */ jsx(Avatar, {
|
|
179
|
-
src:
|
|
180
|
-
name:
|
|
181
|
-
size: "sm",
|
|
180
|
+
src: otherAuthor.avatarUrl ?? void 0,
|
|
181
|
+
name: otherAuthor.name || otherAuthor.username,
|
|
182
182
|
className: "flex-shrink-0 mb-0.5"
|
|
183
183
|
}), /* @__PURE__ */ jsx("div", {
|
|
184
184
|
className: "px-4 py-2.5 chat-ink rounded-2xl rounded-bl-md max-w-[70%] inline-block whitespace-pre-wrap text-base leading-6 bg-[color-mix(in_oklab,var(--theme-panel)_6%,transparent)]",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export type ConversationGroupKey = 'groupToday' | 'groupYesterday' | 'groupThisWeek' | 'groupThisMonth' | 'groupOlder';
|
|
2
1
|
export default function ChatSidebar({ actions, }: {
|
|
3
2
|
/** False when the host's page header carries new chat, attachments and search. */
|
|
4
3
|
actions?: boolean;
|
|
@@ -85,16 +85,15 @@ function ConversationRow({ conv, isCurrent, sharingAvailable, openMenu, onRename
|
|
|
85
85
|
var SIDEBAR_WIDTH_STORAGE_KEY = "aiChatSidebarWidth";
|
|
86
86
|
var SIDEBAR_MIN_WIDTH_PX = 200;
|
|
87
87
|
var SIDEBAR_MAX_WIDTH_PX = 480;
|
|
88
|
-
var SIDEBAR_DEFAULT_WIDTH_PX = 256;
|
|
89
88
|
function clampSidebarWidth(width) {
|
|
90
89
|
return Math.min(SIDEBAR_MAX_WIDTH_PX, Math.max(SIDEBAR_MIN_WIDTH_PX, width));
|
|
91
90
|
}
|
|
92
91
|
function readStoredSidebarWidth() {
|
|
93
92
|
try {
|
|
94
93
|
const stored = Number(window.localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY));
|
|
95
|
-
return Number.isFinite(stored) && stored > 0 ? clampSidebarWidth(stored) :
|
|
94
|
+
return Number.isFinite(stored) && stored > 0 ? clampSidebarWidth(stored) : 256;
|
|
96
95
|
} catch {
|
|
97
|
-
return
|
|
96
|
+
return 256;
|
|
98
97
|
}
|
|
99
98
|
}
|
|
100
99
|
function storeSidebarWidth(width) {
|
|
@@ -125,8 +124,8 @@ function useResizableSidebarWidth() {
|
|
|
125
124
|
window.addEventListener("pointerup", onUp);
|
|
126
125
|
};
|
|
127
126
|
const reset = () => {
|
|
128
|
-
setWidth(
|
|
129
|
-
storeSidebarWidth(
|
|
127
|
+
setWidth(256);
|
|
128
|
+
storeSidebarWidth(256);
|
|
130
129
|
};
|
|
131
130
|
const nudge = (delta) => {
|
|
132
131
|
const next = clampSidebarWidth(widthRef.current + delta);
|
|
@@ -211,7 +210,6 @@ function ChatSidebar({ actions = true }) {
|
|
|
211
210
|
/* @__PURE__ */ jsxs(SidebarPanel, {
|
|
212
211
|
collapsed: sidebarCollapsed,
|
|
213
212
|
width: sidebarWidth,
|
|
214
|
-
railWidth: 48,
|
|
215
213
|
resizing,
|
|
216
214
|
children: [
|
|
217
215
|
!sidebarCollapsed && /* @__PURE__ */ jsx("div", {
|
|
@@ -61,11 +61,8 @@ function ChatThread({ conversationId }) {
|
|
|
61
61
|
setEditingState(null);
|
|
62
62
|
}, []);
|
|
63
63
|
const handleEditLastMessage = useCallback(() => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
handleEditMessage(conversationMessages[i].id);
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
64
|
+
const lastUserMessage = (currentConversation?.messages || []).findLast((m) => m.role === "user");
|
|
65
|
+
if (lastUserMessage) handleEditMessage(lastUserMessage.id);
|
|
69
66
|
}, [currentConversation?.messages, handleEditMessage]);
|
|
70
67
|
const handleNavigateBranch = useCallback((messageId) => {
|
|
71
68
|
navigateToBranch?.(messageId);
|
|
@@ -73,9 +70,9 @@ function ChatThread({ conversationId }) {
|
|
|
73
70
|
const handleRegenerateMessage = useCallback((messageId) => {
|
|
74
71
|
const conversationMessages = currentConversation?.messages || [];
|
|
75
72
|
const assistantMessage = conversationMessages.find((m) => m.id === messageId);
|
|
76
|
-
if (
|
|
73
|
+
if (assistantMessage?.role !== "assistant") return;
|
|
77
74
|
const userMessage = conversationMessages.find((m) => m.id === assistantMessage.parentId);
|
|
78
|
-
if (
|
|
75
|
+
if (userMessage?.role !== "user") return;
|
|
79
76
|
sendMessage(userMessage.content || "", userMessage.attachments?.map((a) => a.id), userMessage.parentId || void 0);
|
|
80
77
|
}, [currentConversation?.messages, sendMessage]);
|
|
81
78
|
const handleRetryMessage = useCallback((messageId) => {
|
|
@@ -99,7 +96,7 @@ function ChatThread({ conversationId }) {
|
|
|
99
96
|
]);
|
|
100
97
|
const messages = currentConversation?.messages || [];
|
|
101
98
|
const showAuthor = useMemo(() => {
|
|
102
|
-
return new Set(messages.
|
|
99
|
+
return new Set(messages.flatMap((m) => m.author ? [m.author.username] : [])).size > 1 || currentConversation?.isOwner === false;
|
|
103
100
|
}, [messages, currentConversation?.isOwner]);
|
|
104
101
|
if (isLoadingConversation && !currentConversation) return /* @__PURE__ */ jsxs("div", {
|
|
105
102
|
className: "flex flex-col h-full bg-(--theme-panel-bg)",
|
|
@@ -33,8 +33,9 @@ function groupModelsByProvider(models) {
|
|
|
33
33
|
const groups = /* @__PURE__ */ new Map();
|
|
34
34
|
for (const model of models) {
|
|
35
35
|
const key = model.id.includes("/") ? getProviderKeyFromModelId(model.id) : model.provider ?? model.owned_by;
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const group = groups.get(key);
|
|
37
|
+
if (group) group.push(model);
|
|
38
|
+
else groups.set(key, [model]);
|
|
38
39
|
}
|
|
39
40
|
return groups;
|
|
40
41
|
}
|
|
@@ -7,6 +7,9 @@ import Dropdown from "../ui/Dropdown.js";
|
|
|
7
7
|
import { useCallback, useEffect, useState, useTransition } from "react";
|
|
8
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/ai/components/ShareDialog.tsx
|
|
10
|
+
function isTeamPermission(p) {
|
|
11
|
+
return !!p.team && !p.entireOrganization;
|
|
12
|
+
}
|
|
10
13
|
function ShareDialog({ conversationId, isOpen, onClose }) {
|
|
11
14
|
const { strings } = useChatConfig();
|
|
12
15
|
const t = strings.shareConversation;
|
|
@@ -66,8 +69,8 @@ function ShareDialog({ conversationId, isOpen, onClose }) {
|
|
|
66
69
|
});
|
|
67
70
|
else if (!wantOrgPerm && hadOrgPerm?.id) await sharing.removePermission(conversationId, hadOrgPerm.id);
|
|
68
71
|
else if (wantOrgPerm && hadOrgPerm?.id && (originalOrgCollaborateAccess !== orgCollaborateAccess || hadOrgPerm.permission === "collaborate" !== orgCollaborateAccess)) await sharing.updatePermission(conversationId, hadOrgPerm.id, orgCollaborateAccess ? "collaborate" : "view");
|
|
69
|
-
const originalTeamPerms = originalPermissions.filter(
|
|
70
|
-
const currentTeamPerms = permissions.filter(
|
|
72
|
+
const originalTeamPerms = originalPermissions.filter(isTeamPermission);
|
|
73
|
+
const currentTeamPerms = permissions.filter(isTeamPermission);
|
|
71
74
|
for (const perm of currentTeamPerms) {
|
|
72
75
|
const original = originalTeamPerms.find((p) => p.team === perm.team);
|
|
73
76
|
if (!original) await sharing.addPermission(conversationId, {
|
|
@@ -117,7 +120,7 @@ function ShareDialog({ conversationId, isOpen, onClose }) {
|
|
|
117
120
|
} : p));
|
|
118
121
|
}, []);
|
|
119
122
|
if (!sharing) return null;
|
|
120
|
-
const teamPermissions = permissions.filter(
|
|
123
|
+
const teamPermissions = permissions.filter(isTeamPermission);
|
|
121
124
|
const availableTeams = teams.filter((team) => !permissions.some((p) => p.team === team.id));
|
|
122
125
|
return /* @__PURE__ */ jsx(ConfirmModal, {
|
|
123
126
|
open: isOpen,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/** The agent status words: one is picked per turn and held until it ends. */
|
|
2
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
|
-
export declare function randomActivityWord(): string;
|
|
4
3
|
/** Elapsed run time the way an agent status line prints it: 45s, 2m13s,
|
|
5
4
|
* 1h2m3s. */
|
|
6
5
|
export declare function formatElapsed(seconds: number): string;
|
|
@@ -49,7 +49,7 @@ var activityWords = [
|
|
|
49
49
|
"Cooking"
|
|
50
50
|
];
|
|
51
51
|
function randomActivityWord() {
|
|
52
|
-
return activityWords[Math.floor(Math.random() * activityWords.length)];
|
|
52
|
+
return activityWords[Math.floor(Math.random() * activityWords.length)] ?? activityWords[0];
|
|
53
53
|
}
|
|
54
54
|
/** Elapsed run time the way an agent status line prints it: 45s, 2m13s,
|
|
55
55
|
* 1h2m3s. */
|
|
@@ -148,4 +148,4 @@ function ActivityLine({ startedAt, inputTokens, outputTokens, onStop, stopping =
|
|
|
148
148
|
});
|
|
149
149
|
}
|
|
150
150
|
//#endregion
|
|
151
|
-
export { activityWords, compactCount, ActivityLine as default, formatElapsed
|
|
151
|
+
export { activityWords, compactCount, ActivityLine as default, formatElapsed };
|
|
@@ -1,31 +1,9 @@
|
|
|
1
1
|
import { type PartRendererProps } from '../../core/config.js';
|
|
2
|
-
import type { ApprovalPart, MessagePart,
|
|
3
|
-
export declare function ToolCallBlock({ part }: {
|
|
4
|
-
part: ToolCallPart;
|
|
5
|
-
}): import("react").JSX.Element;
|
|
6
|
-
/** Drawn the way the TUI draws a delegated Task: a tool-shaped header
|
|
7
|
-
* `Task(description)`, and under it the latest action while running or
|
|
8
|
-
* `Done (summary)` once finished. Expanding shows the whole activity feed. */
|
|
9
|
-
export declare function SubagentCard({ part }: {
|
|
10
|
-
part: SubagentPart;
|
|
11
|
-
}): import("react").JSX.Element;
|
|
2
|
+
import type { ApprovalPart, MessagePart, ReasoningPart, ToolCallPart } from '../../types.js';
|
|
12
3
|
export declare function ApprovalBlock({ part, onApprovalAnswer, }: {
|
|
13
4
|
part: ApprovalPart;
|
|
14
5
|
onApprovalAnswer?: PartRendererProps['onApprovalAnswer'];
|
|
15
6
|
}): import("react").JSX.Element;
|
|
16
|
-
export declare function TodoSnapshotBlock({ part }: {
|
|
17
|
-
part: TodoSnapshotPart;
|
|
18
|
-
}): import("react").JSX.Element;
|
|
19
|
-
export declare function NoticeBlock({ part }: {
|
|
20
|
-
part: NoticePart;
|
|
21
|
-
}): import("react").JSX.Element;
|
|
22
|
-
/** The TUI's thought: the body shows while it streams, then folds to its
|
|
23
|
-
* label and opens on request. The composer's activity line carries the
|
|
24
|
-
* live signal, so nothing here animates. */
|
|
25
|
-
export declare function ReasoningBlock({ part, isStreaming, }: {
|
|
26
|
-
part: ReasoningPart;
|
|
27
|
-
isStreaming?: boolean;
|
|
28
|
-
}): import("react").JSX.Element;
|
|
29
7
|
type RunMember = {
|
|
30
8
|
part: ToolCallPart | ReasoningPart;
|
|
31
9
|
index: number;
|
|
@@ -42,9 +20,6 @@ type RenderItem = {
|
|
|
42
20
|
kind: 'rollup';
|
|
43
21
|
members: RunMember[];
|
|
44
22
|
};
|
|
45
|
-
/** Two thoughts with nothing visible between them read as one, not as a
|
|
46
|
-
* stack of identical lines. */
|
|
47
|
-
export declare function mergeReasoning(parts: ReasoningPart[]): ReasoningPart;
|
|
48
23
|
export declare function buildRenderItems(parts: MessagePart[]): RenderItem[];
|
|
49
24
|
export default function AgentMessageParts({ message, isStreaming, onApprovalAnswer, }: {
|
|
50
25
|
message: PartRendererProps['message'];
|
|
@@ -632,10 +632,9 @@ function buildRenderItems(parts) {
|
|
|
632
632
|
emitThoughts(thoughts);
|
|
633
633
|
};
|
|
634
634
|
const flush = () => {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
while (end > start && isReasoning(run[end - 1])) end--;
|
|
635
|
+
const firstCore = run.findIndex((m) => !isReasoning(m));
|
|
636
|
+
const start = firstCore === -1 ? run.length : firstCore;
|
|
637
|
+
const end = firstCore === -1 ? run.length : run.findLastIndex((m) => !isReasoning(m)) + 1;
|
|
639
638
|
emitThoughts(run.slice(0, start));
|
|
640
639
|
const core = run.slice(start, end);
|
|
641
640
|
if (core.filter((m) => !isReasoning(m)).length >= 2) items.push({
|
|
@@ -718,4 +717,4 @@ function AgentMessageParts({ message, isStreaming, onApprovalAnswer }) {
|
|
|
718
717
|
});
|
|
719
718
|
}
|
|
720
719
|
//#endregion
|
|
721
|
-
export { ApprovalBlock,
|
|
720
|
+
export { ApprovalBlock, buildRenderItems, AgentMessageParts as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { ChatAdapter } from '../adapter/types.js';
|
|
3
|
-
import type { ChatModel, ChatNavigation, ChatNotify, ChatUser, Conversation, ConversationSummary, ChatMessage as Message, MessagePart, ProviderInfo, UnreachableSession } from '../types.js';
|
|
3
|
+
import type { AttachmentMeta, ChatModel, ChatNavigation, ChatNotify, ChatUser, Conversation, ConversationSummary, ChatMessage as Message, MessagePart, ProviderInfo, UnreachableSession } from '../types.js';
|
|
4
4
|
import { type ChatUIConfig } from './config.js';
|
|
5
5
|
interface ChatContextValue {
|
|
6
6
|
adapter: ChatAdapter;
|
|
@@ -36,11 +36,7 @@ interface ChatContextValue {
|
|
|
36
36
|
refreshModels: () => Promise<void>;
|
|
37
37
|
createConversation: (title?: string) => Promise<string | null>;
|
|
38
38
|
deleteConversation: (id: string) => Promise<boolean>;
|
|
39
|
-
sendMessage: (content: string, attachmentIds?: string[], parentId?: string, attachmentMeta?:
|
|
40
|
-
filename: string;
|
|
41
|
-
contentType: string;
|
|
42
|
-
size: number;
|
|
43
|
-
}>) => Promise<boolean>;
|
|
39
|
+
sendMessage: (content: string, attachmentIds?: string[], parentId?: string, attachmentMeta?: AttachmentMeta) => Promise<boolean>;
|
|
44
40
|
retryMessage: (messageId: string) => Promise<boolean>;
|
|
45
41
|
setSelectedProvider: (providerId: string | null) => void;
|
|
46
42
|
setSelectedAllocation: (allocation: string | null) => void;
|