@optilogic/chat 1.0.0-beta.1 → 1.0.0-beta.11
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 +235 -0
- package/dist/index.cjs +1292 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +524 -6
- package/dist/index.d.ts +524 -6
- package/dist/index.js +1267 -33
- package/dist/index.js.map +1 -1
- package/package.json +15 -9
- package/src/components/agent-response/AgentResponse.tsx +99 -10
- package/src/components/agent-response/components/ActivityIndicators.tsx +36 -4
- package/src/components/agent-response/components/HITLSection.tsx +95 -0
- package/src/components/agent-response/components/MetadataRow.tsx +21 -6
- package/src/components/agent-response/components/ThinkingSection.tsx +102 -10
- package/src/components/agent-response/components/TruncatedMessage.tsx +52 -0
- package/src/components/agent-response/components/index.ts +6 -0
- package/src/components/agent-response/hooks/useAgentResponseAccumulator.ts +79 -4
- package/src/components/agent-response/index.ts +23 -0
- package/src/components/agent-response/types.ts +96 -1
- package/src/components/agent-timeline/AgentTimeline.tsx +256 -0
- package/src/components/agent-timeline/TimelineAgentBlock.tsx +84 -0
- package/src/components/agent-timeline/TimelineItem.tsx +97 -0
- package/src/components/agent-timeline/index.ts +14 -0
- package/src/components/agent-timeline/types.ts +49 -0
- package/src/components/agent-timeline/utils.ts +167 -0
- package/src/components/hitl-interactions/HITLInteractionRecord.tsx +139 -0
- package/src/components/hitl-interactions/HITLQuestionPanel.tsx +270 -0
- package/src/components/hitl-interactions/index.ts +18 -0
- package/src/components/inline-actions/ActionMarkdownRenderer.tsx +60 -0
- package/src/components/inline-actions/index.ts +18 -0
- package/src/components/inline-actions/parseResponseSegments.ts +66 -0
- package/src/components/inline-actions/prompts.ts +41 -0
- package/src/components/inline-actions/types.ts +57 -0
- package/src/components/user-prompt/UserPrompt.tsx +60 -0
- package/src/components/user-prompt/index.ts +1 -0
- package/src/components/user-prompt-input/UserPromptInput.tsx +326 -0
- package/src/components/user-prompt-input/index.ts +2 -0
- package/src/components/user-prompt-input/types.ts +52 -0
- package/src/index.ts +54 -0
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React11 = require('react');
|
|
4
4
|
var core = require('@optilogic/core');
|
|
5
5
|
var lucideReact = require('lucide-react');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var editor = require('@optilogic/editor');
|
|
7
8
|
|
|
8
9
|
function _interopNamespace(e) {
|
|
9
10
|
if (e && e.__esModule) return e;
|
|
@@ -23,14 +24,34 @@ function _interopNamespace(e) {
|
|
|
23
24
|
return Object.freeze(n);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
var
|
|
27
|
+
var React11__namespace = /*#__PURE__*/_interopNamespace(React11);
|
|
27
28
|
|
|
28
29
|
// src/components/agent-response/AgentResponse.tsx
|
|
29
|
-
var ActivityIndicators =
|
|
30
|
-
({ toolCalls, knowledge, memory, className, ...props }, ref) => {
|
|
31
|
-
const hasAnyActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0;
|
|
30
|
+
var ActivityIndicators = React11__namespace.forwardRef(
|
|
31
|
+
({ toolCalls, knowledge, memory, statusUpdates = [], className, ...props }, ref) => {
|
|
32
|
+
const hasAnyActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0 || statusUpdates.length > 0;
|
|
32
33
|
if (!hasAnyActivity) return null;
|
|
33
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
|
+
] }),
|
|
34
55
|
toolCalls.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(core.Popover, { children: [
|
|
35
56
|
/* @__PURE__ */ jsxRuntime.jsx(core.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36
57
|
"button",
|
|
@@ -125,7 +146,7 @@ function formatTotalTime(seconds) {
|
|
|
125
146
|
const minutes = seconds / 60;
|
|
126
147
|
return `${minutes.toFixed(1)}m`;
|
|
127
148
|
}
|
|
128
|
-
var MetadataRow =
|
|
149
|
+
var MetadataRow = React11__namespace.forwardRef(
|
|
129
150
|
({
|
|
130
151
|
hasThinking,
|
|
131
152
|
isExpanded,
|
|
@@ -133,6 +154,8 @@ var MetadataRow = React__namespace.forwardRef(
|
|
|
133
154
|
toolCalls,
|
|
134
155
|
knowledge,
|
|
135
156
|
memory,
|
|
157
|
+
statusUpdates = [],
|
|
158
|
+
statusContent,
|
|
136
159
|
status,
|
|
137
160
|
elapsedTime,
|
|
138
161
|
className,
|
|
@@ -140,7 +163,7 @@ var MetadataRow = React__namespace.forwardRef(
|
|
|
140
163
|
}, ref) => {
|
|
141
164
|
const isProcessing = status === "processing";
|
|
142
165
|
const isComplete = status === "complete";
|
|
143
|
-
const hasActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0;
|
|
166
|
+
const hasActivity = toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0 || statusUpdates.length > 0;
|
|
144
167
|
const renderLeftContent = () => {
|
|
145
168
|
if (hasThinking) {
|
|
146
169
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
@@ -157,7 +180,7 @@ var MetadataRow = React__namespace.forwardRef(
|
|
|
157
180
|
return null;
|
|
158
181
|
};
|
|
159
182
|
const leftContent = renderLeftContent();
|
|
160
|
-
if (!leftContent && !hasActivity) {
|
|
183
|
+
if (!leftContent && !hasActivity && !statusContent) {
|
|
161
184
|
return null;
|
|
162
185
|
}
|
|
163
186
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -171,16 +194,18 @@ var MetadataRow = React__namespace.forwardRef(
|
|
|
171
194
|
"button",
|
|
172
195
|
{
|
|
173
196
|
onClick: onToggle,
|
|
174
|
-
className: "flex items-center gap-1.5 hover:bg-muted/50 -ml-1.5 pl-1.5 pr-2 py-0.5 rounded transition-colors",
|
|
197
|
+
className: "flex items-center gap-1.5 hover:bg-muted/50 -ml-1.5 pl-1.5 pr-2 py-0.5 rounded transition-colors shrink-0",
|
|
175
198
|
children: leftContent
|
|
176
199
|
}
|
|
177
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5", children: leftContent }),
|
|
200
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 shrink-0", children: leftContent }),
|
|
201
|
+
statusContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0 mx-2", children: statusContent }),
|
|
178
202
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
179
203
|
ActivityIndicators,
|
|
180
204
|
{
|
|
181
205
|
toolCalls,
|
|
182
206
|
knowledge,
|
|
183
|
-
memory
|
|
207
|
+
memory,
|
|
208
|
+
statusUpdates
|
|
184
209
|
}
|
|
185
210
|
)
|
|
186
211
|
]
|
|
@@ -189,24 +214,61 @@ var MetadataRow = React__namespace.forwardRef(
|
|
|
189
214
|
}
|
|
190
215
|
);
|
|
191
216
|
MetadataRow.displayName = "MetadataRow";
|
|
192
|
-
var
|
|
193
|
-
|
|
194
|
-
|
|
217
|
+
var ThinkingStepItem = ({ step, renderMarkdown }) => {
|
|
218
|
+
const [isCollapsed, setIsCollapsed] = React11.useState(step.isCollapsed ?? false);
|
|
219
|
+
const toggleCollapse = React11.useCallback(() => {
|
|
220
|
+
setIsCollapsed((prev) => !prev);
|
|
221
|
+
}, []);
|
|
222
|
+
const indentPadding = step.depth * 16;
|
|
223
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border/50 last:border-b-0", children: [
|
|
224
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
225
|
+
"button",
|
|
226
|
+
{
|
|
227
|
+
onClick: toggleCollapse,
|
|
228
|
+
className: "w-full flex items-center gap-1.5 py-1.5 px-2 hover:bg-muted/50 transition-colors text-left",
|
|
229
|
+
style: { paddingLeft: `${indentPadding + 8}px` },
|
|
230
|
+
children: [
|
|
231
|
+
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" }),
|
|
232
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-foreground/80", children: step.label })
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
),
|
|
236
|
+
!isCollapsed && /* @__PURE__ */ jsxRuntime.jsx(
|
|
237
|
+
"div",
|
|
238
|
+
{
|
|
239
|
+
className: "pb-2 px-2",
|
|
240
|
+
style: { paddingLeft: `${indentPadding + 28}px` },
|
|
241
|
+
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 })
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
] });
|
|
245
|
+
};
|
|
246
|
+
var ThinkingSection = React11__namespace.forwardRef(
|
|
247
|
+
({ content, isExpanded, renderMarkdown, className, ...props }, ref) => {
|
|
248
|
+
if (!isExpanded || !content || Array.isArray(content) && content.length === 0) {
|
|
195
249
|
return null;
|
|
196
250
|
}
|
|
251
|
+
const isStructured = Array.isArray(content);
|
|
197
252
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
198
253
|
"div",
|
|
199
254
|
{
|
|
200
255
|
ref,
|
|
201
256
|
className: core.cn("px-3 pb-3 border-t border-border", className),
|
|
202
257
|
...props,
|
|
203
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 max-h-[200px] overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx("
|
|
258
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 max-h-[200px] overflow-y-auto scrollbar-thin", children: isStructured ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0", children: content.map((step) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
259
|
+
ThinkingStepItem,
|
|
260
|
+
{
|
|
261
|
+
step,
|
|
262
|
+
renderMarkdown
|
|
263
|
+
},
|
|
264
|
+
step.id
|
|
265
|
+
)) }) : 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 }) })
|
|
204
266
|
}
|
|
205
267
|
);
|
|
206
268
|
}
|
|
207
269
|
);
|
|
208
270
|
ThinkingSection.displayName = "ThinkingSection";
|
|
209
|
-
var ActionBar =
|
|
271
|
+
var ActionBar = React11__namespace.forwardRef(
|
|
210
272
|
({
|
|
211
273
|
response,
|
|
212
274
|
isVisible,
|
|
@@ -217,8 +279,8 @@ var ActionBar = React__namespace.forwardRef(
|
|
|
217
279
|
className,
|
|
218
280
|
...props
|
|
219
281
|
}, ref) => {
|
|
220
|
-
const [copied, setCopied] =
|
|
221
|
-
const handleCopy =
|
|
282
|
+
const [copied, setCopied] = React11.useState(false);
|
|
283
|
+
const handleCopy = React11.useCallback(async () => {
|
|
222
284
|
try {
|
|
223
285
|
await navigator.clipboard.writeText(response);
|
|
224
286
|
setCopied(true);
|
|
@@ -228,11 +290,11 @@ var ActionBar = React__namespace.forwardRef(
|
|
|
228
290
|
console.error("Failed to copy response:", err);
|
|
229
291
|
}
|
|
230
292
|
}, [response, onResponseCopy]);
|
|
231
|
-
const handleThumbsUp =
|
|
293
|
+
const handleThumbsUp = React11.useCallback(() => {
|
|
232
294
|
const newValue = feedback === "up" ? null : "up";
|
|
233
295
|
onFeedbackChange?.(newValue);
|
|
234
296
|
}, [feedback, onFeedbackChange]);
|
|
235
|
-
const handleThumbsDown =
|
|
297
|
+
const handleThumbsDown = React11.useCallback(() => {
|
|
236
298
|
const newValue = feedback === "down" ? null : "down";
|
|
237
299
|
onFeedbackChange?.(newValue);
|
|
238
300
|
}, [feedback, onFeedbackChange]);
|
|
@@ -295,13 +357,320 @@ var ActionBar = React__namespace.forwardRef(
|
|
|
295
357
|
}
|
|
296
358
|
);
|
|
297
359
|
ActionBar.displayName = "ActionBar";
|
|
360
|
+
function buildResponseString(questions, selectedOptions, freeformText) {
|
|
361
|
+
const parts = [];
|
|
362
|
+
for (const q of questions) {
|
|
363
|
+
const answer = selectedOptions[q];
|
|
364
|
+
if (answer) {
|
|
365
|
+
parts.push(`Q: ${q}
|
|
366
|
+
A: ${answer}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
const trimmed = freeformText.trim();
|
|
370
|
+
if (trimmed) {
|
|
371
|
+
parts.push(`Additional context: ${trimmed}`);
|
|
372
|
+
}
|
|
373
|
+
return parts.join("\n\n");
|
|
374
|
+
}
|
|
375
|
+
var HITLQuestionPanel = React11__namespace.forwardRef(({ question, onSubmit, onStop, className, ...props }, ref) => {
|
|
376
|
+
const [freeformText, setFreeformText] = React11.useState("");
|
|
377
|
+
const [selectedOptions, setSelectedOptions] = React11.useState({});
|
|
378
|
+
const hasTimeout = question.timeoutSeconds != null;
|
|
379
|
+
const [secondsLeft, setSecondsLeft] = React11.useState(
|
|
380
|
+
() => hasTimeout ? Math.max(
|
|
381
|
+
0,
|
|
382
|
+
Math.round(
|
|
383
|
+
question.timeoutSeconds - (Date.now() - question.receivedAt) / 1e3
|
|
384
|
+
)
|
|
385
|
+
) : Infinity
|
|
386
|
+
);
|
|
387
|
+
const textareaRef = React11.useRef(null);
|
|
388
|
+
React11.useEffect(() => {
|
|
389
|
+
textareaRef.current?.focus();
|
|
390
|
+
}, []);
|
|
391
|
+
React11.useEffect(() => {
|
|
392
|
+
if (!hasTimeout) return;
|
|
393
|
+
const interval = setInterval(() => {
|
|
394
|
+
const remaining = Math.max(
|
|
395
|
+
0,
|
|
396
|
+
Math.round(
|
|
397
|
+
question.timeoutSeconds - (Date.now() - question.receivedAt) / 1e3
|
|
398
|
+
)
|
|
399
|
+
);
|
|
400
|
+
setSecondsLeft(remaining);
|
|
401
|
+
if (remaining <= 0) clearInterval(interval);
|
|
402
|
+
}, 1e3);
|
|
403
|
+
return () => clearInterval(interval);
|
|
404
|
+
}, [hasTimeout, question.timeoutSeconds, question.receivedAt]);
|
|
405
|
+
const timedOut = hasTimeout && secondsLeft <= 0;
|
|
406
|
+
const questionsWithOptions = React11.useMemo(
|
|
407
|
+
() => question.questions.filter((q) => question.options?.[q]?.length),
|
|
408
|
+
[question.questions, question.options]
|
|
409
|
+
);
|
|
410
|
+
const allOptionsSelected = questionsWithOptions.length > 0 && questionsWithOptions.every((q) => selectedOptions[q]);
|
|
411
|
+
const hasFreeformText = freeformText.trim().length > 0;
|
|
412
|
+
const canSubmit = !timedOut && (allOptionsSelected || hasFreeformText);
|
|
413
|
+
const handleOptionClick = React11.useCallback(
|
|
414
|
+
(questionText, option) => {
|
|
415
|
+
if (timedOut) return;
|
|
416
|
+
setSelectedOptions((prev) => {
|
|
417
|
+
if (prev[questionText] === option) {
|
|
418
|
+
const next = { ...prev };
|
|
419
|
+
delete next[questionText];
|
|
420
|
+
return next;
|
|
421
|
+
}
|
|
422
|
+
return { ...prev, [questionText]: option };
|
|
423
|
+
});
|
|
424
|
+
},
|
|
425
|
+
[timedOut]
|
|
426
|
+
);
|
|
427
|
+
const handleSubmit = React11.useCallback(() => {
|
|
428
|
+
if (!canSubmit) return;
|
|
429
|
+
const combined = buildResponseString(
|
|
430
|
+
question.questions,
|
|
431
|
+
selectedOptions,
|
|
432
|
+
freeformText
|
|
433
|
+
);
|
|
434
|
+
onSubmit(combined, { selectedOptions, freeformText });
|
|
435
|
+
}, [canSubmit, question.questions, selectedOptions, freeformText, onSubmit]);
|
|
436
|
+
const handleKeyDown = React11.useCallback(
|
|
437
|
+
(e) => {
|
|
438
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
439
|
+
e.preventDefault();
|
|
440
|
+
handleSubmit();
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
[handleSubmit]
|
|
444
|
+
);
|
|
445
|
+
const formatTime2 = (s) => {
|
|
446
|
+
const m = Math.floor(s / 60);
|
|
447
|
+
const sec = s % 60;
|
|
448
|
+
return `${m}:${sec.toString().padStart(2, "0")}`;
|
|
449
|
+
};
|
|
450
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
451
|
+
"div",
|
|
452
|
+
{
|
|
453
|
+
ref,
|
|
454
|
+
className: core.cn(
|
|
455
|
+
"rounded-lg border border-border bg-muted p-4 space-y-3",
|
|
456
|
+
className
|
|
457
|
+
),
|
|
458
|
+
...props,
|
|
459
|
+
children: [
|
|
460
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
461
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: question.reason }) }),
|
|
462
|
+
hasTimeout && /* @__PURE__ */ jsxRuntime.jsx(
|
|
463
|
+
"span",
|
|
464
|
+
{
|
|
465
|
+
className: core.cn(
|
|
466
|
+
"text-xs font-mono whitespace-nowrap",
|
|
467
|
+
secondsLeft <= 30 ? "text-destructive" : "text-muted-foreground"
|
|
468
|
+
),
|
|
469
|
+
children: timedOut ? "Timed out" : formatTime2(secondsLeft)
|
|
470
|
+
}
|
|
471
|
+
)
|
|
472
|
+
] }),
|
|
473
|
+
question.context && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground bg-background rounded p-2 border border-border max-h-24 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap font-mono", children: question.context }) }),
|
|
474
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: question.questions.map((q, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
475
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: q }),
|
|
476
|
+
question.options?.[q] && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 mt-1.5", children: question.options[q].map((option, j) => {
|
|
477
|
+
const isSelected = selectedOptions[q] === option;
|
|
478
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
479
|
+
core.Button,
|
|
480
|
+
{
|
|
481
|
+
variant: isSelected ? "primary" : "outline",
|
|
482
|
+
size: "sm",
|
|
483
|
+
onClick: () => handleOptionClick(q, option),
|
|
484
|
+
disabled: timedOut,
|
|
485
|
+
children: option
|
|
486
|
+
},
|
|
487
|
+
j
|
|
488
|
+
);
|
|
489
|
+
}) })
|
|
490
|
+
] }, i)) }),
|
|
491
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
492
|
+
core.Textarea,
|
|
493
|
+
{
|
|
494
|
+
ref: textareaRef,
|
|
495
|
+
value: freeformText,
|
|
496
|
+
onChange: (e) => setFreeformText(e.target.value),
|
|
497
|
+
onKeyDown: handleKeyDown,
|
|
498
|
+
disabled: timedOut,
|
|
499
|
+
placeholder: "Add additional context or type a full response...",
|
|
500
|
+
rows: 2,
|
|
501
|
+
className: "resize-none"
|
|
502
|
+
}
|
|
503
|
+
),
|
|
504
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
505
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
506
|
+
core.Button,
|
|
507
|
+
{
|
|
508
|
+
variant: "ghost",
|
|
509
|
+
size: "sm",
|
|
510
|
+
onClick: onStop,
|
|
511
|
+
className: "text-destructive hover:text-destructive hover:bg-destructive/10",
|
|
512
|
+
children: "Stop agent"
|
|
513
|
+
}
|
|
514
|
+
),
|
|
515
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
516
|
+
core.Button,
|
|
517
|
+
{
|
|
518
|
+
variant: "primary",
|
|
519
|
+
size: "sm",
|
|
520
|
+
onClick: handleSubmit,
|
|
521
|
+
disabled: !canSubmit,
|
|
522
|
+
children: "Send response"
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
] })
|
|
526
|
+
]
|
|
527
|
+
}
|
|
528
|
+
);
|
|
529
|
+
});
|
|
530
|
+
HITLQuestionPanel.displayName = "HITLQuestionPanel";
|
|
531
|
+
function parseResponse(response) {
|
|
532
|
+
const answers = {};
|
|
533
|
+
let additionalContext = null;
|
|
534
|
+
const blocks = response.split("\n\n");
|
|
535
|
+
for (const block of blocks) {
|
|
536
|
+
const qaMatch = block.match(/^Q: (.+)\nA: (.+)$/s);
|
|
537
|
+
if (qaMatch) {
|
|
538
|
+
answers[qaMatch[1].trim()] = qaMatch[2].trim();
|
|
539
|
+
} else if (block.startsWith("Additional context: ")) {
|
|
540
|
+
additionalContext = block.slice("Additional context: ".length).trim();
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return { answers, additionalContext };
|
|
544
|
+
}
|
|
545
|
+
var HITLInteractionRecord = React11__namespace.forwardRef(({ interaction, className, ...props }, ref) => {
|
|
546
|
+
const { question, response, respondedAt } = interaction;
|
|
547
|
+
const timestamp = new Date(respondedAt).toLocaleTimeString([], {
|
|
548
|
+
hour: "2-digit",
|
|
549
|
+
minute: "2-digit"
|
|
550
|
+
});
|
|
551
|
+
const { answers, additionalContext } = React11.useMemo(
|
|
552
|
+
() => parseResponse(response),
|
|
553
|
+
[response]
|
|
554
|
+
);
|
|
555
|
+
const hasParsedAnswers = Object.keys(answers).length > 0;
|
|
556
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
557
|
+
"div",
|
|
558
|
+
{
|
|
559
|
+
ref,
|
|
560
|
+
className: core.cn(
|
|
561
|
+
"rounded-lg border border-border bg-muted p-3 space-y-2 text-sm",
|
|
562
|
+
className
|
|
563
|
+
),
|
|
564
|
+
...props,
|
|
565
|
+
children: [
|
|
566
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
567
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-muted-foreground", children: "Clarifying Question" }),
|
|
568
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: timestamp })
|
|
569
|
+
] }),
|
|
570
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground font-medium", children: question.reason }),
|
|
571
|
+
question.context && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground bg-background rounded p-2 border border-border", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap font-mono", children: question.context }) }),
|
|
572
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: question.questions.map((q, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
573
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground", children: q }),
|
|
574
|
+
question.options?.[q] && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground ml-2", children: [
|
|
575
|
+
"Options: ",
|
|
576
|
+
question.options[q].join(", ")
|
|
577
|
+
] }),
|
|
578
|
+
hasParsedAnswers && answers[q] && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-foreground ml-2 mt-0.5 bg-background rounded px-2 py-1 border border-border", children: [
|
|
579
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Answer: " }),
|
|
580
|
+
answers[q]
|
|
581
|
+
] })
|
|
582
|
+
] }, i)) }),
|
|
583
|
+
hasParsedAnswers && additionalContext && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border pt-2", children: [
|
|
584
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: "Additional context:" }),
|
|
585
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground mt-0.5", children: additionalContext })
|
|
586
|
+
] }),
|
|
587
|
+
!hasParsedAnswers && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border pt-2", children: [
|
|
588
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: "Response:" }),
|
|
589
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground mt-0.5", children: response })
|
|
590
|
+
] })
|
|
591
|
+
]
|
|
592
|
+
}
|
|
593
|
+
);
|
|
594
|
+
});
|
|
595
|
+
HITLInteractionRecord.displayName = "HITLInteractionRecord";
|
|
596
|
+
var HITLSection = React11__namespace.forwardRef(
|
|
597
|
+
({
|
|
598
|
+
interactions,
|
|
599
|
+
defaultExpanded = false,
|
|
600
|
+
isExpanded: controlledExpanded,
|
|
601
|
+
onExpandedChange,
|
|
602
|
+
className,
|
|
603
|
+
...props
|
|
604
|
+
}, ref) => {
|
|
605
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = React11.useState(defaultExpanded);
|
|
606
|
+
const isControlled = controlledExpanded !== void 0;
|
|
607
|
+
const isExpanded = isControlled ? controlledExpanded : uncontrolledExpanded;
|
|
608
|
+
const toggleExpanded = React11.useCallback(() => {
|
|
609
|
+
const newValue = !isExpanded;
|
|
610
|
+
if (isControlled) {
|
|
611
|
+
onExpandedChange?.(newValue);
|
|
612
|
+
} else {
|
|
613
|
+
setUncontrolledExpanded(newValue);
|
|
614
|
+
}
|
|
615
|
+
}, [isExpanded, isControlled, onExpandedChange]);
|
|
616
|
+
if (!interactions || interactions.length === 0) {
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
620
|
+
"div",
|
|
621
|
+
{
|
|
622
|
+
ref,
|
|
623
|
+
className: core.cn("border-t border-border", className),
|
|
624
|
+
...props,
|
|
625
|
+
children: [
|
|
626
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
627
|
+
"button",
|
|
628
|
+
{
|
|
629
|
+
onClick: toggleExpanded,
|
|
630
|
+
className: "w-full flex items-center gap-2 py-2 px-3 hover:bg-muted/50 transition-colors text-left",
|
|
631
|
+
children: [
|
|
632
|
+
isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0" }),
|
|
633
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageCircleQuestion, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0" }),
|
|
634
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground/80", children: [
|
|
635
|
+
"Clarifying Questions (",
|
|
636
|
+
interactions.length,
|
|
637
|
+
")"
|
|
638
|
+
] })
|
|
639
|
+
]
|
|
640
|
+
}
|
|
641
|
+
),
|
|
642
|
+
isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-3 space-y-2", children: interactions.map((interaction, i) => /* @__PURE__ */ jsxRuntime.jsx(HITLInteractionRecord, { interaction }, i)) })
|
|
643
|
+
]
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
HITLSection.displayName = "HITLSection";
|
|
649
|
+
var TruncatedMessage = React11__namespace.forwardRef(
|
|
650
|
+
({ message, className, ...props }, ref) => {
|
|
651
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
652
|
+
"div",
|
|
653
|
+
{
|
|
654
|
+
ref,
|
|
655
|
+
className: core.cn(
|
|
656
|
+
"text-xs text-muted-foreground truncate min-w-0",
|
|
657
|
+
className
|
|
658
|
+
),
|
|
659
|
+
title: message,
|
|
660
|
+
...props,
|
|
661
|
+
children: message
|
|
662
|
+
}
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
);
|
|
666
|
+
TruncatedMessage.displayName = "TruncatedMessage";
|
|
298
667
|
function useThinkingTimer({
|
|
299
668
|
startTime,
|
|
300
669
|
endTime,
|
|
301
670
|
status
|
|
302
671
|
}) {
|
|
303
|
-
const [elapsed, setElapsed] =
|
|
304
|
-
|
|
672
|
+
const [elapsed, setElapsed] = React11.useState(0);
|
|
673
|
+
React11.useEffect(() => {
|
|
305
674
|
if (!startTime) {
|
|
306
675
|
setElapsed(0);
|
|
307
676
|
return;
|
|
@@ -329,17 +698,138 @@ var initialAgentResponseState = {
|
|
|
329
698
|
toolCalls: [],
|
|
330
699
|
knowledge: [],
|
|
331
700
|
memory: [],
|
|
701
|
+
statusUpdates: [],
|
|
332
702
|
response: "",
|
|
333
703
|
thinkingStartTime: null,
|
|
334
704
|
responseCompleteTime: null,
|
|
335
705
|
firstMessageTime: null
|
|
336
706
|
};
|
|
337
707
|
|
|
708
|
+
// src/components/agent-timeline/utils.ts
|
|
709
|
+
function buildTimelineEntries(state) {
|
|
710
|
+
const entries = [];
|
|
711
|
+
if (state.thinkingSteps) {
|
|
712
|
+
let idx = 0;
|
|
713
|
+
for (const step of state.thinkingSteps) {
|
|
714
|
+
entries.push({
|
|
715
|
+
id: `tl-think-${idx++}`,
|
|
716
|
+
type: "thinking",
|
|
717
|
+
agentName: step.agentName ?? null,
|
|
718
|
+
parentAgent: step.parentAgent ?? null,
|
|
719
|
+
depth: step.depth ?? 0,
|
|
720
|
+
content: step.content,
|
|
721
|
+
title: step.label,
|
|
722
|
+
timestamp: step.timestamp ?? 0
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
} else if (state.thinking) {
|
|
726
|
+
entries.push({
|
|
727
|
+
id: "tl-think-0",
|
|
728
|
+
type: "thinking",
|
|
729
|
+
agentName: null,
|
|
730
|
+
parentAgent: null,
|
|
731
|
+
depth: 0,
|
|
732
|
+
content: state.thinking,
|
|
733
|
+
title: null,
|
|
734
|
+
timestamp: state.thinkingStartTime ?? 0
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
let toolIdx = 0;
|
|
738
|
+
for (const tool of state.toolCalls) {
|
|
739
|
+
entries.push({
|
|
740
|
+
id: `tl-tool-${toolIdx++}`,
|
|
741
|
+
type: "tool_call",
|
|
742
|
+
agentName: tool.agentName ?? null,
|
|
743
|
+
parentAgent: tool.parentAgent ?? null,
|
|
744
|
+
depth: tool.depth ?? 0,
|
|
745
|
+
content: tool.name,
|
|
746
|
+
title: null,
|
|
747
|
+
timestamp: tool.timestamp
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
let knowIdx = 0;
|
|
751
|
+
for (const item of state.knowledge) {
|
|
752
|
+
entries.push({
|
|
753
|
+
id: `tl-know-${knowIdx++}`,
|
|
754
|
+
type: "knowledge",
|
|
755
|
+
agentName: item.agentName ?? null,
|
|
756
|
+
parentAgent: item.parentAgent ?? null,
|
|
757
|
+
depth: item.depth ?? 0,
|
|
758
|
+
content: item.content,
|
|
759
|
+
title: item.source,
|
|
760
|
+
timestamp: item.timestamp
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
let memIdx = 0;
|
|
764
|
+
for (const item of state.memory) {
|
|
765
|
+
entries.push({
|
|
766
|
+
id: `tl-mem-${memIdx++}`,
|
|
767
|
+
type: "memory",
|
|
768
|
+
agentName: item.agentName ?? null,
|
|
769
|
+
parentAgent: item.parentAgent ?? null,
|
|
770
|
+
depth: item.depth ?? 0,
|
|
771
|
+
content: item.content,
|
|
772
|
+
title: item.type,
|
|
773
|
+
timestamp: item.timestamp
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
let statIdx = 0;
|
|
777
|
+
for (const item of state.statusUpdates) {
|
|
778
|
+
entries.push({
|
|
779
|
+
id: `tl-stat-${statIdx++}`,
|
|
780
|
+
type: "status_update",
|
|
781
|
+
agentName: item.agentName ?? item.agent ?? null,
|
|
782
|
+
parentAgent: item.parentAgent ?? null,
|
|
783
|
+
depth: item.depth ?? 0,
|
|
784
|
+
content: item.message,
|
|
785
|
+
title: null,
|
|
786
|
+
timestamp: item.timestamp
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
entries.sort((a, b) => a.timestamp - b.timestamp);
|
|
790
|
+
return entries;
|
|
791
|
+
}
|
|
792
|
+
function groupIntoAgentRuns(entries) {
|
|
793
|
+
const runs = [];
|
|
794
|
+
let currentRun = null;
|
|
795
|
+
for (const entry of entries) {
|
|
796
|
+
const name = entry.agentName || "Agent";
|
|
797
|
+
if (!currentRun || currentRun.agentName !== name) {
|
|
798
|
+
currentRun = {
|
|
799
|
+
agentName: name,
|
|
800
|
+
parentAgent: entry.parentAgent,
|
|
801
|
+
depth: entry.depth,
|
|
802
|
+
entries: []
|
|
803
|
+
};
|
|
804
|
+
runs.push(currentRun);
|
|
805
|
+
}
|
|
806
|
+
currentRun.entries.push({ entry, count: 1 });
|
|
807
|
+
}
|
|
808
|
+
for (const run of runs) {
|
|
809
|
+
run.entries = deduplicateEntries(run.entries);
|
|
810
|
+
}
|
|
811
|
+
return runs;
|
|
812
|
+
}
|
|
813
|
+
function deduplicateEntries(entries) {
|
|
814
|
+
if (entries.length === 0) return [];
|
|
815
|
+
const result = [entries[0]];
|
|
816
|
+
for (let i = 1; i < entries.length; i++) {
|
|
817
|
+
const prev = result[result.length - 1];
|
|
818
|
+
const curr = entries[i];
|
|
819
|
+
if (prev.entry.type === curr.entry.type && prev.entry.content === curr.entry.content) {
|
|
820
|
+
prev.count += curr.count;
|
|
821
|
+
} else {
|
|
822
|
+
result.push({ ...curr });
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return result;
|
|
826
|
+
}
|
|
827
|
+
|
|
338
828
|
// src/components/agent-response/hooks/useAgentResponseAccumulator.ts
|
|
339
829
|
function useAgentResponseAccumulator(options) {
|
|
340
|
-
const [state, setState] =
|
|
830
|
+
const [state, setState] = React11.useState(initialAgentResponseState);
|
|
341
831
|
const topic = options?.topic;
|
|
342
|
-
const handleMessage =
|
|
832
|
+
const handleMessage = React11.useCallback(
|
|
343
833
|
(message) => {
|
|
344
834
|
let payload;
|
|
345
835
|
if (topic) {
|
|
@@ -363,16 +853,49 @@ function useAgentResponseAccumulator(options) {
|
|
|
363
853
|
}
|
|
364
854
|
return { ...prev, status: newStatus };
|
|
365
855
|
case "thinking": {
|
|
856
|
+
if (payload.thinkingStep) {
|
|
857
|
+
const newStep = {
|
|
858
|
+
id: payload.thinkingStep.id || `step-${Date.now()}`,
|
|
859
|
+
label: payload.thinkingStep.label,
|
|
860
|
+
content: payload.thinkingStep.content,
|
|
861
|
+
depth: payload.thinkingStep.depth ?? payload.depth ?? 0,
|
|
862
|
+
isCollapsed: payload.thinkingStep.isCollapsed,
|
|
863
|
+
timestamp: Date.now(),
|
|
864
|
+
agentName: payload.agentName,
|
|
865
|
+
parentAgent: payload.parentAgent
|
|
866
|
+
};
|
|
867
|
+
const thinkingStartTime2 = prev.thinkingStartTime ?? Date.now();
|
|
868
|
+
const next2 = {
|
|
869
|
+
...prev,
|
|
870
|
+
status: newStatus,
|
|
871
|
+
thinkingSteps: [...prev.thinkingSteps || [], newStep],
|
|
872
|
+
thinkingStartTime: thinkingStartTime2,
|
|
873
|
+
firstMessageTime
|
|
874
|
+
};
|
|
875
|
+
return { ...next2, timelineEntries: buildTimelineEntries(next2) };
|
|
876
|
+
}
|
|
366
877
|
const newThinking = payload.message || payload.content || "";
|
|
367
878
|
const separator = prev.thinking && newThinking ? "\n\n" : "";
|
|
368
879
|
const thinkingStartTime = prev.thinkingStartTime ?? (newThinking ? Date.now() : null);
|
|
369
|
-
|
|
880
|
+
const prevSteps = prev.thinkingSteps || [];
|
|
881
|
+
const plainStep = {
|
|
882
|
+
id: `step-${prevSteps.length}`,
|
|
883
|
+
label: newThinking,
|
|
884
|
+
content: newThinking,
|
|
885
|
+
depth: payload.depth ?? 0,
|
|
886
|
+
timestamp: Date.now(),
|
|
887
|
+
agentName: payload.agentName,
|
|
888
|
+
parentAgent: payload.parentAgent
|
|
889
|
+
};
|
|
890
|
+
const next = {
|
|
370
891
|
...prev,
|
|
371
892
|
status: newStatus,
|
|
372
893
|
thinking: prev.thinking + separator + newThinking,
|
|
894
|
+
thinkingSteps: [...prevSteps, plainStep],
|
|
373
895
|
thinkingStartTime,
|
|
374
896
|
firstMessageTime
|
|
375
897
|
};
|
|
898
|
+
return { ...next, timelineEntries: buildTimelineEntries(next) };
|
|
376
899
|
}
|
|
377
900
|
case "tool_call": {
|
|
378
901
|
const toolName = payload.message || payload.tool?.name;
|
|
@@ -381,14 +904,18 @@ function useAgentResponseAccumulator(options) {
|
|
|
381
904
|
id: payload.tool?.id || `tool-${Date.now()}`,
|
|
382
905
|
name: toolName,
|
|
383
906
|
arguments: payload.tool?.arguments,
|
|
384
|
-
timestamp: Date.now()
|
|
907
|
+
timestamp: Date.now(),
|
|
908
|
+
agentName: payload.agentName,
|
|
909
|
+
parentAgent: payload.parentAgent,
|
|
910
|
+
depth: payload.depth
|
|
385
911
|
};
|
|
386
|
-
|
|
912
|
+
const next = {
|
|
387
913
|
...prev,
|
|
388
914
|
status: newStatus,
|
|
389
915
|
toolCalls: [...prev.toolCalls, newToolCall],
|
|
390
916
|
firstMessageTime
|
|
391
917
|
};
|
|
918
|
+
return { ...next, timelineEntries: buildTimelineEntries(next) };
|
|
392
919
|
}
|
|
393
920
|
return { ...prev, status: newStatus, firstMessageTime };
|
|
394
921
|
}
|
|
@@ -399,14 +926,18 @@ function useAgentResponseAccumulator(options) {
|
|
|
399
926
|
id: payload.knowledge?.id || `knowledge-${Date.now()}`,
|
|
400
927
|
source: payload.knowledge?.source || "unknown",
|
|
401
928
|
content: knowledgeContent,
|
|
402
|
-
timestamp: Date.now()
|
|
929
|
+
timestamp: Date.now(),
|
|
930
|
+
agentName: payload.agentName,
|
|
931
|
+
parentAgent: payload.parentAgent,
|
|
932
|
+
depth: payload.depth
|
|
403
933
|
};
|
|
404
|
-
|
|
934
|
+
const next = {
|
|
405
935
|
...prev,
|
|
406
936
|
status: newStatus,
|
|
407
937
|
knowledge: [...prev.knowledge, newKnowledge],
|
|
408
938
|
firstMessageTime
|
|
409
939
|
};
|
|
940
|
+
return { ...next, timelineEntries: buildTimelineEntries(next) };
|
|
410
941
|
}
|
|
411
942
|
return { ...prev, status: newStatus, firstMessageTime };
|
|
412
943
|
}
|
|
@@ -417,14 +948,18 @@ function useAgentResponseAccumulator(options) {
|
|
|
417
948
|
id: payload.memory?.id || `memory-${Date.now()}`,
|
|
418
949
|
type: payload.memory?.type || "unknown",
|
|
419
950
|
content: memoryContent,
|
|
420
|
-
timestamp: Date.now()
|
|
951
|
+
timestamp: Date.now(),
|
|
952
|
+
agentName: payload.agentName,
|
|
953
|
+
parentAgent: payload.parentAgent,
|
|
954
|
+
depth: payload.depth
|
|
421
955
|
};
|
|
422
|
-
|
|
956
|
+
const next = {
|
|
423
957
|
...prev,
|
|
424
958
|
status: newStatus,
|
|
425
959
|
memory: [...prev.memory, newMemory],
|
|
426
960
|
firstMessageTime
|
|
427
961
|
};
|
|
962
|
+
return { ...next, timelineEntries: buildTimelineEntries(next) };
|
|
428
963
|
}
|
|
429
964
|
return { ...prev, status: newStatus, firstMessageTime };
|
|
430
965
|
}
|
|
@@ -436,6 +971,28 @@ function useAgentResponseAccumulator(options) {
|
|
|
436
971
|
responseCompleteTime: Date.now(),
|
|
437
972
|
firstMessageTime: prev.firstMessageTime ?? Date.now()
|
|
438
973
|
};
|
|
974
|
+
case "status_update": {
|
|
975
|
+
const statusMessage = payload.message || payload.statusUpdate?.message;
|
|
976
|
+
if (statusMessage) {
|
|
977
|
+
const newStatusItem = {
|
|
978
|
+
id: payload.statusUpdate?.id || `status-${Date.now()}`,
|
|
979
|
+
message: statusMessage,
|
|
980
|
+
agent: payload.statusUpdate?.agent,
|
|
981
|
+
timestamp: Date.now(),
|
|
982
|
+
agentName: payload.agentName,
|
|
983
|
+
parentAgent: payload.parentAgent,
|
|
984
|
+
depth: payload.depth
|
|
985
|
+
};
|
|
986
|
+
const next = {
|
|
987
|
+
...prev,
|
|
988
|
+
status: newStatus,
|
|
989
|
+
statusUpdates: [...prev.statusUpdates, newStatusItem],
|
|
990
|
+
firstMessageTime
|
|
991
|
+
};
|
|
992
|
+
return { ...next, timelineEntries: buildTimelineEntries(next) };
|
|
993
|
+
}
|
|
994
|
+
return { ...prev, status: newStatus, firstMessageTime };
|
|
995
|
+
}
|
|
439
996
|
default:
|
|
440
997
|
return { ...prev, status: newStatus, firstMessageTime };
|
|
441
998
|
}
|
|
@@ -443,12 +1000,293 @@ function useAgentResponseAccumulator(options) {
|
|
|
443
1000
|
},
|
|
444
1001
|
[topic]
|
|
445
1002
|
);
|
|
446
|
-
const reset =
|
|
1003
|
+
const reset = React11.useCallback(() => {
|
|
447
1004
|
setState(initialAgentResponseState);
|
|
448
1005
|
}, []);
|
|
449
1006
|
return { state, handleMessage, reset };
|
|
450
1007
|
}
|
|
451
|
-
var
|
|
1008
|
+
var ICON_MAP = {
|
|
1009
|
+
thinking: lucideReact.Brain,
|
|
1010
|
+
tool_call: lucideReact.Wrench,
|
|
1011
|
+
knowledge: lucideReact.BookOpen,
|
|
1012
|
+
memory: lucideReact.HardDrive,
|
|
1013
|
+
status_update: lucideReact.Activity,
|
|
1014
|
+
ai_response: lucideReact.MessageSquare,
|
|
1015
|
+
error: lucideReact.AlertCircle
|
|
1016
|
+
};
|
|
1017
|
+
function TimelineItem({
|
|
1018
|
+
displayEntry,
|
|
1019
|
+
renderMarkdown,
|
|
1020
|
+
isExpanded,
|
|
1021
|
+
onToggleExpanded
|
|
1022
|
+
}) {
|
|
1023
|
+
const { entry, count } = displayEntry;
|
|
1024
|
+
const Icon = ICON_MAP[entry.type] ?? lucideReact.Activity;
|
|
1025
|
+
const isLong = entry.content.length > 200 || entry.content.split("\n").length > 3;
|
|
1026
|
+
const canExpand = isLong || entry.type === "ai_response";
|
|
1027
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1 flex items-start gap-2 group", children: [
|
|
1028
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0 mt-0.5" }),
|
|
1029
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: isExpanded && entry.type === "ai_response" && renderMarkdown ? (
|
|
1030
|
+
// Expanded AI response: rendered markdown
|
|
1031
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1032
|
+
renderMarkdown(entry.content),
|
|
1033
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1034
|
+
"button",
|
|
1035
|
+
{
|
|
1036
|
+
onClick: onToggleExpanded,
|
|
1037
|
+
className: "text-[10px] text-muted-foreground/70 hover:text-muted-foreground mt-1",
|
|
1038
|
+
children: "Show less"
|
|
1039
|
+
}
|
|
1040
|
+
)
|
|
1041
|
+
] })
|
|
1042
|
+
) : isExpanded ? (
|
|
1043
|
+
// Expanded non-AI: plain text
|
|
1044
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1045
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs text-muted-foreground whitespace-pre-wrap font-mono", children: entry.content }),
|
|
1046
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1047
|
+
"button",
|
|
1048
|
+
{
|
|
1049
|
+
onClick: onToggleExpanded,
|
|
1050
|
+
className: "text-[10px] text-muted-foreground/70 hover:text-muted-foreground mt-1",
|
|
1051
|
+
children: "Show less"
|
|
1052
|
+
}
|
|
1053
|
+
)
|
|
1054
|
+
] })
|
|
1055
|
+
) : (
|
|
1056
|
+
// Collapsed: truncated with optional expand
|
|
1057
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-1.5 min-w-0", children: [
|
|
1058
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1059
|
+
"div",
|
|
1060
|
+
{
|
|
1061
|
+
className: `text-xs text-muted-foreground min-w-0 ${canExpand ? "line-clamp-2 cursor-pointer hover:text-foreground/80" : ""}`,
|
|
1062
|
+
onClick: canExpand ? onToggleExpanded : void 0,
|
|
1063
|
+
children: entry.content
|
|
1064
|
+
}
|
|
1065
|
+
),
|
|
1066
|
+
count > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground/60 whitespace-nowrap flex-shrink-0", children: [
|
|
1067
|
+
"(x",
|
|
1068
|
+
count,
|
|
1069
|
+
")"
|
|
1070
|
+
] })
|
|
1071
|
+
] })
|
|
1072
|
+
) })
|
|
1073
|
+
] });
|
|
1074
|
+
}
|
|
1075
|
+
function TimelineAgentBlock({
|
|
1076
|
+
block,
|
|
1077
|
+
renderMarkdown,
|
|
1078
|
+
isSingleAgent,
|
|
1079
|
+
isCollapsed,
|
|
1080
|
+
onToggleCollapsed,
|
|
1081
|
+
expandedItems,
|
|
1082
|
+
onToggleItemExpanded
|
|
1083
|
+
}) {
|
|
1084
|
+
const indentPx = block.depth * 16;
|
|
1085
|
+
if (isSingleAgent && block.depth === 0) {
|
|
1086
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { paddingLeft: `${indentPx}px` }, children: block.entries.map((displayEntry, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1087
|
+
TimelineItem,
|
|
1088
|
+
{
|
|
1089
|
+
displayEntry,
|
|
1090
|
+
renderMarkdown,
|
|
1091
|
+
isExpanded: expandedItems.has(displayEntry.entry.id),
|
|
1092
|
+
onToggleExpanded: () => onToggleItemExpanded(displayEntry.entry.id)
|
|
1093
|
+
},
|
|
1094
|
+
displayEntry.entry.id + "-" + i
|
|
1095
|
+
)) });
|
|
1096
|
+
}
|
|
1097
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { paddingLeft: `${indentPx}px` }, children: [
|
|
1098
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1099
|
+
"button",
|
|
1100
|
+
{
|
|
1101
|
+
onClick: onToggleCollapsed,
|
|
1102
|
+
className: "w-full flex items-center gap-1.5 py-1 hover:bg-muted/50 -ml-1 pl-1 pr-2 rounded transition-colors text-left",
|
|
1103
|
+
children: [
|
|
1104
|
+
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" }),
|
|
1105
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-foreground/80", children: block.agentName }),
|
|
1106
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground/60", children: [
|
|
1107
|
+
"(",
|
|
1108
|
+
block.entries.reduce((sum, e) => sum + e.count, 0),
|
|
1109
|
+
")"
|
|
1110
|
+
] })
|
|
1111
|
+
]
|
|
1112
|
+
}
|
|
1113
|
+
),
|
|
1114
|
+
!isCollapsed && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-4", children: block.entries.map((displayEntry, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1115
|
+
TimelineItem,
|
|
1116
|
+
{
|
|
1117
|
+
displayEntry,
|
|
1118
|
+
renderMarkdown,
|
|
1119
|
+
isExpanded: expandedItems.has(displayEntry.entry.id),
|
|
1120
|
+
onToggleExpanded: () => onToggleItemExpanded(displayEntry.entry.id)
|
|
1121
|
+
},
|
|
1122
|
+
displayEntry.entry.id + "-" + i
|
|
1123
|
+
)) })
|
|
1124
|
+
] });
|
|
1125
|
+
}
|
|
1126
|
+
function createTimelineUIState() {
|
|
1127
|
+
return {
|
|
1128
|
+
expandedItems: /* @__PURE__ */ new Set(),
|
|
1129
|
+
collapsedRuns: /* @__PURE__ */ new Set(),
|
|
1130
|
+
activeFilters: /* @__PURE__ */ new Set()
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
var TYPE_CONFIG = [
|
|
1134
|
+
{ type: "status_update", icon: lucideReact.Activity, label: "Status" },
|
|
1135
|
+
{ type: "thinking", icon: lucideReact.Brain, label: "Thinking" },
|
|
1136
|
+
{ type: "tool_call", icon: lucideReact.Wrench, label: "Tools" },
|
|
1137
|
+
{ type: "knowledge", icon: lucideReact.BookOpen, label: "Knowledge" },
|
|
1138
|
+
{ type: "memory", icon: lucideReact.HardDrive, label: "Memory" },
|
|
1139
|
+
{ type: "ai_response", icon: lucideReact.MessageSquare, label: "AI" },
|
|
1140
|
+
{ type: "error", icon: lucideReact.AlertCircle, label: "Errors" }
|
|
1141
|
+
];
|
|
1142
|
+
function AgentTimeline({ entries, renderMarkdown, uiState, maxHeight = "300px" }) {
|
|
1143
|
+
const containerRef = React11.useRef(null);
|
|
1144
|
+
const [renderTick, setRenderTick] = React11.useState(0);
|
|
1145
|
+
const forceRender = React11.useCallback(() => setRenderTick((t) => t + 1), []);
|
|
1146
|
+
const [internalExpandedItems] = React11.useState(() => /* @__PURE__ */ new Set());
|
|
1147
|
+
const [internalCollapsedRuns] = React11.useState(() => /* @__PURE__ */ new Set());
|
|
1148
|
+
const [internalActiveFilters] = React11.useState(() => /* @__PURE__ */ new Set());
|
|
1149
|
+
const expandedItems = uiState?.expandedItems ?? internalExpandedItems;
|
|
1150
|
+
const collapsedRuns = uiState?.collapsedRuns ?? internalCollapsedRuns;
|
|
1151
|
+
const activeFilters = uiState?.activeFilters ?? internalActiveFilters;
|
|
1152
|
+
const availableTypes = React11.useMemo(() => {
|
|
1153
|
+
const types = /* @__PURE__ */ new Set();
|
|
1154
|
+
for (const entry of entries) {
|
|
1155
|
+
types.add(entry.type);
|
|
1156
|
+
}
|
|
1157
|
+
return types;
|
|
1158
|
+
}, [entries]);
|
|
1159
|
+
const filteredEntries = React11.useMemo(
|
|
1160
|
+
() => activeFilters.size === 0 ? entries : entries.filter((e) => activeFilters.has(e.type)),
|
|
1161
|
+
[entries, activeFilters, renderTick]
|
|
1162
|
+
);
|
|
1163
|
+
const agentRuns = React11.useMemo(() => groupIntoAgentRuns(filteredEntries), [filteredEntries, renderTick]);
|
|
1164
|
+
const toggleFilter = React11.useCallback((type) => {
|
|
1165
|
+
if (activeFilters.has(type)) {
|
|
1166
|
+
activeFilters.delete(type);
|
|
1167
|
+
} else {
|
|
1168
|
+
activeFilters.add(type);
|
|
1169
|
+
}
|
|
1170
|
+
forceRender();
|
|
1171
|
+
}, [activeFilters, forceRender]);
|
|
1172
|
+
const clearFilters = React11.useCallback(() => {
|
|
1173
|
+
activeFilters.clear();
|
|
1174
|
+
forceRender();
|
|
1175
|
+
}, [activeFilters, forceRender]);
|
|
1176
|
+
const toggleItemExpanded = React11.useCallback((entryId) => {
|
|
1177
|
+
if (expandedItems.has(entryId)) {
|
|
1178
|
+
expandedItems.delete(entryId);
|
|
1179
|
+
} else {
|
|
1180
|
+
expandedItems.add(entryId);
|
|
1181
|
+
}
|
|
1182
|
+
forceRender();
|
|
1183
|
+
}, [expandedItems, forceRender]);
|
|
1184
|
+
const collapseAll = React11.useCallback(() => {
|
|
1185
|
+
collapsedRuns.clear();
|
|
1186
|
+
agentRuns.forEach((run, i) => {
|
|
1187
|
+
collapsedRuns.add(`${run.agentName}-${i}`);
|
|
1188
|
+
});
|
|
1189
|
+
expandedItems.clear();
|
|
1190
|
+
forceRender();
|
|
1191
|
+
}, [agentRuns, collapsedRuns, expandedItems, forceRender]);
|
|
1192
|
+
const expandAll = React11.useCallback(() => {
|
|
1193
|
+
collapsedRuns.clear();
|
|
1194
|
+
agentRuns.forEach((run, i) => {
|
|
1195
|
+
collapsedRuns.add(`${run.agentName}-${i}:expanded`);
|
|
1196
|
+
});
|
|
1197
|
+
forceRender();
|
|
1198
|
+
}, [agentRuns, collapsedRuns, forceRender]);
|
|
1199
|
+
if (entries.length === 0) return null;
|
|
1200
|
+
const isSingle = agentRuns.length === 1;
|
|
1201
|
+
const hasActiveFilter = activeFilters.size > 0;
|
|
1202
|
+
const scrollStyle = maxHeight !== "none" ? { maxHeight } : void 0;
|
|
1203
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1204
|
+
"div",
|
|
1205
|
+
{
|
|
1206
|
+
ref: containerRef,
|
|
1207
|
+
className: `-mt-1 ${maxHeight !== "none" ? "overflow-y-auto scrollbar-thin" : ""}`,
|
|
1208
|
+
style: scrollStyle,
|
|
1209
|
+
children: [
|
|
1210
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 z-10 bg-background flex items-center gap-1 py-1.5 mb-1 border-b border-border/50 flex-wrap", children: [
|
|
1211
|
+
TYPE_CONFIG.filter((tc) => availableTypes.has(tc.type)).map((tc) => {
|
|
1212
|
+
const isActive = activeFilters.has(tc.type);
|
|
1213
|
+
const count = entries.filter((e) => e.type === tc.type).length;
|
|
1214
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1215
|
+
"button",
|
|
1216
|
+
{
|
|
1217
|
+
onClick: () => toggleFilter(tc.type),
|
|
1218
|
+
className: `inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] transition-colors ${isActive ? "bg-accent text-accent-foreground ring-1 ring-accent-foreground/20" : "text-muted-foreground/60 hover:text-muted-foreground hover:bg-muted/50"}`,
|
|
1219
|
+
title: `${isActive ? "Hide" : "Show only"} ${tc.label}`,
|
|
1220
|
+
children: [
|
|
1221
|
+
/* @__PURE__ */ jsxRuntime.jsx(tc.icon, { className: "w-3 h-3" }),
|
|
1222
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: count })
|
|
1223
|
+
]
|
|
1224
|
+
},
|
|
1225
|
+
tc.type
|
|
1226
|
+
);
|
|
1227
|
+
}),
|
|
1228
|
+
hasActiveFilter && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1229
|
+
"button",
|
|
1230
|
+
{
|
|
1231
|
+
onClick: clearFilters,
|
|
1232
|
+
className: "text-[10px] text-muted-foreground/60 hover:text-muted-foreground px-1",
|
|
1233
|
+
children: "Clear"
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
|
|
1237
|
+
!isSingle && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1238
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1239
|
+
"button",
|
|
1240
|
+
{
|
|
1241
|
+
onClick: collapseAll,
|
|
1242
|
+
className: "inline-flex items-center gap-0.5 text-[10px] text-muted-foreground/60 hover:text-muted-foreground px-1 py-0.5 rounded hover:bg-muted/50 transition-colors",
|
|
1243
|
+
title: "Collapse all",
|
|
1244
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsDownUp, { className: "w-3 h-3" })
|
|
1245
|
+
}
|
|
1246
|
+
),
|
|
1247
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1248
|
+
"button",
|
|
1249
|
+
{
|
|
1250
|
+
onClick: expandAll,
|
|
1251
|
+
className: "inline-flex items-center gap-0.5 text-[10px] text-muted-foreground/60 hover:text-muted-foreground px-1 py-0.5 rounded hover:bg-muted/50 transition-colors",
|
|
1252
|
+
title: "Expand all",
|
|
1253
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { className: "w-3 h-3" })
|
|
1254
|
+
}
|
|
1255
|
+
)
|
|
1256
|
+
] })
|
|
1257
|
+
] }),
|
|
1258
|
+
filteredEntries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-muted-foreground/50 py-2 text-center", children: "No entries match the selected filters" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children: agentRuns.map((run, i) => {
|
|
1259
|
+
const runKey = `${run.agentName}-${i}`;
|
|
1260
|
+
const defaultCollapsed = run.depth > 0;
|
|
1261
|
+
const isCollapsed = collapsedRuns.has(runKey) ? true : collapsedRuns.has(`${runKey}:expanded`) ? false : defaultCollapsed;
|
|
1262
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1263
|
+
TimelineAgentBlock,
|
|
1264
|
+
{
|
|
1265
|
+
block: run,
|
|
1266
|
+
renderMarkdown,
|
|
1267
|
+
isSingleAgent: isSingle,
|
|
1268
|
+
isCollapsed,
|
|
1269
|
+
onToggleCollapsed: () => {
|
|
1270
|
+
if (isCollapsed) {
|
|
1271
|
+
collapsedRuns.delete(runKey);
|
|
1272
|
+
collapsedRuns.add(`${runKey}:expanded`);
|
|
1273
|
+
} else {
|
|
1274
|
+
collapsedRuns.delete(`${runKey}:expanded`);
|
|
1275
|
+
collapsedRuns.add(runKey);
|
|
1276
|
+
}
|
|
1277
|
+
forceRender();
|
|
1278
|
+
},
|
|
1279
|
+
expandedItems,
|
|
1280
|
+
onToggleItemExpanded: toggleItemExpanded
|
|
1281
|
+
},
|
|
1282
|
+
runKey
|
|
1283
|
+
);
|
|
1284
|
+
}) })
|
|
1285
|
+
]
|
|
1286
|
+
}
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
var AgentResponse = React11__namespace.forwardRef(
|
|
452
1290
|
({
|
|
453
1291
|
state,
|
|
454
1292
|
id,
|
|
@@ -460,14 +1298,19 @@ var AgentResponse = React__namespace.forwardRef(
|
|
|
460
1298
|
thinkingExpanded: controlledThinkingExpanded,
|
|
461
1299
|
onThinkingExpandedChange,
|
|
462
1300
|
actionsVisible = "hover",
|
|
1301
|
+
hitlInteractions,
|
|
1302
|
+
defaultHITLExpanded = false,
|
|
1303
|
+
statusContent,
|
|
463
1304
|
renderMarkdown,
|
|
1305
|
+
renderThinkingMarkdown,
|
|
464
1306
|
className,
|
|
465
1307
|
...props
|
|
466
1308
|
}, ref) => {
|
|
467
|
-
const
|
|
1309
|
+
const timelineUIStateRef = React11.useRef(createTimelineUIState());
|
|
1310
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = React11.useState(defaultThinkingExpanded);
|
|
468
1311
|
const isThinkingControlled = controlledThinkingExpanded !== void 0;
|
|
469
1312
|
const thinkingExpanded = isThinkingControlled ? controlledThinkingExpanded : uncontrolledExpanded;
|
|
470
|
-
const toggleThinking =
|
|
1313
|
+
const toggleThinking = React11.useCallback(() => {
|
|
471
1314
|
const newValue = !thinkingExpanded;
|
|
472
1315
|
if (isThinkingControlled) {
|
|
473
1316
|
onThinkingExpandedChange?.(newValue);
|
|
@@ -475,18 +1318,21 @@ var AgentResponse = React__namespace.forwardRef(
|
|
|
475
1318
|
setUncontrolledExpanded(newValue);
|
|
476
1319
|
}
|
|
477
1320
|
}, [thinkingExpanded, isThinkingControlled, onThinkingExpandedChange]);
|
|
478
|
-
const [isHovered, setIsHovered] =
|
|
1321
|
+
const [isHovered, setIsHovered] = React11.useState(false);
|
|
479
1322
|
const elapsedTime = useThinkingTimer({
|
|
480
1323
|
startTime: state.thinkingStartTime,
|
|
481
1324
|
endTime: state.responseCompleteTime,
|
|
482
1325
|
status: state.status
|
|
483
1326
|
});
|
|
484
|
-
const totalTimeSeconds =
|
|
1327
|
+
const totalTimeSeconds = React11.useMemo(() => {
|
|
485
1328
|
if (!state.firstMessageTime || !state.responseCompleteTime) return 0;
|
|
486
1329
|
return (state.responseCompleteTime - state.firstMessageTime) / 1e3;
|
|
487
1330
|
}, [state.firstMessageTime, state.responseCompleteTime]);
|
|
488
|
-
const
|
|
489
|
-
const
|
|
1331
|
+
const hasTimelineEntries = !!(state.timelineEntries && state.timelineEntries.length > 0);
|
|
1332
|
+
const hasThinkingContent = !!state.thinking || state.thinkingSteps && state.thinkingSteps.length > 0 || hasTimelineEntries || false;
|
|
1333
|
+
const hasHITLInteractions = hitlInteractions && hitlInteractions.length > 0;
|
|
1334
|
+
const hasAnyContent = hasThinkingContent || state.toolCalls.length > 0 || state.knowledge.length > 0 || state.memory.length > 0 || state.statusUpdates.length > 0 || hasHITLInteractions || state.response;
|
|
1335
|
+
const showMetadataRow = hasThinkingContent || state.toolCalls.length > 0 || state.knowledge.length > 0 || state.memory.length > 0 || state.statusUpdates.length > 0 || state.status === "processing";
|
|
490
1336
|
const showActionBar = state.status === "complete" && state.response;
|
|
491
1337
|
const isActionBarVisible = actionsVisible === true || actionsVisible === "hover" && isHovered;
|
|
492
1338
|
if (!hasAnyContent) {
|
|
@@ -506,24 +1352,41 @@ var AgentResponse = React__namespace.forwardRef(
|
|
|
506
1352
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
507
1353
|
MetadataRow,
|
|
508
1354
|
{
|
|
509
|
-
hasThinking:
|
|
1355
|
+
hasThinking: hasThinkingContent,
|
|
510
1356
|
isExpanded: thinkingExpanded,
|
|
511
1357
|
onToggle: toggleThinking,
|
|
512
1358
|
toolCalls: state.toolCalls,
|
|
513
1359
|
knowledge: state.knowledge,
|
|
514
1360
|
memory: state.memory,
|
|
1361
|
+
statusUpdates: state.statusUpdates,
|
|
1362
|
+
statusContent,
|
|
515
1363
|
status: state.status,
|
|
516
1364
|
elapsedTime
|
|
517
1365
|
}
|
|
518
1366
|
),
|
|
519
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1367
|
+
hasTimelineEntries ? thinkingExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-3 border-t border-border mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1368
|
+
AgentTimeline,
|
|
1369
|
+
{
|
|
1370
|
+
entries: state.timelineEntries,
|
|
1371
|
+
renderMarkdown: renderThinkingMarkdown,
|
|
1372
|
+
uiState: timelineUIStateRef.current
|
|
1373
|
+
}
|
|
1374
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
520
1375
|
ThinkingSection,
|
|
521
1376
|
{
|
|
522
|
-
content: state.thinking,
|
|
523
|
-
isExpanded: thinkingExpanded
|
|
1377
|
+
content: state.thinkingSteps && state.thinkingSteps.length > 0 ? state.thinkingSteps : state.thinking,
|
|
1378
|
+
isExpanded: thinkingExpanded,
|
|
1379
|
+
renderMarkdown: renderThinkingMarkdown
|
|
524
1380
|
}
|
|
525
1381
|
)
|
|
526
1382
|
] }),
|
|
1383
|
+
hasHITLInteractions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1384
|
+
HITLSection,
|
|
1385
|
+
{
|
|
1386
|
+
interactions: hitlInteractions,
|
|
1387
|
+
defaultExpanded: defaultHITLExpanded
|
|
1388
|
+
}
|
|
1389
|
+
),
|
|
527
1390
|
state.response && /* @__PURE__ */ jsxRuntime.jsx(
|
|
528
1391
|
"div",
|
|
529
1392
|
{
|
|
@@ -552,15 +1415,401 @@ var AgentResponse = React__namespace.forwardRef(
|
|
|
552
1415
|
}
|
|
553
1416
|
);
|
|
554
1417
|
AgentResponse.displayName = "AgentResponse";
|
|
1418
|
+
var UserPrompt = React11__namespace.forwardRef(
|
|
1419
|
+
({ content, timestamp, className, ...props }, ref) => {
|
|
1420
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1421
|
+
"div",
|
|
1422
|
+
{
|
|
1423
|
+
ref,
|
|
1424
|
+
className: core.cn(
|
|
1425
|
+
"w-fit max-w-[80%] rounded-lg px-4 pt-3.5 pb-3",
|
|
1426
|
+
"bg-secondary text-secondary-foreground",
|
|
1427
|
+
className
|
|
1428
|
+
),
|
|
1429
|
+
...props,
|
|
1430
|
+
children: [
|
|
1431
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap", children: content }),
|
|
1432
|
+
timestamp && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-secondary-foreground/70 mt-1", children: timestamp.toLocaleTimeString([], {
|
|
1433
|
+
hour: "2-digit",
|
|
1434
|
+
minute: "2-digit"
|
|
1435
|
+
}) })
|
|
1436
|
+
]
|
|
1437
|
+
}
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1440
|
+
);
|
|
1441
|
+
UserPrompt.displayName = "UserPrompt";
|
|
1442
|
+
function createCodeBlockDecorate(entry) {
|
|
1443
|
+
const [node, path] = entry;
|
|
1444
|
+
const ranges = [];
|
|
1445
|
+
if (!editor.Text.isText(node)) {
|
|
1446
|
+
return ranges;
|
|
1447
|
+
}
|
|
1448
|
+
const { text } = node;
|
|
1449
|
+
const backtickPositions = [];
|
|
1450
|
+
let searchStart = 0;
|
|
1451
|
+
while (true) {
|
|
1452
|
+
const pos = text.indexOf("```", searchStart);
|
|
1453
|
+
if (pos === -1) break;
|
|
1454
|
+
backtickPositions.push(pos);
|
|
1455
|
+
searchStart = pos + 3;
|
|
1456
|
+
}
|
|
1457
|
+
let i = 0;
|
|
1458
|
+
while (i < backtickPositions.length) {
|
|
1459
|
+
const openPos = backtickPositions[i];
|
|
1460
|
+
const closePos = backtickPositions[i + 1];
|
|
1461
|
+
ranges.push({
|
|
1462
|
+
anchor: { path, offset: openPos },
|
|
1463
|
+
focus: { path, offset: openPos + 3 },
|
|
1464
|
+
codeDelimiter: true
|
|
1465
|
+
});
|
|
1466
|
+
if (closePos !== void 0) {
|
|
1467
|
+
if (closePos > openPos + 3) {
|
|
1468
|
+
ranges.push({
|
|
1469
|
+
anchor: { path, offset: openPos + 3 },
|
|
1470
|
+
focus: { path, offset: closePos },
|
|
1471
|
+
codeBlock: true
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
ranges.push({
|
|
1475
|
+
anchor: { path, offset: closePos },
|
|
1476
|
+
focus: { path, offset: closePos + 3 },
|
|
1477
|
+
codeDelimiter: true
|
|
1478
|
+
});
|
|
1479
|
+
i += 2;
|
|
1480
|
+
} else {
|
|
1481
|
+
if (text.length > openPos + 3) {
|
|
1482
|
+
ranges.push({
|
|
1483
|
+
anchor: { path, offset: openPos + 3 },
|
|
1484
|
+
focus: { path, offset: text.length },
|
|
1485
|
+
codeBlock: true
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
i += 1;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
return ranges;
|
|
1492
|
+
}
|
|
1493
|
+
function CodeBlockLeaf({ attributes, children, leaf }) {
|
|
1494
|
+
const leafAny = leaf;
|
|
1495
|
+
if (leafAny.codeBlock) {
|
|
1496
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1497
|
+
"span",
|
|
1498
|
+
{
|
|
1499
|
+
...attributes,
|
|
1500
|
+
className: "bg-muted/50 text-muted-foreground font-mono text-sm rounded px-1",
|
|
1501
|
+
children
|
|
1502
|
+
}
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
if (leafAny.codeDelimiter) {
|
|
1506
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1507
|
+
"span",
|
|
1508
|
+
{
|
|
1509
|
+
...attributes,
|
|
1510
|
+
className: "text-muted-foreground/50 font-mono text-sm",
|
|
1511
|
+
children
|
|
1512
|
+
}
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { ...attributes, children });
|
|
1516
|
+
}
|
|
1517
|
+
var UserPromptInput = React11__namespace.forwardRef(
|
|
1518
|
+
({
|
|
1519
|
+
value = "",
|
|
1520
|
+
onChange,
|
|
1521
|
+
onSubmit,
|
|
1522
|
+
clearOnSubmit = true,
|
|
1523
|
+
placeholder = "Type your message...",
|
|
1524
|
+
disabled = false,
|
|
1525
|
+
isSubmitting = false,
|
|
1526
|
+
onStop,
|
|
1527
|
+
disableWhileSubmitting = true,
|
|
1528
|
+
autoFocus = false,
|
|
1529
|
+
refocusAfterSubmit = false,
|
|
1530
|
+
onReady,
|
|
1531
|
+
minRows = 1,
|
|
1532
|
+
maxRows = 6,
|
|
1533
|
+
renderActions,
|
|
1534
|
+
enableTags = false,
|
|
1535
|
+
onTagCreate,
|
|
1536
|
+
onTagDelete,
|
|
1537
|
+
className,
|
|
1538
|
+
...props
|
|
1539
|
+
}, ref) => {
|
|
1540
|
+
const editorRef = React11__namespace.useRef(null);
|
|
1541
|
+
const [internalValue, setInternalValue] = React11__namespace.useState(value);
|
|
1542
|
+
const prevIsSubmitting = React11__namespace.useRef(isSubmitting);
|
|
1543
|
+
const hasEmittedReady = React11__namespace.useRef(false);
|
|
1544
|
+
React11__namespace.useEffect(() => {
|
|
1545
|
+
setInternalValue(value);
|
|
1546
|
+
}, [value]);
|
|
1547
|
+
React11__namespace.useEffect(() => {
|
|
1548
|
+
if (autoFocus) {
|
|
1549
|
+
requestAnimationFrame(() => {
|
|
1550
|
+
requestAnimationFrame(() => {
|
|
1551
|
+
editorRef.current?.focus();
|
|
1552
|
+
});
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
}, [autoFocus]);
|
|
1556
|
+
React11__namespace.useEffect(() => {
|
|
1557
|
+
if (!hasEmittedReady.current && onReady) {
|
|
1558
|
+
requestAnimationFrame(() => {
|
|
1559
|
+
requestAnimationFrame(() => {
|
|
1560
|
+
hasEmittedReady.current = true;
|
|
1561
|
+
onReady();
|
|
1562
|
+
});
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
}, [onReady]);
|
|
1566
|
+
React11__namespace.useEffect(() => {
|
|
1567
|
+
if (refocusAfterSubmit && prevIsSubmitting.current && !isSubmitting) {
|
|
1568
|
+
requestAnimationFrame(() => {
|
|
1569
|
+
editorRef.current?.focus();
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
prevIsSubmitting.current = isSubmitting;
|
|
1573
|
+
}, [isSubmitting, refocusAfterSubmit]);
|
|
1574
|
+
React11__namespace.useImperativeHandle(
|
|
1575
|
+
ref,
|
|
1576
|
+
() => ({
|
|
1577
|
+
focus: () => {
|
|
1578
|
+
try {
|
|
1579
|
+
editorRef.current?.focus();
|
|
1580
|
+
} catch {
|
|
1581
|
+
requestAnimationFrame(() => {
|
|
1582
|
+
requestAnimationFrame(() => {
|
|
1583
|
+
editorRef.current?.focus();
|
|
1584
|
+
});
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
},
|
|
1588
|
+
clear: () => {
|
|
1589
|
+
editorRef.current?.clear();
|
|
1590
|
+
setInternalValue("");
|
|
1591
|
+
},
|
|
1592
|
+
getText: () => editorRef.current?.getText() ?? "",
|
|
1593
|
+
insertText: (text) => editorRef.current?.insertText(text)
|
|
1594
|
+
}),
|
|
1595
|
+
[]
|
|
1596
|
+
);
|
|
1597
|
+
const handleChange = React11__namespace.useCallback(
|
|
1598
|
+
(newValue) => {
|
|
1599
|
+
setInternalValue(newValue);
|
|
1600
|
+
onChange?.(newValue);
|
|
1601
|
+
},
|
|
1602
|
+
[onChange]
|
|
1603
|
+
);
|
|
1604
|
+
const handleSubmit = React11__namespace.useCallback(
|
|
1605
|
+
(text) => {
|
|
1606
|
+
if (disabled || isSubmitting) return;
|
|
1607
|
+
if (!text.trim()) return;
|
|
1608
|
+
onSubmit?.(text.trim());
|
|
1609
|
+
if (clearOnSubmit) {
|
|
1610
|
+
editorRef.current?.clear();
|
|
1611
|
+
setInternalValue("");
|
|
1612
|
+
}
|
|
1613
|
+
},
|
|
1614
|
+
[disabled, isSubmitting, onSubmit, clearOnSubmit]
|
|
1615
|
+
);
|
|
1616
|
+
const handleSendClick = React11__namespace.useCallback(() => {
|
|
1617
|
+
const text = editorRef.current?.getText() ?? "";
|
|
1618
|
+
handleSubmit(text);
|
|
1619
|
+
}, [handleSubmit]);
|
|
1620
|
+
const hasContent = internalValue.trim().length > 0;
|
|
1621
|
+
const canSubmit = hasContent && !disabled && !isSubmitting;
|
|
1622
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1623
|
+
"div",
|
|
1624
|
+
{
|
|
1625
|
+
className: core.cn(
|
|
1626
|
+
"rounded-lg border border-input bg-background",
|
|
1627
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
1628
|
+
className
|
|
1629
|
+
),
|
|
1630
|
+
...props,
|
|
1631
|
+
children: [
|
|
1632
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-2 pr-0 pt-1 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1633
|
+
editor.SlateEditor,
|
|
1634
|
+
{
|
|
1635
|
+
ref: editorRef,
|
|
1636
|
+
value: internalValue,
|
|
1637
|
+
onChange: handleChange,
|
|
1638
|
+
onSubmit: handleSubmit,
|
|
1639
|
+
clearOnSubmit: false,
|
|
1640
|
+
placeholder,
|
|
1641
|
+
disabled: disabled || disableWhileSubmitting && isSubmitting,
|
|
1642
|
+
enableTags,
|
|
1643
|
+
onTagCreate,
|
|
1644
|
+
onTagDelete,
|
|
1645
|
+
minRows,
|
|
1646
|
+
maxRows,
|
|
1647
|
+
decorate: createCodeBlockDecorate,
|
|
1648
|
+
renderLeaf: CodeBlockLeaf
|
|
1649
|
+
}
|
|
1650
|
+
) }),
|
|
1651
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pl-2 pr-1 pb-1 pt-1", children: [
|
|
1652
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: renderActions?.() }),
|
|
1653
|
+
isSubmitting && onStop ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1654
|
+
core.IconButton,
|
|
1655
|
+
{
|
|
1656
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, {}),
|
|
1657
|
+
variant: "filled",
|
|
1658
|
+
size: "sm",
|
|
1659
|
+
"aria-label": "Stop",
|
|
1660
|
+
onClick: onStop
|
|
1661
|
+
}
|
|
1662
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1663
|
+
core.IconButton,
|
|
1664
|
+
{
|
|
1665
|
+
icon: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, {}),
|
|
1666
|
+
variant: "filled",
|
|
1667
|
+
size: "sm",
|
|
1668
|
+
"aria-label": isSubmitting ? "Sending..." : "Send message",
|
|
1669
|
+
disabled: !canSubmit,
|
|
1670
|
+
onClick: handleSendClick
|
|
1671
|
+
}
|
|
1672
|
+
)
|
|
1673
|
+
] })
|
|
1674
|
+
]
|
|
1675
|
+
}
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
);
|
|
1679
|
+
UserPromptInput.displayName = "UserPromptInput";
|
|
1680
|
+
|
|
1681
|
+
// src/components/inline-actions/parseResponseSegments.ts
|
|
1682
|
+
var ACTION_BLOCK_REGEX = /```json:action\s*\n([\s\S]*?)```/g;
|
|
1683
|
+
function parseResponseSegments(text) {
|
|
1684
|
+
if (!text) return [];
|
|
1685
|
+
const segments = [];
|
|
1686
|
+
let lastIndex = 0;
|
|
1687
|
+
ACTION_BLOCK_REGEX.lastIndex = 0;
|
|
1688
|
+
let match;
|
|
1689
|
+
while ((match = ACTION_BLOCK_REGEX.exec(text)) !== null) {
|
|
1690
|
+
const before = text.slice(lastIndex, match.index);
|
|
1691
|
+
if (before.trim()) {
|
|
1692
|
+
segments.push({ kind: "markdown", content: before });
|
|
1693
|
+
}
|
|
1694
|
+
const jsonContent = match[1].trim();
|
|
1695
|
+
let parsed = null;
|
|
1696
|
+
try {
|
|
1697
|
+
parsed = JSON.parse(jsonContent);
|
|
1698
|
+
} catch {
|
|
1699
|
+
}
|
|
1700
|
+
if (parsed && typeof parsed === "object" && typeof parsed.type === "string") {
|
|
1701
|
+
segments.push({
|
|
1702
|
+
kind: "action",
|
|
1703
|
+
actionType: parsed.type,
|
|
1704
|
+
payload: parsed
|
|
1705
|
+
});
|
|
1706
|
+
} else {
|
|
1707
|
+
const rawBlock = match[0];
|
|
1708
|
+
segments.push({ kind: "markdown", content: rawBlock });
|
|
1709
|
+
}
|
|
1710
|
+
lastIndex = match.index + match[0].length;
|
|
1711
|
+
}
|
|
1712
|
+
const trailing = text.slice(lastIndex);
|
|
1713
|
+
if (trailing.trim()) {
|
|
1714
|
+
segments.push({ kind: "markdown", content: trailing });
|
|
1715
|
+
}
|
|
1716
|
+
return segments;
|
|
1717
|
+
}
|
|
1718
|
+
function ActionMarkdownRenderer({
|
|
1719
|
+
content,
|
|
1720
|
+
registry,
|
|
1721
|
+
renderMarkdown,
|
|
1722
|
+
onAction,
|
|
1723
|
+
isLatest
|
|
1724
|
+
}) {
|
|
1725
|
+
const segments = React11.useMemo(() => parseResponseSegments(content), [content]);
|
|
1726
|
+
if (segments.length === 1 && segments[0].kind === "markdown") {
|
|
1727
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderMarkdown(segments[0].content) });
|
|
1728
|
+
}
|
|
1729
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: segments.map((segment, index) => {
|
|
1730
|
+
if (segment.kind === "markdown") {
|
|
1731
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderMarkdown(segment.content) }, `md-${index}`);
|
|
1732
|
+
}
|
|
1733
|
+
const Component = registry[segment.actionType];
|
|
1734
|
+
if (!Component) {
|
|
1735
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1736
|
+
"pre",
|
|
1737
|
+
{
|
|
1738
|
+
className: "my-4 p-4 rounded-lg border border-border bg-muted text-sm font-mono overflow-x-auto",
|
|
1739
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: JSON.stringify(segment.payload, null, 2) })
|
|
1740
|
+
},
|
|
1741
|
+
`action-fallback-${index}`
|
|
1742
|
+
);
|
|
1743
|
+
}
|
|
1744
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1745
|
+
Component,
|
|
1746
|
+
{
|
|
1747
|
+
payload: segment.payload,
|
|
1748
|
+
onAction,
|
|
1749
|
+
isLatest
|
|
1750
|
+
},
|
|
1751
|
+
`action-${segment.actionType}-${index}`
|
|
1752
|
+
);
|
|
1753
|
+
}) });
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
// src/components/inline-actions/prompts.ts
|
|
1757
|
+
var INLINE_ACTION_PROMPT = `
|
|
1758
|
+
<inline_actions>
|
|
1759
|
+
When your response should include interactive components (like query viewers,
|
|
1760
|
+
data tables, or executable actions), embed them as fenced code blocks using
|
|
1761
|
+
the \`json:action\` language tag:
|
|
1762
|
+
|
|
1763
|
+
\`\`\`json:action
|
|
1764
|
+
{
|
|
1765
|
+
"type": "action-type-here",
|
|
1766
|
+
...action-specific fields
|
|
1767
|
+
}
|
|
1768
|
+
\`\`\`
|
|
1769
|
+
|
|
1770
|
+
Rules:
|
|
1771
|
+
- Each block must contain valid JSON with a "type" field.
|
|
1772
|
+
- The "type" must match a registered action component on the frontend.
|
|
1773
|
+
- Multiple action blocks per response are allowed.
|
|
1774
|
+
- Surround action blocks with normal markdown text for user context.
|
|
1775
|
+
- The action block is rendered as an interactive component in the chat UI.
|
|
1776
|
+
- SQL strings inside JSON must be properly escaped (newlines as \\n, quotes as \\").
|
|
1777
|
+
|
|
1778
|
+
Available action types:
|
|
1779
|
+
|
|
1780
|
+
- "optimap-query": Displays SQL queries with a button to execute them and
|
|
1781
|
+
update the 3D globe map.
|
|
1782
|
+
Required fields:
|
|
1783
|
+
- type: "optimap-query"
|
|
1784
|
+
- locations_sql: string (the validated locations SQL query)
|
|
1785
|
+
- routes_sql: string (the validated routes SQL query)
|
|
1786
|
+
- database_name: string (the target database name)
|
|
1787
|
+
</inline_actions>
|
|
1788
|
+
`;
|
|
555
1789
|
|
|
556
1790
|
exports.ActionBar = ActionBar;
|
|
1791
|
+
exports.ActionMarkdownRenderer = ActionMarkdownRenderer;
|
|
557
1792
|
exports.ActivityIndicators = ActivityIndicators;
|
|
558
1793
|
exports.AgentResponse = AgentResponse;
|
|
1794
|
+
exports.AgentTimeline = AgentTimeline;
|
|
1795
|
+
exports.HITLInteractionRecord = HITLInteractionRecord;
|
|
1796
|
+
exports.HITLQuestionPanel = HITLQuestionPanel;
|
|
1797
|
+
exports.HITLSection = HITLSection;
|
|
1798
|
+
exports.INLINE_ACTION_PROMPT = INLINE_ACTION_PROMPT;
|
|
559
1799
|
exports.MetadataRow = MetadataRow;
|
|
560
1800
|
exports.ThinkingSection = ThinkingSection;
|
|
1801
|
+
exports.TruncatedMessage = TruncatedMessage;
|
|
1802
|
+
exports.UserPrompt = UserPrompt;
|
|
1803
|
+
exports.UserPromptInput = UserPromptInput;
|
|
1804
|
+
exports.buildResponseString = buildResponseString;
|
|
1805
|
+
exports.buildTimelineEntries = buildTimelineEntries;
|
|
1806
|
+
exports.createTimelineUIState = createTimelineUIState;
|
|
1807
|
+
exports.deduplicateEntries = deduplicateEntries;
|
|
561
1808
|
exports.formatTime = formatTime;
|
|
562
1809
|
exports.formatTotalTime = formatTotalTime;
|
|
1810
|
+
exports.groupIntoAgentRuns = groupIntoAgentRuns;
|
|
563
1811
|
exports.initialAgentResponseState = initialAgentResponseState;
|
|
1812
|
+
exports.parseResponseSegments = parseResponseSegments;
|
|
564
1813
|
exports.useAgentResponseAccumulator = useAgentResponseAccumulator;
|
|
565
1814
|
exports.useThinkingTimer = useThinkingTimer;
|
|
566
1815
|
//# sourceMappingURL=index.cjs.map
|