@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/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,37 @@ interface MemoryItem {
|
|
|
40
40
|
content: string;
|
|
41
41
|
timestamp: number;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Status update information from the agent
|
|
45
|
+
*/
|
|
46
|
+
interface StatusItem {
|
|
47
|
+
id: string;
|
|
48
|
+
message: string;
|
|
49
|
+
timestamp: number;
|
|
50
|
+
/** Optional agent name if in multi-agent scenario */
|
|
51
|
+
agent?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A single step in structured thinking content
|
|
55
|
+
*/
|
|
56
|
+
interface ThinkingStep {
|
|
57
|
+
/** Unique identifier for the step */
|
|
58
|
+
id: string;
|
|
59
|
+
/** Label/title shown in the collapsible header */
|
|
60
|
+
label: string;
|
|
61
|
+
/** Content of the thinking step */
|
|
62
|
+
content: string;
|
|
63
|
+
/** Nesting depth (0 = root level, 1 = first indent, etc.) */
|
|
64
|
+
depth: number;
|
|
65
|
+
/** Whether this step should start collapsed (default: false) */
|
|
66
|
+
isCollapsed?: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Union type for thinking content
|
|
70
|
+
* - string: plain text (backward compatible)
|
|
71
|
+
* - ThinkingStep[]: structured with collapsible sub-sections
|
|
72
|
+
*/
|
|
73
|
+
type ThinkingContent = string | ThinkingStep[];
|
|
43
74
|
/**
|
|
44
75
|
* State shape for the agent response component
|
|
45
76
|
*/
|
|
@@ -48,12 +79,16 @@ interface AgentResponseState {
|
|
|
48
79
|
status: AgentResponseStatus;
|
|
49
80
|
/** Accumulated thinking/reasoning text */
|
|
50
81
|
thinking: string;
|
|
82
|
+
/** Structured thinking steps (if provided, takes precedence over thinking string) */
|
|
83
|
+
thinkingSteps?: ThinkingStep[];
|
|
51
84
|
/** Tool calls made during processing */
|
|
52
85
|
toolCalls: ToolCall[];
|
|
53
86
|
/** Knowledge items retrieved */
|
|
54
87
|
knowledge: KnowledgeItem[];
|
|
55
88
|
/** Memory items accessed */
|
|
56
89
|
memory: MemoryItem[];
|
|
90
|
+
/** Status updates from the agent */
|
|
91
|
+
statusUpdates: StatusItem[];
|
|
57
92
|
/** Final response text */
|
|
58
93
|
response: string;
|
|
59
94
|
/** Timestamp when first thinking message was received (for timer) */
|
|
@@ -67,7 +102,7 @@ interface AgentResponseState {
|
|
|
67
102
|
* WebSocket message payload for agent responses
|
|
68
103
|
*/
|
|
69
104
|
interface AgentMessage {
|
|
70
|
-
type: "status" | "thinking" | "tool_call" | "knowledge" | "memory" | "response";
|
|
105
|
+
type: "status" | "thinking" | "tool_call" | "knowledge" | "memory" | "response" | "status_update";
|
|
71
106
|
/** Message content - for simple string payloads */
|
|
72
107
|
message?: string;
|
|
73
108
|
/** Alternative content field */
|
|
@@ -92,6 +127,20 @@ interface AgentMessage {
|
|
|
92
127
|
type: string;
|
|
93
128
|
content: string;
|
|
94
129
|
};
|
|
130
|
+
/** For status_update messages */
|
|
131
|
+
statusUpdate?: {
|
|
132
|
+
id: string;
|
|
133
|
+
message: string;
|
|
134
|
+
agent?: string;
|
|
135
|
+
};
|
|
136
|
+
/** For structured thinking step messages */
|
|
137
|
+
thinkingStep?: {
|
|
138
|
+
id?: string;
|
|
139
|
+
label: string;
|
|
140
|
+
content: string;
|
|
141
|
+
depth?: number;
|
|
142
|
+
isCollapsed?: boolean;
|
|
143
|
+
};
|
|
95
144
|
}
|
|
96
145
|
/**
|
|
97
146
|
* Generic websocket message wrapper type
|
|
@@ -142,6 +191,17 @@ interface AgentResponseProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
142
191
|
* />
|
|
143
192
|
*/
|
|
144
193
|
renderMarkdown?: (content: string) => React.ReactNode;
|
|
194
|
+
/**
|
|
195
|
+
* Custom markdown renderer for the thinking content.
|
|
196
|
+
* If not provided, the thinking will be rendered as plain preformatted text.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* <AgentResponse
|
|
200
|
+
* state={state}
|
|
201
|
+
* renderThinkingMarkdown={(content) => <MyMarkdownRenderer content={content} />}
|
|
202
|
+
* />
|
|
203
|
+
*/
|
|
204
|
+
renderThinkingMarkdown?: (content: string) => React.ReactNode;
|
|
145
205
|
}
|
|
146
206
|
/**
|
|
147
207
|
* AgentResponse Component
|
|
@@ -190,6 +250,8 @@ interface ActivityIndicatorsProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
190
250
|
knowledge: KnowledgeItem[];
|
|
191
251
|
/** Memory items to display */
|
|
192
252
|
memory: MemoryItem[];
|
|
253
|
+
/** Status updates to display */
|
|
254
|
+
statusUpdates?: StatusItem[];
|
|
193
255
|
}
|
|
194
256
|
/**
|
|
195
257
|
* ActivityIndicators Component
|
|
@@ -225,6 +287,8 @@ interface MetadataRowProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
225
287
|
knowledge: KnowledgeItem[];
|
|
226
288
|
/** Memory items to display */
|
|
227
289
|
memory: MemoryItem[];
|
|
290
|
+
/** Status updates to display */
|
|
291
|
+
statusUpdates?: StatusItem[];
|
|
228
292
|
/** Current response status */
|
|
229
293
|
status: AgentResponseStatus;
|
|
230
294
|
/** Elapsed time in seconds */
|
|
@@ -253,22 +317,40 @@ declare const MetadataRow: React.ForwardRefExoticComponent<MetadataRowProps & Re
|
|
|
253
317
|
/**
|
|
254
318
|
* Thinking Section Component
|
|
255
319
|
*
|
|
256
|
-
* Collapsible section for displaying agent thinking/reasoning content
|
|
320
|
+
* Collapsible section for displaying agent thinking/reasoning content.
|
|
321
|
+
* Supports both plain text and structured collapsible sub-sections.
|
|
257
322
|
*/
|
|
258
323
|
|
|
259
|
-
interface ThinkingSectionProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
260
|
-
/** The thinking content to display */
|
|
261
|
-
content: string;
|
|
324
|
+
interface ThinkingSectionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "content"> {
|
|
325
|
+
/** The thinking content to display (string or structured steps) */
|
|
326
|
+
content: string | ThinkingStep[];
|
|
262
327
|
/** Whether the section is expanded */
|
|
263
328
|
isExpanded: boolean;
|
|
329
|
+
/**
|
|
330
|
+
* Custom markdown renderer for the thinking content.
|
|
331
|
+
* If not provided, the content will be rendered as plain preformatted text.
|
|
332
|
+
*/
|
|
333
|
+
renderMarkdown?: (content: string) => React.ReactNode;
|
|
264
334
|
}
|
|
265
335
|
/**
|
|
266
336
|
* ThinkingSection Component
|
|
267
337
|
*
|
|
268
338
|
* Displays the agent's thinking/reasoning content in a collapsible panel.
|
|
339
|
+
* Supports both plain text content and structured collapsible sub-sections.
|
|
269
340
|
*
|
|
270
341
|
* @example
|
|
342
|
+
* // Plain text content
|
|
271
343
|
* <ThinkingSection content={state.thinking} isExpanded={isExpanded} />
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* // Structured content with sub-sections
|
|
347
|
+
* <ThinkingSection
|
|
348
|
+
* content={[
|
|
349
|
+
* { id: "1", label: "Analysis", content: "...", depth: 0 },
|
|
350
|
+
* { id: "2", label: "Sub-analysis", content: "...", depth: 1 },
|
|
351
|
+
* ]}
|
|
352
|
+
* isExpanded={isExpanded}
|
|
353
|
+
* />
|
|
272
354
|
*/
|
|
273
355
|
declare const ThinkingSection: React.ForwardRefExoticComponent<ThinkingSectionProps & React.RefAttributes<HTMLDivElement>>;
|
|
274
356
|
|
|
@@ -421,6 +503,16 @@ interface UserPromptInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>
|
|
|
421
503
|
disabled?: boolean;
|
|
422
504
|
/** Whether a submission is in progress (shows loading state) */
|
|
423
505
|
isSubmitting?: boolean;
|
|
506
|
+
/** Called when user clicks Stop during submission */
|
|
507
|
+
onStop?: () => void;
|
|
508
|
+
/** Whether to disable input while submitting (default: true) */
|
|
509
|
+
disableWhileSubmitting?: boolean;
|
|
510
|
+
/** Auto-focus the editor when mounted (handles Slate initialization timing) */
|
|
511
|
+
autoFocus?: boolean;
|
|
512
|
+
/** Refocus the input after submission completes (default: false) */
|
|
513
|
+
refocusAfterSubmit?: boolean;
|
|
514
|
+
/** Called when the editor is fully initialized and ready for interaction */
|
|
515
|
+
onReady?: () => void;
|
|
424
516
|
/** Minimum number of rows for the editor */
|
|
425
517
|
minRows?: number;
|
|
426
518
|
/** Maximum number of rows before scrolling */
|
|
@@ -466,4 +558,4 @@ interface UserPromptInputRef {
|
|
|
466
558
|
*/
|
|
467
559
|
declare const UserPromptInput: React.ForwardRefExoticComponent<UserPromptInputProps & React.RefAttributes<UserPromptInputRef>>;
|
|
468
560
|
|
|
469
|
-
export { ActionBar, type ActionBarProps, ActivityIndicators, type ActivityIndicatorsProps, type AgentMessage, AgentResponse, type AgentResponseProps, type AgentResponseState, type AgentResponseStatus, type FeedbackValue, type GenericWebSocketMessage, type KnowledgeItem, type MemoryItem, MetadataRow, type MetadataRowProps, ThinkingSection, type ThinkingSectionProps, type ToolCall, type UseAgentResponseAccumulatorOptions, type UseAgentResponseAccumulatorReturn, type UseThinkingTimerOptions, UserPrompt, UserPromptInput, type UserPromptInputProps, type UserPromptInputRef, type UserPromptProps, formatTime, formatTotalTime, initialAgentResponseState, useAgentResponseAccumulator, useThinkingTimer };
|
|
561
|
+
export { ActionBar, type ActionBarProps, ActivityIndicators, type ActivityIndicatorsProps, type AgentMessage, AgentResponse, type AgentResponseProps, type AgentResponseState, type AgentResponseStatus, type FeedbackValue, type GenericWebSocketMessage, type KnowledgeItem, type MemoryItem, MetadataRow, type MetadataRowProps, type StatusItem, type ThinkingContent, ThinkingSection, type ThinkingSectionProps, type ThinkingStep, type ToolCall, type UseAgentResponseAccumulatorOptions, type UseAgentResponseAccumulatorReturn, type UseThinkingTimerOptions, UserPrompt, UserPromptInput, type UserPromptInputProps, type UserPromptInputRef, type UserPromptProps, formatTime, formatTotalTime, initialAgentResponseState, useAgentResponseAccumulator, useThinkingTimer };
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,36 @@
|
|
|
1
1
|
import * as React7 from 'react';
|
|
2
2
|
import { useState, useCallback, useMemo, useEffect } from 'react';
|
|
3
3
|
import { cn, Popover, PopoverTrigger, PopoverContent, IconButton, LoadingSpinner } from '@optilogic/core';
|
|
4
|
-
import { Wrench, Book, HardDrive, Check, Copy, ThumbsUp, ThumbsDown, Loader2, Send, ChevronUp, ChevronDown } from 'lucide-react';
|
|
4
|
+
import { Activity, Wrench, Book, HardDrive, Check, Copy, ThumbsUp, ThumbsDown, Square, Loader2, Send, ChevronUp, ChevronDown, ChevronRight } from 'lucide-react';
|
|
5
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { SlateEditor, Text } from '@optilogic/editor';
|
|
7
7
|
|
|
8
8
|
// src/components/agent-response/AgentResponse.tsx
|
|
9
9
|
var ActivityIndicators = React7.forwardRef(
|
|
10
|
-
({ toolCalls, knowledge, memory, className, ...props }, ref) => {
|
|
11
|
-
const hasAnyActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0;
|
|
10
|
+
({ toolCalls, knowledge, memory, statusUpdates = [], className, ...props }, ref) => {
|
|
11
|
+
const hasAnyActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0 || statusUpdates.length > 0;
|
|
12
12
|
if (!hasAnyActivity) return null;
|
|
13
13
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex items-center gap-2", className), ...props, children: [
|
|
14
|
+
statusUpdates.length > 0 && /* @__PURE__ */ jsxs(Popover, { children: [
|
|
15
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
16
|
+
"button",
|
|
17
|
+
{
|
|
18
|
+
className: "flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",
|
|
19
|
+
onClick: (e) => e.stopPropagation(),
|
|
20
|
+
children: [
|
|
21
|
+
/* @__PURE__ */ jsx(Activity, { className: "w-3.5 h-3.5" }),
|
|
22
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: statusUpdates.length })
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
) }),
|
|
26
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "w-80", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
27
|
+
/* @__PURE__ */ jsx("h4", { className: "font-medium text-sm", children: "Status Updates" }),
|
|
28
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-60 overflow-auto", children: statusUpdates.map((item) => /* @__PURE__ */ jsxs("div", { className: "p-2 bg-muted rounded text-xs", children: [
|
|
29
|
+
item.agent && /* @__PURE__ */ jsx("div", { className: "font-medium text-muted-foreground", children: item.agent }),
|
|
30
|
+
/* @__PURE__ */ jsx("div", { className: item.agent ? "mt-1" : "", children: item.message })
|
|
31
|
+
] }, item.id)) })
|
|
32
|
+
] }) })
|
|
33
|
+
] }),
|
|
14
34
|
toolCalls.length > 0 && /* @__PURE__ */ jsxs(Popover, { children: [
|
|
15
35
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
16
36
|
"button",
|
|
@@ -113,6 +133,7 @@ var MetadataRow = React7.forwardRef(
|
|
|
113
133
|
toolCalls,
|
|
114
134
|
knowledge,
|
|
115
135
|
memory,
|
|
136
|
+
statusUpdates = [],
|
|
116
137
|
status,
|
|
117
138
|
elapsedTime,
|
|
118
139
|
className,
|
|
@@ -120,7 +141,7 @@ var MetadataRow = React7.forwardRef(
|
|
|
120
141
|
}, ref) => {
|
|
121
142
|
const isProcessing = status === "processing";
|
|
122
143
|
const isComplete = status === "complete";
|
|
123
|
-
const hasActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0;
|
|
144
|
+
const hasActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0 || statusUpdates.length > 0;
|
|
124
145
|
const renderLeftContent = () => {
|
|
125
146
|
if (hasThinking) {
|
|
126
147
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
@@ -160,7 +181,8 @@ var MetadataRow = React7.forwardRef(
|
|
|
160
181
|
{
|
|
161
182
|
toolCalls,
|
|
162
183
|
knowledge,
|
|
163
|
-
memory
|
|
184
|
+
memory,
|
|
185
|
+
statusUpdates
|
|
164
186
|
}
|
|
165
187
|
)
|
|
166
188
|
]
|
|
@@ -169,18 +191,55 @@ var MetadataRow = React7.forwardRef(
|
|
|
169
191
|
}
|
|
170
192
|
);
|
|
171
193
|
MetadataRow.displayName = "MetadataRow";
|
|
194
|
+
var ThinkingStepItem = ({ step, renderMarkdown }) => {
|
|
195
|
+
const [isCollapsed, setIsCollapsed] = useState(step.isCollapsed ?? false);
|
|
196
|
+
const toggleCollapse = useCallback(() => {
|
|
197
|
+
setIsCollapsed((prev) => !prev);
|
|
198
|
+
}, []);
|
|
199
|
+
const indentPadding = step.depth * 16;
|
|
200
|
+
return /* @__PURE__ */ jsxs("div", { className: "border-b border-border/50 last:border-b-0", children: [
|
|
201
|
+
/* @__PURE__ */ jsxs(
|
|
202
|
+
"button",
|
|
203
|
+
{
|
|
204
|
+
onClick: toggleCollapse,
|
|
205
|
+
className: "w-full flex items-center gap-1.5 py-1.5 px-2 hover:bg-muted/50 transition-colors text-left",
|
|
206
|
+
style: { paddingLeft: `${indentPadding + 8}px` },
|
|
207
|
+
children: [
|
|
208
|
+
isCollapsed ? /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3 text-muted-foreground flex-shrink-0" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "w-3 h-3 text-muted-foreground flex-shrink-0" }),
|
|
209
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-foreground/80", children: step.label })
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
),
|
|
213
|
+
!isCollapsed && /* @__PURE__ */ jsx(
|
|
214
|
+
"div",
|
|
215
|
+
{
|
|
216
|
+
className: "pb-2 px-2",
|
|
217
|
+
style: { paddingLeft: `${indentPadding + 28}px` },
|
|
218
|
+
children: renderMarkdown ? /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: renderMarkdown(step.content) }) : /* @__PURE__ */ jsx("pre", { className: "text-xs text-muted-foreground whitespace-pre-wrap font-mono", children: step.content })
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
] });
|
|
222
|
+
};
|
|
172
223
|
var ThinkingSection = React7.forwardRef(
|
|
173
|
-
({ content, isExpanded, className, ...props }, ref) => {
|
|
174
|
-
if (!isExpanded || !content) {
|
|
224
|
+
({ content, isExpanded, renderMarkdown, className, ...props }, ref) => {
|
|
225
|
+
if (!isExpanded || !content || Array.isArray(content) && content.length === 0) {
|
|
175
226
|
return null;
|
|
176
227
|
}
|
|
228
|
+
const isStructured = Array.isArray(content);
|
|
177
229
|
return /* @__PURE__ */ jsx(
|
|
178
230
|
"div",
|
|
179
231
|
{
|
|
180
232
|
ref,
|
|
181
233
|
className: cn("px-3 pb-3 border-t border-border", className),
|
|
182
234
|
...props,
|
|
183
|
-
children: /* @__PURE__ */ jsx("div", { className: "mt-2 max-h-[200px] overflow-y-auto", children: /* @__PURE__ */ jsx("
|
|
235
|
+
children: /* @__PURE__ */ jsx("div", { className: "mt-2 max-h-[200px] overflow-y-auto", children: isStructured ? /* @__PURE__ */ jsx("div", { className: "space-y-0", children: content.map((step) => /* @__PURE__ */ jsx(
|
|
236
|
+
ThinkingStepItem,
|
|
237
|
+
{
|
|
238
|
+
step,
|
|
239
|
+
renderMarkdown
|
|
240
|
+
},
|
|
241
|
+
step.id
|
|
242
|
+
)) }) : renderMarkdown ? /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: renderMarkdown(content) }) : /* @__PURE__ */ jsx("pre", { className: "text-xs text-muted-foreground whitespace-pre-wrap font-mono", children: content }) })
|
|
184
243
|
}
|
|
185
244
|
);
|
|
186
245
|
}
|
|
@@ -309,6 +368,7 @@ var initialAgentResponseState = {
|
|
|
309
368
|
toolCalls: [],
|
|
310
369
|
knowledge: [],
|
|
311
370
|
memory: [],
|
|
371
|
+
statusUpdates: [],
|
|
312
372
|
response: "",
|
|
313
373
|
thinkingStartTime: null,
|
|
314
374
|
responseCompleteTime: null,
|
|
@@ -343,6 +403,23 @@ function useAgentResponseAccumulator(options) {
|
|
|
343
403
|
}
|
|
344
404
|
return { ...prev, status: newStatus };
|
|
345
405
|
case "thinking": {
|
|
406
|
+
if (payload.thinkingStep) {
|
|
407
|
+
const newStep = {
|
|
408
|
+
id: payload.thinkingStep.id || `step-${Date.now()}`,
|
|
409
|
+
label: payload.thinkingStep.label,
|
|
410
|
+
content: payload.thinkingStep.content,
|
|
411
|
+
depth: payload.thinkingStep.depth ?? 0,
|
|
412
|
+
isCollapsed: payload.thinkingStep.isCollapsed
|
|
413
|
+
};
|
|
414
|
+
const thinkingStartTime2 = prev.thinkingStartTime ?? Date.now();
|
|
415
|
+
return {
|
|
416
|
+
...prev,
|
|
417
|
+
status: newStatus,
|
|
418
|
+
thinkingSteps: [...prev.thinkingSteps || [], newStep],
|
|
419
|
+
thinkingStartTime: thinkingStartTime2,
|
|
420
|
+
firstMessageTime
|
|
421
|
+
};
|
|
422
|
+
}
|
|
346
423
|
const newThinking = payload.message || payload.content || "";
|
|
347
424
|
const separator = prev.thinking && newThinking ? "\n\n" : "";
|
|
348
425
|
const thinkingStartTime = prev.thinkingStartTime ?? (newThinking ? Date.now() : null);
|
|
@@ -416,6 +493,24 @@ function useAgentResponseAccumulator(options) {
|
|
|
416
493
|
responseCompleteTime: Date.now(),
|
|
417
494
|
firstMessageTime: prev.firstMessageTime ?? Date.now()
|
|
418
495
|
};
|
|
496
|
+
case "status_update": {
|
|
497
|
+
const statusMessage = payload.message || payload.statusUpdate?.message;
|
|
498
|
+
if (statusMessage) {
|
|
499
|
+
const newStatusItem = {
|
|
500
|
+
id: payload.statusUpdate?.id || `status-${Date.now()}`,
|
|
501
|
+
message: statusMessage,
|
|
502
|
+
agent: payload.statusUpdate?.agent,
|
|
503
|
+
timestamp: Date.now()
|
|
504
|
+
};
|
|
505
|
+
return {
|
|
506
|
+
...prev,
|
|
507
|
+
status: newStatus,
|
|
508
|
+
statusUpdates: [...prev.statusUpdates, newStatusItem],
|
|
509
|
+
firstMessageTime
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
return { ...prev, status: newStatus, firstMessageTime };
|
|
513
|
+
}
|
|
419
514
|
default:
|
|
420
515
|
return { ...prev, status: newStatus, firstMessageTime };
|
|
421
516
|
}
|
|
@@ -441,6 +536,7 @@ var AgentResponse = React7.forwardRef(
|
|
|
441
536
|
onThinkingExpandedChange,
|
|
442
537
|
actionsVisible = "hover",
|
|
443
538
|
renderMarkdown,
|
|
539
|
+
renderThinkingMarkdown,
|
|
444
540
|
className,
|
|
445
541
|
...props
|
|
446
542
|
}, ref) => {
|
|
@@ -465,8 +561,9 @@ var AgentResponse = React7.forwardRef(
|
|
|
465
561
|
if (!state.firstMessageTime || !state.responseCompleteTime) return 0;
|
|
466
562
|
return (state.responseCompleteTime - state.firstMessageTime) / 1e3;
|
|
467
563
|
}, [state.firstMessageTime, state.responseCompleteTime]);
|
|
468
|
-
const
|
|
469
|
-
const
|
|
564
|
+
const hasThinkingContent = !!state.thinking || state.thinkingSteps && state.thinkingSteps.length > 0 || false;
|
|
565
|
+
const hasAnyContent = hasThinkingContent || state.toolCalls.length > 0 || state.knowledge.length > 0 || state.memory.length > 0 || state.statusUpdates.length > 0 || state.response;
|
|
566
|
+
const showMetadataRow = hasThinkingContent || state.toolCalls.length > 0 || state.knowledge.length > 0 || state.memory.length > 0 || state.statusUpdates.length > 0 || state.status === "processing";
|
|
470
567
|
const showActionBar = state.status === "complete" && state.response;
|
|
471
568
|
const isActionBarVisible = actionsVisible === true || actionsVisible === "hover" && isHovered;
|
|
472
569
|
if (!hasAnyContent) {
|
|
@@ -486,12 +583,13 @@ var AgentResponse = React7.forwardRef(
|
|
|
486
583
|
/* @__PURE__ */ jsx(
|
|
487
584
|
MetadataRow,
|
|
488
585
|
{
|
|
489
|
-
hasThinking:
|
|
586
|
+
hasThinking: hasThinkingContent,
|
|
490
587
|
isExpanded: thinkingExpanded,
|
|
491
588
|
onToggle: toggleThinking,
|
|
492
589
|
toolCalls: state.toolCalls,
|
|
493
590
|
knowledge: state.knowledge,
|
|
494
591
|
memory: state.memory,
|
|
592
|
+
statusUpdates: state.statusUpdates,
|
|
495
593
|
status: state.status,
|
|
496
594
|
elapsedTime
|
|
497
595
|
}
|
|
@@ -499,8 +597,9 @@ var AgentResponse = React7.forwardRef(
|
|
|
499
597
|
/* @__PURE__ */ jsx(
|
|
500
598
|
ThinkingSection,
|
|
501
599
|
{
|
|
502
|
-
content: state.thinking,
|
|
503
|
-
isExpanded: thinkingExpanded
|
|
600
|
+
content: state.thinkingSteps && state.thinkingSteps.length > 0 ? state.thinkingSteps : state.thinking,
|
|
601
|
+
isExpanded: thinkingExpanded,
|
|
602
|
+
renderMarkdown: renderThinkingMarkdown
|
|
504
603
|
}
|
|
505
604
|
)
|
|
506
605
|
] }),
|
|
@@ -640,6 +739,11 @@ var UserPromptInput = React7.forwardRef(
|
|
|
640
739
|
placeholder = "Type your message...",
|
|
641
740
|
disabled = false,
|
|
642
741
|
isSubmitting = false,
|
|
742
|
+
onStop,
|
|
743
|
+
disableWhileSubmitting = true,
|
|
744
|
+
autoFocus = false,
|
|
745
|
+
refocusAfterSubmit = false,
|
|
746
|
+
onReady,
|
|
643
747
|
minRows = 1,
|
|
644
748
|
maxRows = 6,
|
|
645
749
|
renderActions,
|
|
@@ -651,13 +755,52 @@ var UserPromptInput = React7.forwardRef(
|
|
|
651
755
|
}, ref) => {
|
|
652
756
|
const editorRef = React7.useRef(null);
|
|
653
757
|
const [internalValue, setInternalValue] = React7.useState(value);
|
|
758
|
+
const prevIsSubmitting = React7.useRef(isSubmitting);
|
|
759
|
+
const hasEmittedReady = React7.useRef(false);
|
|
654
760
|
React7.useEffect(() => {
|
|
655
761
|
setInternalValue(value);
|
|
656
762
|
}, [value]);
|
|
763
|
+
React7.useEffect(() => {
|
|
764
|
+
if (autoFocus) {
|
|
765
|
+
requestAnimationFrame(() => {
|
|
766
|
+
requestAnimationFrame(() => {
|
|
767
|
+
editorRef.current?.focus();
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
}, [autoFocus]);
|
|
772
|
+
React7.useEffect(() => {
|
|
773
|
+
if (!hasEmittedReady.current && onReady) {
|
|
774
|
+
requestAnimationFrame(() => {
|
|
775
|
+
requestAnimationFrame(() => {
|
|
776
|
+
hasEmittedReady.current = true;
|
|
777
|
+
onReady();
|
|
778
|
+
});
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
}, [onReady]);
|
|
782
|
+
React7.useEffect(() => {
|
|
783
|
+
if (refocusAfterSubmit && prevIsSubmitting.current && !isSubmitting) {
|
|
784
|
+
requestAnimationFrame(() => {
|
|
785
|
+
editorRef.current?.focus();
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
prevIsSubmitting.current = isSubmitting;
|
|
789
|
+
}, [isSubmitting, refocusAfterSubmit]);
|
|
657
790
|
React7.useImperativeHandle(
|
|
658
791
|
ref,
|
|
659
792
|
() => ({
|
|
660
|
-
focus: () =>
|
|
793
|
+
focus: () => {
|
|
794
|
+
try {
|
|
795
|
+
editorRef.current?.focus();
|
|
796
|
+
} catch {
|
|
797
|
+
requestAnimationFrame(() => {
|
|
798
|
+
requestAnimationFrame(() => {
|
|
799
|
+
editorRef.current?.focus();
|
|
800
|
+
});
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
},
|
|
661
804
|
clear: () => {
|
|
662
805
|
editorRef.current?.clear();
|
|
663
806
|
setInternalValue("");
|
|
@@ -711,7 +854,7 @@ var UserPromptInput = React7.forwardRef(
|
|
|
711
854
|
onSubmit: handleSubmit,
|
|
712
855
|
clearOnSubmit: false,
|
|
713
856
|
placeholder,
|
|
714
|
-
disabled: disabled || isSubmitting,
|
|
857
|
+
disabled: disabled || disableWhileSubmitting && isSubmitting,
|
|
715
858
|
enableTags,
|
|
716
859
|
onTagCreate,
|
|
717
860
|
onTagDelete,
|
|
@@ -723,7 +866,16 @@ var UserPromptInput = React7.forwardRef(
|
|
|
723
866
|
) }),
|
|
724
867
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pl-2 pr-1 pb-1 pt-1", children: [
|
|
725
868
|
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: renderActions?.() }),
|
|
726
|
-
/* @__PURE__ */ jsx(
|
|
869
|
+
isSubmitting && onStop ? /* @__PURE__ */ jsx(
|
|
870
|
+
IconButton,
|
|
871
|
+
{
|
|
872
|
+
icon: /* @__PURE__ */ jsx(Square, {}),
|
|
873
|
+
variant: "filled",
|
|
874
|
+
size: "sm",
|
|
875
|
+
"aria-label": "Stop",
|
|
876
|
+
onClick: onStop
|
|
877
|
+
}
|
|
878
|
+
) : /* @__PURE__ */ jsx(
|
|
727
879
|
IconButton,
|
|
728
880
|
{
|
|
729
881
|
icon: isSubmitting ? /* @__PURE__ */ jsx(Loader2, { className: "animate-spin" }) : /* @__PURE__ */ jsx(Send, {}),
|