@optilogic/chat 1.0.0-beta.6 → 1.0.0-beta.7
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 +99 -0
- package/dist/index.cjs +167 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -6
- package/dist/index.d.ts +98 -6
- package/dist/index.js +168 -16
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/agent-response/AgentResponse.tsx +29 -4
- package/src/components/agent-response/components/ActivityIndicators.tsx +36 -4
- package/src/components/agent-response/components/MetadataRow.tsx +6 -2
- package/src/components/agent-response/components/ThinkingSection.tsx +101 -9
- package/src/components/agent-response/hooks/useAgentResponseAccumulator.ts +41 -0
- package/src/components/agent-response/index.ts +3 -0
- package/src/components/agent-response/types.ts +54 -1
- package/src/components/user-prompt-input/UserPromptInput.tsx +79 -18
- package/src/components/user-prompt-input/types.ts +10 -0
- package/src/index.ts +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# @optilogic/chat
|
|
2
|
+
|
|
3
|
+
Chat UI components for opti-ui - Components for displaying LLM/AI agent interactions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @optilogic/chat @optilogic/core @optilogic/editor slate slate-react slate-history
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Make sure you have configured `@optilogic/core` with the Tailwind preset and CSS variables.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### AgentResponse
|
|
18
|
+
|
|
19
|
+
Display AI agent responses with thinking indicators, tool calls, and feedback actions:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { AgentResponse, useAgentResponseAccumulator } from '@optilogic/chat';
|
|
23
|
+
|
|
24
|
+
function ChatView() {
|
|
25
|
+
const { state, handlers } = useAgentResponseAccumulator({
|
|
26
|
+
onComplete: (response) => console.log('Response complete:', response),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<AgentResponse
|
|
31
|
+
{...state}
|
|
32
|
+
onCopy={() => navigator.clipboard.writeText(state.content)}
|
|
33
|
+
onFeedback={(value) => console.log('Feedback:', value)}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### UserPrompt
|
|
40
|
+
|
|
41
|
+
Display user messages in the chat:
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { UserPrompt } from '@optilogic/chat';
|
|
45
|
+
|
|
46
|
+
function ChatMessage() {
|
|
47
|
+
return (
|
|
48
|
+
<UserPrompt
|
|
49
|
+
content="What is the weather today?"
|
|
50
|
+
timestamp={new Date()}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### UserPromptInput
|
|
57
|
+
|
|
58
|
+
Input component for user messages:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { UserPromptInput } from '@optilogic/chat';
|
|
62
|
+
|
|
63
|
+
function ChatInput() {
|
|
64
|
+
return (
|
|
65
|
+
<UserPromptInput
|
|
66
|
+
onSubmit={(text) => console.log('Submitted:', text)}
|
|
67
|
+
placeholder="Type your message..."
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Components
|
|
74
|
+
|
|
75
|
+
### AgentResponse
|
|
76
|
+
Main component for displaying AI agent responses with:
|
|
77
|
+
- Streaming content support
|
|
78
|
+
- Thinking/reasoning indicators
|
|
79
|
+
- Tool call visualization
|
|
80
|
+
- Copy and feedback actions
|
|
81
|
+
- Metadata display (tokens, timing)
|
|
82
|
+
|
|
83
|
+
### UserPrompt
|
|
84
|
+
Component for displaying user messages in the chat interface.
|
|
85
|
+
|
|
86
|
+
### UserPromptInput
|
|
87
|
+
Input component for composing user messages with tag support.
|
|
88
|
+
|
|
89
|
+
## Hooks
|
|
90
|
+
|
|
91
|
+
### useAgentResponseAccumulator
|
|
92
|
+
Manages state for streaming agent responses, handling incremental updates and message accumulation.
|
|
93
|
+
|
|
94
|
+
### useThinkingTimer
|
|
95
|
+
Tracks elapsed time during agent thinking phases.
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -28,10 +28,30 @@ var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
|
|
|
28
28
|
|
|
29
29
|
// src/components/agent-response/AgentResponse.tsx
|
|
30
30
|
var ActivityIndicators = React7__namespace.forwardRef(
|
|
31
|
-
({ toolCalls, knowledge, memory, className, ...props }, ref) => {
|
|
32
|
-
const hasAnyActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0;
|
|
31
|
+
({ toolCalls, knowledge, memory, statusUpdates = [], className, ...props }, ref) => {
|
|
32
|
+
const hasAnyActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0 || statusUpdates.length > 0;
|
|
33
33
|
if (!hasAnyActivity) return null;
|
|
34
34
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: core.cn("flex items-center gap-2", className), ...props, children: [
|
|
35
|
+
statusUpdates.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(core.Popover, { children: [
|
|
36
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
37
|
+
"button",
|
|
38
|
+
{
|
|
39
|
+
className: "flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",
|
|
40
|
+
onClick: (e) => e.stopPropagation(),
|
|
41
|
+
children: [
|
|
42
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Activity, { className: "w-3.5 h-3.5" }),
|
|
43
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: statusUpdates.length })
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
) }),
|
|
47
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.PopoverContent, { className: "w-80", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
48
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-medium text-sm", children: "Status Updates" }),
|
|
49
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2 max-h-60 overflow-auto", children: statusUpdates.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 bg-muted rounded text-xs", children: [
|
|
50
|
+
item.agent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-muted-foreground", children: item.agent }),
|
|
51
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: item.agent ? "mt-1" : "", children: item.message })
|
|
52
|
+
] }, item.id)) })
|
|
53
|
+
] }) })
|
|
54
|
+
] }),
|
|
35
55
|
toolCalls.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(core.Popover, { children: [
|
|
36
56
|
/* @__PURE__ */ jsxRuntime.jsx(core.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
37
57
|
"button",
|
|
@@ -134,6 +154,7 @@ var MetadataRow = React7__namespace.forwardRef(
|
|
|
134
154
|
toolCalls,
|
|
135
155
|
knowledge,
|
|
136
156
|
memory,
|
|
157
|
+
statusUpdates = [],
|
|
137
158
|
status,
|
|
138
159
|
elapsedTime,
|
|
139
160
|
className,
|
|
@@ -141,7 +162,7 @@ var MetadataRow = React7__namespace.forwardRef(
|
|
|
141
162
|
}, ref) => {
|
|
142
163
|
const isProcessing = status === "processing";
|
|
143
164
|
const isComplete = status === "complete";
|
|
144
|
-
const hasActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0;
|
|
165
|
+
const hasActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0 || statusUpdates.length > 0;
|
|
145
166
|
const renderLeftContent = () => {
|
|
146
167
|
if (hasThinking) {
|
|
147
168
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
@@ -181,7 +202,8 @@ var MetadataRow = React7__namespace.forwardRef(
|
|
|
181
202
|
{
|
|
182
203
|
toolCalls,
|
|
183
204
|
knowledge,
|
|
184
|
-
memory
|
|
205
|
+
memory,
|
|
206
|
+
statusUpdates
|
|
185
207
|
}
|
|
186
208
|
)
|
|
187
209
|
]
|
|
@@ -190,18 +212,55 @@ var MetadataRow = React7__namespace.forwardRef(
|
|
|
190
212
|
}
|
|
191
213
|
);
|
|
192
214
|
MetadataRow.displayName = "MetadataRow";
|
|
215
|
+
var ThinkingStepItem = ({ step, renderMarkdown }) => {
|
|
216
|
+
const [isCollapsed, setIsCollapsed] = React7.useState(step.isCollapsed ?? false);
|
|
217
|
+
const toggleCollapse = React7.useCallback(() => {
|
|
218
|
+
setIsCollapsed((prev) => !prev);
|
|
219
|
+
}, []);
|
|
220
|
+
const indentPadding = step.depth * 16;
|
|
221
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border/50 last:border-b-0", children: [
|
|
222
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
223
|
+
"button",
|
|
224
|
+
{
|
|
225
|
+
onClick: toggleCollapse,
|
|
226
|
+
className: "w-full flex items-center gap-1.5 py-1.5 px-2 hover:bg-muted/50 transition-colors text-left",
|
|
227
|
+
style: { paddingLeft: `${indentPadding + 8}px` },
|
|
228
|
+
children: [
|
|
229
|
+
isCollapsed ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-3 h-3 text-muted-foreground flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "w-3 h-3 text-muted-foreground flex-shrink-0" }),
|
|
230
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-foreground/80", children: step.label })
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
),
|
|
234
|
+
!isCollapsed && /* @__PURE__ */ jsxRuntime.jsx(
|
|
235
|
+
"div",
|
|
236
|
+
{
|
|
237
|
+
className: "pb-2 px-2",
|
|
238
|
+
style: { paddingLeft: `${indentPadding + 28}px` },
|
|
239
|
+
children: renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: renderMarkdown(step.content) }) : /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs text-muted-foreground whitespace-pre-wrap font-mono", children: step.content })
|
|
240
|
+
}
|
|
241
|
+
)
|
|
242
|
+
] });
|
|
243
|
+
};
|
|
193
244
|
var ThinkingSection = React7__namespace.forwardRef(
|
|
194
|
-
({ content, isExpanded, className, ...props }, ref) => {
|
|
195
|
-
if (!isExpanded || !content) {
|
|
245
|
+
({ content, isExpanded, renderMarkdown, className, ...props }, ref) => {
|
|
246
|
+
if (!isExpanded || !content || Array.isArray(content) && content.length === 0) {
|
|
196
247
|
return null;
|
|
197
248
|
}
|
|
249
|
+
const isStructured = Array.isArray(content);
|
|
198
250
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
199
251
|
"div",
|
|
200
252
|
{
|
|
201
253
|
ref,
|
|
202
254
|
className: core.cn("px-3 pb-3 border-t border-border", className),
|
|
203
255
|
...props,
|
|
204
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 max-h-[200px] overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx("
|
|
256
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 max-h-[200px] overflow-y-auto", children: isStructured ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0", children: content.map((step) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
257
|
+
ThinkingStepItem,
|
|
258
|
+
{
|
|
259
|
+
step,
|
|
260
|
+
renderMarkdown
|
|
261
|
+
},
|
|
262
|
+
step.id
|
|
263
|
+
)) }) : renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: renderMarkdown(content) }) : /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs text-muted-foreground whitespace-pre-wrap font-mono", children: content }) })
|
|
205
264
|
}
|
|
206
265
|
);
|
|
207
266
|
}
|
|
@@ -330,6 +389,7 @@ var initialAgentResponseState = {
|
|
|
330
389
|
toolCalls: [],
|
|
331
390
|
knowledge: [],
|
|
332
391
|
memory: [],
|
|
392
|
+
statusUpdates: [],
|
|
333
393
|
response: "",
|
|
334
394
|
thinkingStartTime: null,
|
|
335
395
|
responseCompleteTime: null,
|
|
@@ -364,6 +424,23 @@ function useAgentResponseAccumulator(options) {
|
|
|
364
424
|
}
|
|
365
425
|
return { ...prev, status: newStatus };
|
|
366
426
|
case "thinking": {
|
|
427
|
+
if (payload.thinkingStep) {
|
|
428
|
+
const newStep = {
|
|
429
|
+
id: payload.thinkingStep.id || `step-${Date.now()}`,
|
|
430
|
+
label: payload.thinkingStep.label,
|
|
431
|
+
content: payload.thinkingStep.content,
|
|
432
|
+
depth: payload.thinkingStep.depth ?? 0,
|
|
433
|
+
isCollapsed: payload.thinkingStep.isCollapsed
|
|
434
|
+
};
|
|
435
|
+
const thinkingStartTime2 = prev.thinkingStartTime ?? Date.now();
|
|
436
|
+
return {
|
|
437
|
+
...prev,
|
|
438
|
+
status: newStatus,
|
|
439
|
+
thinkingSteps: [...prev.thinkingSteps || [], newStep],
|
|
440
|
+
thinkingStartTime: thinkingStartTime2,
|
|
441
|
+
firstMessageTime
|
|
442
|
+
};
|
|
443
|
+
}
|
|
367
444
|
const newThinking = payload.message || payload.content || "";
|
|
368
445
|
const separator = prev.thinking && newThinking ? "\n\n" : "";
|
|
369
446
|
const thinkingStartTime = prev.thinkingStartTime ?? (newThinking ? Date.now() : null);
|
|
@@ -437,6 +514,24 @@ function useAgentResponseAccumulator(options) {
|
|
|
437
514
|
responseCompleteTime: Date.now(),
|
|
438
515
|
firstMessageTime: prev.firstMessageTime ?? Date.now()
|
|
439
516
|
};
|
|
517
|
+
case "status_update": {
|
|
518
|
+
const statusMessage = payload.message || payload.statusUpdate?.message;
|
|
519
|
+
if (statusMessage) {
|
|
520
|
+
const newStatusItem = {
|
|
521
|
+
id: payload.statusUpdate?.id || `status-${Date.now()}`,
|
|
522
|
+
message: statusMessage,
|
|
523
|
+
agent: payload.statusUpdate?.agent,
|
|
524
|
+
timestamp: Date.now()
|
|
525
|
+
};
|
|
526
|
+
return {
|
|
527
|
+
...prev,
|
|
528
|
+
status: newStatus,
|
|
529
|
+
statusUpdates: [...prev.statusUpdates, newStatusItem],
|
|
530
|
+
firstMessageTime
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
return { ...prev, status: newStatus, firstMessageTime };
|
|
534
|
+
}
|
|
440
535
|
default:
|
|
441
536
|
return { ...prev, status: newStatus, firstMessageTime };
|
|
442
537
|
}
|
|
@@ -462,6 +557,7 @@ var AgentResponse = React7__namespace.forwardRef(
|
|
|
462
557
|
onThinkingExpandedChange,
|
|
463
558
|
actionsVisible = "hover",
|
|
464
559
|
renderMarkdown,
|
|
560
|
+
renderThinkingMarkdown,
|
|
465
561
|
className,
|
|
466
562
|
...props
|
|
467
563
|
}, ref) => {
|
|
@@ -486,8 +582,9 @@ var AgentResponse = React7__namespace.forwardRef(
|
|
|
486
582
|
if (!state.firstMessageTime || !state.responseCompleteTime) return 0;
|
|
487
583
|
return (state.responseCompleteTime - state.firstMessageTime) / 1e3;
|
|
488
584
|
}, [state.firstMessageTime, state.responseCompleteTime]);
|
|
489
|
-
const
|
|
490
|
-
const
|
|
585
|
+
const hasThinkingContent = !!state.thinking || state.thinkingSteps && state.thinkingSteps.length > 0 || false;
|
|
586
|
+
const hasAnyContent = hasThinkingContent || state.toolCalls.length > 0 || state.knowledge.length > 0 || state.memory.length > 0 || state.statusUpdates.length > 0 || state.response;
|
|
587
|
+
const showMetadataRow = hasThinkingContent || state.toolCalls.length > 0 || state.knowledge.length > 0 || state.memory.length > 0 || state.statusUpdates.length > 0 || state.status === "processing";
|
|
491
588
|
const showActionBar = state.status === "complete" && state.response;
|
|
492
589
|
const isActionBarVisible = actionsVisible === true || actionsVisible === "hover" && isHovered;
|
|
493
590
|
if (!hasAnyContent) {
|
|
@@ -507,12 +604,13 @@ var AgentResponse = React7__namespace.forwardRef(
|
|
|
507
604
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
508
605
|
MetadataRow,
|
|
509
606
|
{
|
|
510
|
-
hasThinking:
|
|
607
|
+
hasThinking: hasThinkingContent,
|
|
511
608
|
isExpanded: thinkingExpanded,
|
|
512
609
|
onToggle: toggleThinking,
|
|
513
610
|
toolCalls: state.toolCalls,
|
|
514
611
|
knowledge: state.knowledge,
|
|
515
612
|
memory: state.memory,
|
|
613
|
+
statusUpdates: state.statusUpdates,
|
|
516
614
|
status: state.status,
|
|
517
615
|
elapsedTime
|
|
518
616
|
}
|
|
@@ -520,8 +618,9 @@ var AgentResponse = React7__namespace.forwardRef(
|
|
|
520
618
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
521
619
|
ThinkingSection,
|
|
522
620
|
{
|
|
523
|
-
content: state.thinking,
|
|
524
|
-
isExpanded: thinkingExpanded
|
|
621
|
+
content: state.thinkingSteps && state.thinkingSteps.length > 0 ? state.thinkingSteps : state.thinking,
|
|
622
|
+
isExpanded: thinkingExpanded,
|
|
623
|
+
renderMarkdown: renderThinkingMarkdown
|
|
525
624
|
}
|
|
526
625
|
)
|
|
527
626
|
] }),
|
|
@@ -661,6 +760,11 @@ var UserPromptInput = React7__namespace.forwardRef(
|
|
|
661
760
|
placeholder = "Type your message...",
|
|
662
761
|
disabled = false,
|
|
663
762
|
isSubmitting = false,
|
|
763
|
+
onStop,
|
|
764
|
+
disableWhileSubmitting = true,
|
|
765
|
+
autoFocus = false,
|
|
766
|
+
refocusAfterSubmit = false,
|
|
767
|
+
onReady,
|
|
664
768
|
minRows = 1,
|
|
665
769
|
maxRows = 6,
|
|
666
770
|
renderActions,
|
|
@@ -672,13 +776,52 @@ var UserPromptInput = React7__namespace.forwardRef(
|
|
|
672
776
|
}, ref) => {
|
|
673
777
|
const editorRef = React7__namespace.useRef(null);
|
|
674
778
|
const [internalValue, setInternalValue] = React7__namespace.useState(value);
|
|
779
|
+
const prevIsSubmitting = React7__namespace.useRef(isSubmitting);
|
|
780
|
+
const hasEmittedReady = React7__namespace.useRef(false);
|
|
675
781
|
React7__namespace.useEffect(() => {
|
|
676
782
|
setInternalValue(value);
|
|
677
783
|
}, [value]);
|
|
784
|
+
React7__namespace.useEffect(() => {
|
|
785
|
+
if (autoFocus) {
|
|
786
|
+
requestAnimationFrame(() => {
|
|
787
|
+
requestAnimationFrame(() => {
|
|
788
|
+
editorRef.current?.focus();
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
}, [autoFocus]);
|
|
793
|
+
React7__namespace.useEffect(() => {
|
|
794
|
+
if (!hasEmittedReady.current && onReady) {
|
|
795
|
+
requestAnimationFrame(() => {
|
|
796
|
+
requestAnimationFrame(() => {
|
|
797
|
+
hasEmittedReady.current = true;
|
|
798
|
+
onReady();
|
|
799
|
+
});
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
}, [onReady]);
|
|
803
|
+
React7__namespace.useEffect(() => {
|
|
804
|
+
if (refocusAfterSubmit && prevIsSubmitting.current && !isSubmitting) {
|
|
805
|
+
requestAnimationFrame(() => {
|
|
806
|
+
editorRef.current?.focus();
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
prevIsSubmitting.current = isSubmitting;
|
|
810
|
+
}, [isSubmitting, refocusAfterSubmit]);
|
|
678
811
|
React7__namespace.useImperativeHandle(
|
|
679
812
|
ref,
|
|
680
813
|
() => ({
|
|
681
|
-
focus: () =>
|
|
814
|
+
focus: () => {
|
|
815
|
+
try {
|
|
816
|
+
editorRef.current?.focus();
|
|
817
|
+
} catch {
|
|
818
|
+
requestAnimationFrame(() => {
|
|
819
|
+
requestAnimationFrame(() => {
|
|
820
|
+
editorRef.current?.focus();
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
},
|
|
682
825
|
clear: () => {
|
|
683
826
|
editorRef.current?.clear();
|
|
684
827
|
setInternalValue("");
|
|
@@ -732,7 +875,7 @@ var UserPromptInput = React7__namespace.forwardRef(
|
|
|
732
875
|
onSubmit: handleSubmit,
|
|
733
876
|
clearOnSubmit: false,
|
|
734
877
|
placeholder,
|
|
735
|
-
disabled: disabled || isSubmitting,
|
|
878
|
+
disabled: disabled || disableWhileSubmitting && isSubmitting,
|
|
736
879
|
enableTags,
|
|
737
880
|
onTagCreate,
|
|
738
881
|
onTagDelete,
|
|
@@ -744,7 +887,16 @@ var UserPromptInput = React7__namespace.forwardRef(
|
|
|
744
887
|
) }),
|
|
745
888
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pl-2 pr-1 pb-1 pt-1", children: [
|
|
746
889
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: renderActions?.() }),
|
|
747
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
890
|
+
isSubmitting && onStop ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
891
|
+
core.IconButton,
|
|
892
|
+
{
|
|
893
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, {}),
|
|
894
|
+
variant: "filled",
|
|
895
|
+
size: "sm",
|
|
896
|
+
"aria-label": "Stop",
|
|
897
|
+
onClick: onStop
|
|
898
|
+
}
|
|
899
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
748
900
|
core.IconButton,
|
|
749
901
|
{
|
|
750
902
|
icon: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, {}),
|