@vegintech/langchain-react-agent 0.0.24 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +66 -28
- package/dist/index.mjs +605 -608
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as react from "react";
|
|
2
2
|
import React$1, { ReactNode } from "react";
|
|
3
3
|
import { ThoughtChainItemProps } from "@ant-design/x";
|
|
4
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
5
|
import { Components } from "streamdown";
|
|
5
|
-
import
|
|
6
|
+
import { UseStreamOptions, useStream } from "@langchain/langgraph-sdk/react";
|
|
6
7
|
import { BaseNode, InsertPosition, NodeRender, SenderProps, SkillType, SlotConfigType } from "@ant-design/x/es/sender/interface.ts";
|
|
7
8
|
import { Message } from "@langchain/langgraph-sdk";
|
|
8
9
|
|
|
@@ -35,8 +36,11 @@ interface InterruptConfig {
|
|
|
35
36
|
}
|
|
36
37
|
/** InterruptManager Hook 的 Props */
|
|
37
38
|
interface InterruptManagerProps {
|
|
38
|
-
/** 当前 interrupt 事件 */
|
|
39
|
-
interrupt:
|
|
39
|
+
/** 当前 interrupt 事件 - 与 useStream 返回的 Interrupt 类型兼容 */
|
|
40
|
+
interrupt: {
|
|
41
|
+
value: unknown;
|
|
42
|
+
id?: string;
|
|
43
|
+
} | null | undefined;
|
|
40
44
|
/** Interrupt 处理配置 */
|
|
41
45
|
config?: InterruptConfig;
|
|
42
46
|
/** 提交回调 */
|
|
@@ -46,7 +50,7 @@ interface InterruptManagerProps {
|
|
|
46
50
|
command?: {
|
|
47
51
|
resume: unknown;
|
|
48
52
|
};
|
|
49
|
-
}) => Promise<void> | void;
|
|
53
|
+
} | Record<string, unknown>) => Promise<void> | void;
|
|
50
54
|
}
|
|
51
55
|
/** Context Item,用于传递上下文信息 */
|
|
52
56
|
interface ContextItem {
|
|
@@ -219,25 +223,42 @@ interface InputConfig extends SenderCustomizationProps {
|
|
|
219
223
|
/** 输入框占位符文本 */
|
|
220
224
|
placeholder?: string;
|
|
221
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* AgentChat 需要的 Stream 属性
|
|
228
|
+
* 由外部通过 useStream/useAgentStream hook 创建并传入
|
|
229
|
+
*/
|
|
230
|
+
interface AgentChatStreamProps {
|
|
231
|
+
/** 消息列表 */
|
|
232
|
+
messages: Message[];
|
|
233
|
+
/** 是否正在加载 */
|
|
234
|
+
isLoading: boolean;
|
|
235
|
+
/** 提交消息 */
|
|
236
|
+
submit: (values: {
|
|
237
|
+
[x: string]: unknown;
|
|
238
|
+
} | null | undefined, options?: {
|
|
239
|
+
command?: {
|
|
240
|
+
resume: unknown;
|
|
241
|
+
};
|
|
242
|
+
} | Record<string, unknown>) => Promise<void> | void;
|
|
243
|
+
/** 中断事件 - 与 useStream 返回的 Interrupt 类型兼容 */
|
|
244
|
+
interrupt: unknown;
|
|
245
|
+
/** 停止流 */
|
|
246
|
+
stop: () => Promise<void> | void;
|
|
247
|
+
}
|
|
222
248
|
interface AgentChatProps {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Stream 相关属性
|
|
251
|
+
* 由外部通过 useAgentStream/useStream hook 创建并解构传入
|
|
252
|
+
*/
|
|
253
|
+
stream: AgentChatStreamProps;
|
|
228
254
|
className?: string;
|
|
229
255
|
tools?: ToolDefinition<any>[];
|
|
230
256
|
contexts?: ContextItem[];
|
|
231
257
|
messageConfig?: MessageConfig;
|
|
232
258
|
inputConfig?: InputConfig;
|
|
233
|
-
onError?: (error: Error) => void;
|
|
234
259
|
interruptConfig?: InterruptConfig;
|
|
235
260
|
/** Agent 状态值 */
|
|
236
261
|
agentState?: Record<string, unknown>;
|
|
237
|
-
/** Agent 状态变化回调 */
|
|
238
|
-
onAgentStateChange?: (state: Record<string, unknown>) => void;
|
|
239
|
-
/** 是否显示调试面板,默认 false。仅在开发环境生效 */
|
|
240
|
-
showDebug?: boolean;
|
|
241
262
|
/** 欢迎组件,当消息列表为空且非加载状态时显示 */
|
|
242
263
|
welcome?: ReactNode;
|
|
243
264
|
}
|
|
@@ -251,19 +272,6 @@ interface AgentChatRef {
|
|
|
251
272
|
clearInput: () => void;
|
|
252
273
|
/** 聚焦输入框 */
|
|
253
274
|
focusInput: () => void;
|
|
254
|
-
/**
|
|
255
|
-
* LangGraph Stream 实例
|
|
256
|
-
* 提供对底层流式连接的完整访问,包括:
|
|
257
|
-
* - messages: 当前消息列表
|
|
258
|
-
* - values: Agent 状态值
|
|
259
|
-
* - isLoading: 是否正在加载
|
|
260
|
-
* - submit: 提交消息
|
|
261
|
-
* - stop: 停止流
|
|
262
|
-
* - interrupt: 中断事件
|
|
263
|
-
* - client: LangGraph 客户端(可通过 client.threads.create() 创建新线程)
|
|
264
|
-
* 等完整功能
|
|
265
|
-
*/
|
|
266
|
-
stream: ReturnType<typeof _langchain_langgraph_sdk_react0.useStream> | null;
|
|
267
275
|
}
|
|
268
276
|
/** Streamdown 安全过滤配置 */
|
|
269
277
|
interface StreamdownSecurityConfig {
|
|
@@ -309,4 +317,34 @@ interface MessageContentRendererProps {
|
|
|
309
317
|
/** 消息内容渲染组件 - 支持字符串和多模态内容块 */
|
|
310
318
|
declare const MessageContentRenderer: React$1.FC<MessageContentRendererProps>;
|
|
311
319
|
//#endregion
|
|
312
|
-
|
|
320
|
+
//#region src/components/DebugPanel.d.ts
|
|
321
|
+
interface DebugPanelProps {
|
|
322
|
+
/** Stream 状态数据(包含 messages) */
|
|
323
|
+
streamState: Record<string, unknown>;
|
|
324
|
+
/** 是否显示调试面板 */
|
|
325
|
+
visible?: boolean;
|
|
326
|
+
}
|
|
327
|
+
declare function DebugPanel({
|
|
328
|
+
streamState,
|
|
329
|
+
visible
|
|
330
|
+
}: DebugPanelProps): react_jsx_runtime0.JSX.Element | null;
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/hooks/useAgentStream.d.ts
|
|
333
|
+
type AgentStreamOptions = UseStreamOptions;
|
|
334
|
+
type AgentStream = ReturnType<typeof useStream>;
|
|
335
|
+
/**
|
|
336
|
+
* 包装 useStream hook,为 AgentChat 提供统一的 stream 实例创建方式
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```tsx
|
|
340
|
+
* const stream = useAgentStream({
|
|
341
|
+
* apiUrl: "http://localhost:2026",
|
|
342
|
+
* assistantId: "demo",
|
|
343
|
+
* });
|
|
344
|
+
*
|
|
345
|
+
* <AgentChat stream={stream} />
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
declare function useAgentStream(options: AgentStreamOptions): AgentStream;
|
|
349
|
+
//#endregion
|
|
350
|
+
export { AgentChat, type AgentChatInputRef, type AgentChatProps, type AgentChatRef, type AgentChatStreamProps, type AgentStream, type AgentStreamOptions, type BackendTool, type ChatMessage, type ContextItem, DebugPanel, type DebugPanelProps, type EmptyStateConfig, type FrontendTool, type InputConfig, type InterruptConfig, type InterruptEvent, type InterruptManagerProps, type InterruptRenderProps, type MessageConfig, type MessageContent, type MessageContentBlock, MessageContentRenderer, type MessageContentRendererProps, type MessageType, type SenderCustomizationProps, type SenderSlotConfig, type SenderSubmitParams, type ToolCallInput, ToolCard, type ToolCardProps, type ToolDefinition, type ToolExecutionRecord, type ToolExecutionStatus, type ToolParameterSchema, type ToolRenderProps, useAgentStream };
|
package/dist/index.mjs
CHANGED
|
@@ -456,551 +456,84 @@ const MessageList = ({ messages, isLoading = false, className = "", tools, toolE
|
|
|
456
456
|
});
|
|
457
457
|
};
|
|
458
458
|
//#endregion
|
|
459
|
-
//#region src/
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
469
|
-
const [activeTab, setActiveTab] = useState("messages");
|
|
470
|
-
const [expandedRows, setExpandedRows] = useState(/* @__PURE__ */ new Set());
|
|
471
|
-
const [buttonPos, setButtonPos] = useState({
|
|
472
|
-
x: 0,
|
|
473
|
-
y: 0
|
|
474
|
-
});
|
|
475
|
-
const [isDraggingButton, setIsDraggingButton] = useState(false);
|
|
476
|
-
const buttonDragRef = useRef(null);
|
|
477
|
-
const [dialogPos, setDialogPos] = useState({
|
|
478
|
-
x: 0,
|
|
479
|
-
y: 0
|
|
480
|
-
});
|
|
481
|
-
const [isDraggingDialog, setIsDraggingDialog] = useState(false);
|
|
482
|
-
const dialogDragRef = useRef(null);
|
|
483
|
-
const handleButtonMouseDown = useCallback((e) => {
|
|
484
|
-
e.preventDefault();
|
|
485
|
-
buttonDragRef.current = {
|
|
486
|
-
startX: e.clientX,
|
|
487
|
-
startY: e.clientY,
|
|
488
|
-
initialX: buttonPos.x,
|
|
489
|
-
initialY: buttonPos.y
|
|
490
|
-
};
|
|
491
|
-
setIsDraggingButton(true);
|
|
492
|
-
}, [buttonPos]);
|
|
493
|
-
const handleDialogMouseDown = useCallback((e) => {
|
|
494
|
-
if (!e.target.closest(".debug-panel-header")) return;
|
|
495
|
-
e.preventDefault();
|
|
496
|
-
dialogDragRef.current = {
|
|
497
|
-
startX: e.clientX,
|
|
498
|
-
startY: e.clientY,
|
|
499
|
-
initialX: dialogPos.x,
|
|
500
|
-
initialY: dialogPos.y
|
|
501
|
-
};
|
|
502
|
-
setIsDraggingDialog(true);
|
|
503
|
-
}, [dialogPos]);
|
|
459
|
+
//#region src/hooks/useInterrupt.tsx
|
|
460
|
+
/**
|
|
461
|
+
* InterruptManager - 管理 Interrupt 状态的 Hook
|
|
462
|
+
*
|
|
463
|
+
* 封装 Interrupt 状态管理和处理逻辑,避免在 AgentChat 组件中臃肿
|
|
464
|
+
*/
|
|
465
|
+
function useInterrupt({ interrupt, config, onSubmit }) {
|
|
466
|
+
const [activeInterrupt, setActiveInterrupt] = useState(null);
|
|
467
|
+
const processedInterruptIdRef = useRef(null);
|
|
504
468
|
useEffect(() => {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
x: buttonDragRef.current.initialX + dx,
|
|
511
|
-
y: buttonDragRef.current.initialY + dy
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
if (isDraggingDialog && dialogDragRef.current) {
|
|
515
|
-
const dx = e.clientX - dialogDragRef.current.startX;
|
|
516
|
-
const dy = e.clientY - dialogDragRef.current.startY;
|
|
517
|
-
setDialogPos({
|
|
518
|
-
x: dialogDragRef.current.initialX + dx,
|
|
519
|
-
y: dialogDragRef.current.initialY + dy
|
|
520
|
-
});
|
|
469
|
+
if (interrupt) {
|
|
470
|
+
const interruptEvent = interrupt;
|
|
471
|
+
if (interruptEvent.id !== processedInterruptIdRef.current) {
|
|
472
|
+
processedInterruptIdRef.current = interruptEvent.id;
|
|
473
|
+
setActiveInterrupt(interruptEvent);
|
|
521
474
|
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
setIsDraggingDialog(false);
|
|
526
|
-
buttonDragRef.current = null;
|
|
527
|
-
dialogDragRef.current = null;
|
|
528
|
-
};
|
|
529
|
-
if (isDraggingButton || isDraggingDialog) {
|
|
530
|
-
document.addEventListener("mousemove", handleMouseMove);
|
|
531
|
-
document.addEventListener("mouseup", handleMouseUp);
|
|
532
|
-
}
|
|
533
|
-
return () => {
|
|
534
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
535
|
-
document.removeEventListener("mouseup", handleMouseUp);
|
|
536
|
-
};
|
|
537
|
-
}, [isDraggingButton, isDraggingDialog]);
|
|
538
|
-
const formatJson = (data) => {
|
|
539
|
-
try {
|
|
540
|
-
return JSON.stringify(data, null, 2);
|
|
541
|
-
} catch {
|
|
542
|
-
return String(data);
|
|
475
|
+
} else {
|
|
476
|
+
processedInterruptIdRef.current = null;
|
|
477
|
+
setActiveInterrupt(null);
|
|
543
478
|
}
|
|
479
|
+
}, [interrupt?.id]);
|
|
480
|
+
const handleResolveInterrupt = useCallback((response) => {
|
|
481
|
+
onSubmit(null, { command: { resume: response } });
|
|
482
|
+
setActiveInterrupt(null);
|
|
483
|
+
}, [onSubmit]);
|
|
484
|
+
return {
|
|
485
|
+
activeInterrupt,
|
|
486
|
+
handleResolveInterrupt,
|
|
487
|
+
renderInterrupt: useCallback(() => {
|
|
488
|
+
if (!activeInterrupt || !config?.render) return null;
|
|
489
|
+
return /* @__PURE__ */ jsx("div", {
|
|
490
|
+
className: "agent-chat-interrupt",
|
|
491
|
+
children: config.render({
|
|
492
|
+
event: activeInterrupt,
|
|
493
|
+
resolve: handleResolveInterrupt
|
|
494
|
+
})
|
|
495
|
+
});
|
|
496
|
+
}, [
|
|
497
|
+
activeInterrupt,
|
|
498
|
+
config,
|
|
499
|
+
handleResolveInterrupt
|
|
500
|
+
])
|
|
544
501
|
};
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
display: "inline-block",
|
|
581
|
-
padding: "2px 8px",
|
|
582
|
-
borderRadius: "4px",
|
|
583
|
-
fontSize: "12px",
|
|
584
|
-
fontWeight: 500,
|
|
585
|
-
background: color.bg,
|
|
586
|
-
color: color.color
|
|
587
|
-
};
|
|
588
|
-
};
|
|
589
|
-
const formatContent = (content) => {
|
|
590
|
-
if (!content) return "";
|
|
591
|
-
if (Array.isArray(content)) return content.map((item) => typeof item === "string" ? item : JSON.stringify(item)).join("");
|
|
592
|
-
return String(content);
|
|
593
|
-
};
|
|
594
|
-
const renderMessageContent = (message) => {
|
|
595
|
-
const hasToolCalls = message.tool_calls && Array.isArray(message.tool_calls) && message.tool_calls.length > 0;
|
|
596
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
597
|
-
style: {
|
|
598
|
-
display: "flex",
|
|
599
|
-
flexDirection: "column",
|
|
600
|
-
gap: "8px"
|
|
601
|
-
},
|
|
602
|
-
children: [message.content && /* @__PURE__ */ jsx("div", {
|
|
603
|
-
style: {
|
|
604
|
-
color: "#333",
|
|
605
|
-
lineHeight: 1.5,
|
|
606
|
-
wordBreak: "break-all"
|
|
607
|
-
},
|
|
608
|
-
children: formatContent(message.content)
|
|
609
|
-
}), hasToolCalls && /* @__PURE__ */ jsxs("div", {
|
|
610
|
-
style: {
|
|
611
|
-
marginTop: "4px",
|
|
612
|
-
padding: "8px",
|
|
613
|
-
background: "#f6ffed",
|
|
614
|
-
border: "1px solid #b7eb8f",
|
|
615
|
-
borderRadius: "6px"
|
|
616
|
-
},
|
|
617
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
618
|
-
style: {
|
|
619
|
-
fontSize: "11px",
|
|
620
|
-
fontWeight: 600,
|
|
621
|
-
color: "#389e0d",
|
|
622
|
-
marginBottom: "6px",
|
|
623
|
-
display: "flex",
|
|
624
|
-
alignItems: "center",
|
|
625
|
-
gap: "4px"
|
|
626
|
-
},
|
|
627
|
-
children: [/* @__PURE__ */ jsx("span", { children: "🔧" }), /* @__PURE__ */ jsxs("span", { children: [
|
|
628
|
-
"Tool Calls (",
|
|
629
|
-
message.tool_calls.length,
|
|
630
|
-
")"
|
|
631
|
-
] })]
|
|
632
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
633
|
-
style: {
|
|
634
|
-
...preStyle,
|
|
635
|
-
background: "#fff",
|
|
636
|
-
border: "1px solid #d9f7be",
|
|
637
|
-
maxHeight: "200px",
|
|
638
|
-
fontSize: "11px"
|
|
639
|
-
},
|
|
640
|
-
children: formatJson(message.tool_calls)
|
|
641
|
-
})]
|
|
642
|
-
})]
|
|
643
|
-
});
|
|
644
|
-
};
|
|
645
|
-
const buttonStyle = {
|
|
646
|
-
position: "fixed",
|
|
647
|
-
right: `${20 - buttonPos.x}px`,
|
|
648
|
-
bottom: `${20 - buttonPos.y}px`,
|
|
649
|
-
width: "48px",
|
|
650
|
-
height: "48px",
|
|
651
|
-
borderRadius: "50%",
|
|
652
|
-
background: "#1677ff",
|
|
653
|
-
color: "#fff",
|
|
654
|
-
border: "none",
|
|
655
|
-
cursor: isDraggingButton ? "grabbing" : "grab",
|
|
656
|
-
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
657
|
-
display: "flex",
|
|
658
|
-
alignItems: "center",
|
|
659
|
-
justifyContent: "center",
|
|
660
|
-
fontSize: "20px",
|
|
661
|
-
zIndex: 9998,
|
|
662
|
-
transition: isDraggingButton ? "none" : "box-shadow 0.2s",
|
|
663
|
-
userSelect: "none"
|
|
664
|
-
};
|
|
665
|
-
const dialogStyle = {
|
|
666
|
-
position: "fixed",
|
|
667
|
-
left: "50%",
|
|
668
|
-
top: "50%",
|
|
669
|
-
transform: `translate(calc(-50% + ${dialogPos.x}px), calc(-50% + ${dialogPos.y}px))`,
|
|
670
|
-
width: "1000px",
|
|
671
|
-
maxWidth: "90vw",
|
|
672
|
-
height: "650px",
|
|
673
|
-
maxHeight: "85vh",
|
|
674
|
-
background: "#fff",
|
|
675
|
-
borderRadius: "12px",
|
|
676
|
-
boxShadow: "0 8px 32px rgba(0, 0, 0, 0.2)",
|
|
677
|
-
zIndex: 9999,
|
|
678
|
-
display: "flex",
|
|
679
|
-
flexDirection: "column",
|
|
680
|
-
overflow: "hidden",
|
|
681
|
-
cursor: isDraggingDialog ? "grabbing" : "default"
|
|
682
|
-
};
|
|
683
|
-
const headerStyle = {
|
|
684
|
-
padding: "12px 16px",
|
|
685
|
-
background: "#f5f5f5",
|
|
686
|
-
borderBottom: "1px solid #e8e8e8",
|
|
687
|
-
display: "flex",
|
|
688
|
-
alignItems: "center",
|
|
689
|
-
justifyContent: "space-between",
|
|
690
|
-
cursor: isDraggingDialog ? "grabbing" : "grab"
|
|
691
|
-
};
|
|
692
|
-
const tabContainerStyle = {
|
|
693
|
-
display: "flex",
|
|
694
|
-
gap: "8px"
|
|
695
|
-
};
|
|
696
|
-
const getTabStyle = (isActive) => ({
|
|
697
|
-
padding: "6px 16px",
|
|
698
|
-
borderRadius: "6px",
|
|
699
|
-
border: "none",
|
|
700
|
-
background: isActive ? "#1677ff" : "transparent",
|
|
701
|
-
color: isActive ? "#fff" : "#666",
|
|
702
|
-
cursor: "pointer",
|
|
703
|
-
fontSize: "14px",
|
|
704
|
-
transition: "all 0.2s"
|
|
705
|
-
});
|
|
706
|
-
const closeButtonStyle = {
|
|
707
|
-
width: "28px",
|
|
708
|
-
height: "28px",
|
|
709
|
-
borderRadius: "50%",
|
|
710
|
-
border: "none",
|
|
711
|
-
background: "#ff4d4f",
|
|
712
|
-
color: "#fff",
|
|
713
|
-
cursor: "pointer",
|
|
714
|
-
display: "flex",
|
|
715
|
-
alignItems: "center",
|
|
716
|
-
justifyContent: "center",
|
|
717
|
-
fontSize: "16px",
|
|
718
|
-
transition: "background 0.2s"
|
|
719
|
-
};
|
|
720
|
-
const contentStyle = {
|
|
721
|
-
flex: 1,
|
|
722
|
-
overflow: "auto",
|
|
723
|
-
padding: "16px",
|
|
724
|
-
background: "#fafafa"
|
|
725
|
-
};
|
|
726
|
-
const preStyle = {
|
|
727
|
-
margin: 0,
|
|
728
|
-
padding: "12px",
|
|
729
|
-
background: "#f8f9fa",
|
|
730
|
-
color: "#333",
|
|
731
|
-
borderRadius: "8px",
|
|
732
|
-
fontSize: "12px",
|
|
733
|
-
fontFamily: "\"Fira Code\", \"Monaco\", \"Consolas\", monospace",
|
|
734
|
-
lineHeight: 1.5,
|
|
735
|
-
overflow: "auto",
|
|
736
|
-
whiteSpace: "pre-wrap",
|
|
737
|
-
wordBreak: "break-word",
|
|
738
|
-
border: "1px solid #e8e8e8"
|
|
739
|
-
};
|
|
740
|
-
const statsStyle = {
|
|
741
|
-
padding: "8px 12px",
|
|
742
|
-
background: "#e6f4ff",
|
|
743
|
-
borderRadius: "6px",
|
|
744
|
-
marginBottom: "12px",
|
|
745
|
-
fontSize: "13px",
|
|
746
|
-
color: "#0958d9"
|
|
747
|
-
};
|
|
748
|
-
const tableStyle = {
|
|
749
|
-
width: "100%",
|
|
750
|
-
borderCollapse: "collapse",
|
|
751
|
-
fontSize: "13px",
|
|
752
|
-
background: "#fff",
|
|
753
|
-
borderRadius: "8px",
|
|
754
|
-
overflow: "hidden",
|
|
755
|
-
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)"
|
|
756
|
-
};
|
|
757
|
-
const tableHeaderStyle = {
|
|
758
|
-
background: "#f5f5f5",
|
|
759
|
-
fontWeight: 600,
|
|
760
|
-
color: "#333",
|
|
761
|
-
textAlign: "left",
|
|
762
|
-
padding: "10px 12px",
|
|
763
|
-
borderBottom: "1px solid #e8e8e8",
|
|
764
|
-
whiteSpace: "nowrap"
|
|
765
|
-
};
|
|
766
|
-
const tableCellStyle = {
|
|
767
|
-
padding: "10px 12px",
|
|
768
|
-
borderBottom: "1px solid #f0f0f0",
|
|
769
|
-
verticalAlign: "top"
|
|
770
|
-
};
|
|
771
|
-
const expandButtonStyle = {
|
|
772
|
-
width: "20px",
|
|
773
|
-
height: "20px",
|
|
774
|
-
border: "none",
|
|
775
|
-
background: "transparent",
|
|
776
|
-
cursor: "pointer",
|
|
777
|
-
display: "flex",
|
|
778
|
-
alignItems: "center",
|
|
779
|
-
justifyContent: "center",
|
|
780
|
-
fontSize: "12px",
|
|
781
|
-
color: "#666",
|
|
782
|
-
borderRadius: "4px",
|
|
783
|
-
transition: "background 0.2s"
|
|
784
|
-
};
|
|
785
|
-
const expandedRowStyle = { background: "#fafafa" };
|
|
786
|
-
const jsonContainerStyle = {
|
|
787
|
-
padding: "12px",
|
|
788
|
-
background: "#fff",
|
|
789
|
-
borderRadius: "6px",
|
|
790
|
-
margin: "8px 0",
|
|
791
|
-
border: "1px solid #e8e8e8"
|
|
792
|
-
};
|
|
793
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
|
|
794
|
-
style: buttonStyle,
|
|
795
|
-
onMouseDown: handleButtonMouseDown,
|
|
796
|
-
onClick: () => !isDraggingButton && setIsOpen(true),
|
|
797
|
-
title: "打开调试面板",
|
|
798
|
-
children: "🐛"
|
|
799
|
-
}), isOpen && /* @__PURE__ */ jsxs("div", {
|
|
800
|
-
style: dialogStyle,
|
|
801
|
-
onMouseDown: handleDialogMouseDown,
|
|
802
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
803
|
-
className: "debug-panel-header",
|
|
804
|
-
style: headerStyle,
|
|
805
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
806
|
-
style: tabContainerStyle,
|
|
807
|
-
children: [/* @__PURE__ */ jsxs("button", {
|
|
808
|
-
style: getTabStyle(activeTab === "messages"),
|
|
809
|
-
onClick: () => setActiveTab("messages"),
|
|
810
|
-
children: [
|
|
811
|
-
"Messages (",
|
|
812
|
-
messages.length,
|
|
813
|
-
")"
|
|
814
|
-
]
|
|
815
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
816
|
-
style: getTabStyle(activeTab === "state"),
|
|
817
|
-
onClick: () => setActiveTab("state"),
|
|
818
|
-
children: "State"
|
|
819
|
-
})]
|
|
820
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
821
|
-
style: closeButtonStyle,
|
|
822
|
-
onClick: () => setIsOpen(false),
|
|
823
|
-
title: "关闭",
|
|
824
|
-
children: "×"
|
|
825
|
-
})]
|
|
826
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
827
|
-
style: contentStyle,
|
|
828
|
-
children: activeTab === "messages" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
829
|
-
style: statsStyle,
|
|
830
|
-
children: [
|
|
831
|
-
"共 ",
|
|
832
|
-
messages.length,
|
|
833
|
-
" 条消息"
|
|
834
|
-
]
|
|
835
|
-
}), /* @__PURE__ */ jsxs("table", {
|
|
836
|
-
style: tableStyle,
|
|
837
|
-
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
838
|
-
/* @__PURE__ */ jsx("th", { style: {
|
|
839
|
-
...tableHeaderStyle,
|
|
840
|
-
width: "30px"
|
|
841
|
-
} }),
|
|
842
|
-
/* @__PURE__ */ jsx("th", {
|
|
843
|
-
style: {
|
|
844
|
-
...tableHeaderStyle,
|
|
845
|
-
width: "60px"
|
|
846
|
-
},
|
|
847
|
-
children: "类型"
|
|
848
|
-
}),
|
|
849
|
-
/* @__PURE__ */ jsx("th", {
|
|
850
|
-
style: tableHeaderStyle,
|
|
851
|
-
children: "内容"
|
|
852
|
-
})
|
|
853
|
-
] }) }), /* @__PURE__ */ jsx("tbody", { children: messages.map((msg, index) => {
|
|
854
|
-
const message = msg;
|
|
855
|
-
const isExpanded = expandedRows.has(index);
|
|
856
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("tr", {
|
|
857
|
-
style: {
|
|
858
|
-
cursor: "pointer",
|
|
859
|
-
transition: "background 0.2s"
|
|
860
|
-
},
|
|
861
|
-
onClick: () => toggleRow(index),
|
|
862
|
-
onMouseEnter: (e) => {
|
|
863
|
-
e.currentTarget.style.background = "#f5f5f5";
|
|
864
|
-
},
|
|
865
|
-
onMouseLeave: (e) => {
|
|
866
|
-
e.currentTarget.style.background = "transparent";
|
|
867
|
-
},
|
|
868
|
-
children: [
|
|
869
|
-
/* @__PURE__ */ jsx("td", {
|
|
870
|
-
style: tableCellStyle,
|
|
871
|
-
children: /* @__PURE__ */ jsx("button", {
|
|
872
|
-
style: expandButtonStyle,
|
|
873
|
-
onClick: (e) => {
|
|
874
|
-
e.stopPropagation();
|
|
875
|
-
toggleRow(index);
|
|
876
|
-
},
|
|
877
|
-
children: isExpanded ? "▼" : "▶"
|
|
878
|
-
})
|
|
879
|
-
}),
|
|
880
|
-
/* @__PURE__ */ jsx("td", {
|
|
881
|
-
style: tableCellStyle,
|
|
882
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
883
|
-
style: getTypeTagStyle(message.type),
|
|
884
|
-
children: message.type || "unknown"
|
|
885
|
-
})
|
|
886
|
-
}),
|
|
887
|
-
/* @__PURE__ */ jsx("td", {
|
|
888
|
-
style: tableCellStyle,
|
|
889
|
-
children: renderMessageContent(message)
|
|
890
|
-
})
|
|
891
|
-
]
|
|
892
|
-
}, index), isExpanded && /* @__PURE__ */ jsx("tr", {
|
|
893
|
-
style: expandedRowStyle,
|
|
894
|
-
children: /* @__PURE__ */ jsx("td", {
|
|
895
|
-
colSpan: 3,
|
|
896
|
-
style: {
|
|
897
|
-
padding: 0,
|
|
898
|
-
borderBottom: "1px solid #e8e8e8"
|
|
899
|
-
},
|
|
900
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
901
|
-
style: jsonContainerStyle,
|
|
902
|
-
children: /* @__PURE__ */ jsx("pre", {
|
|
903
|
-
style: {
|
|
904
|
-
...preStyle,
|
|
905
|
-
margin: 0,
|
|
906
|
-
maxHeight: "300px",
|
|
907
|
-
overflow: "auto"
|
|
908
|
-
},
|
|
909
|
-
children: formatJson(message)
|
|
910
|
-
})
|
|
911
|
-
})
|
|
912
|
-
})
|
|
913
|
-
})] });
|
|
914
|
-
}) })]
|
|
915
|
-
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
916
|
-
style: statsStyle,
|
|
917
|
-
children: ["State 键数量: ", Object.keys(streamState).length]
|
|
918
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
919
|
-
style: preStyle,
|
|
920
|
-
children: formatJson(streamState)
|
|
921
|
-
})] })
|
|
922
|
-
})]
|
|
923
|
-
})] });
|
|
924
|
-
}
|
|
925
|
-
//#endregion
|
|
926
|
-
//#region src/hooks/useInterrupt.tsx
|
|
927
|
-
/**
|
|
928
|
-
* InterruptManager - 管理 Interrupt 状态的 Hook
|
|
929
|
-
*
|
|
930
|
-
* 封装 Interrupt 状态管理和处理逻辑,避免在 AgentChat 组件中臃肿
|
|
931
|
-
*/
|
|
932
|
-
function useInterrupt({ interrupt, config, onSubmit }) {
|
|
933
|
-
const [activeInterrupt, setActiveInterrupt] = useState(null);
|
|
934
|
-
const processedInterruptIdRef = useRef(null);
|
|
935
|
-
useEffect(() => {
|
|
936
|
-
if (interrupt) {
|
|
937
|
-
const interruptEvent = interrupt;
|
|
938
|
-
if (interruptEvent.id !== processedInterruptIdRef.current) {
|
|
939
|
-
processedInterruptIdRef.current = interruptEvent.id;
|
|
940
|
-
setActiveInterrupt(interruptEvent);
|
|
941
|
-
}
|
|
942
|
-
} else {
|
|
943
|
-
processedInterruptIdRef.current = null;
|
|
944
|
-
setActiveInterrupt(null);
|
|
945
|
-
}
|
|
946
|
-
}, [interrupt?.id]);
|
|
947
|
-
const handleResolveInterrupt = useCallback((response) => {
|
|
948
|
-
onSubmit(null, { command: { resume: response } });
|
|
949
|
-
setActiveInterrupt(null);
|
|
950
|
-
}, [onSubmit]);
|
|
951
|
-
return {
|
|
952
|
-
activeInterrupt,
|
|
953
|
-
handleResolveInterrupt,
|
|
954
|
-
renderInterrupt: useCallback(() => {
|
|
955
|
-
if (!activeInterrupt || !config?.render) return null;
|
|
956
|
-
return /* @__PURE__ */ jsx("div", {
|
|
957
|
-
className: "agent-chat-interrupt",
|
|
958
|
-
children: config.render({
|
|
959
|
-
event: activeInterrupt,
|
|
960
|
-
resolve: handleResolveInterrupt
|
|
961
|
-
})
|
|
962
|
-
});
|
|
963
|
-
}, [
|
|
964
|
-
activeInterrupt,
|
|
965
|
-
config,
|
|
966
|
-
handleResolveInterrupt
|
|
967
|
-
])
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
//#endregion
|
|
971
|
-
//#region src/hooks/useToolExecution.ts
|
|
972
|
-
/**
|
|
973
|
-
* useToolExecution - 管理前端工具执行的 Hook
|
|
974
|
-
*
|
|
975
|
-
* 职责:
|
|
976
|
-
* 1. 管理工具执行状态
|
|
977
|
-
* 2. 自动执行前端工具(避免重复执行)
|
|
978
|
-
* 3. 通知外部执行状态变化
|
|
979
|
-
* 4. 支持批量提交工具结果
|
|
980
|
-
*/
|
|
981
|
-
function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChange, onToolResultsBatch, completedToolResults }) {
|
|
982
|
-
const executedCallsRef = useRef(/* @__PURE__ */ new Set());
|
|
983
|
-
const executingCallsRef = useRef(/* @__PURE__ */ new Set());
|
|
984
|
-
const pendingNotifiedRef = useRef(/* @__PURE__ */ new Set());
|
|
985
|
-
const notifiedCompletedRef = useRef(/* @__PURE__ */ new Set());
|
|
986
|
-
const batchCallIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
987
|
-
const batchResultsRef = useRef(/* @__PURE__ */ new Map());
|
|
988
|
-
const isProcessingRef = useRef(false);
|
|
989
|
-
const batchSubmittedRef = useRef(false);
|
|
990
|
-
useEffect(() => {
|
|
991
|
-
if (!completedToolResults || completedToolResults.size === 0) return;
|
|
992
|
-
completedToolResults.forEach((result, callId) => {
|
|
993
|
-
if (notifiedCompletedRef.current.has(callId)) return;
|
|
994
|
-
notifiedCompletedRef.current.add(callId);
|
|
995
|
-
executedCallsRef.current.add(callId);
|
|
996
|
-
const call = toolCalls.find((c) => c.id === callId);
|
|
997
|
-
if (call) onExecutionChange?.({
|
|
998
|
-
callId,
|
|
999
|
-
name: call.name,
|
|
1000
|
-
args: call.args,
|
|
1001
|
-
status: "success",
|
|
1002
|
-
result
|
|
1003
|
-
});
|
|
502
|
+
}
|
|
503
|
+
//#endregion
|
|
504
|
+
//#region src/hooks/useToolExecution.ts
|
|
505
|
+
/**
|
|
506
|
+
* useToolExecution - 管理前端工具执行的 Hook
|
|
507
|
+
*
|
|
508
|
+
* 职责:
|
|
509
|
+
* 1. 管理工具执行状态
|
|
510
|
+
* 2. 自动执行前端工具(避免重复执行)
|
|
511
|
+
* 3. 通知外部执行状态变化
|
|
512
|
+
* 4. 支持批量提交工具结果
|
|
513
|
+
*/
|
|
514
|
+
function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChange, onToolResultsBatch, completedToolResults }) {
|
|
515
|
+
const executedCallsRef = useRef(/* @__PURE__ */ new Set());
|
|
516
|
+
const executingCallsRef = useRef(/* @__PURE__ */ new Set());
|
|
517
|
+
const pendingNotifiedRef = useRef(/* @__PURE__ */ new Set());
|
|
518
|
+
const notifiedCompletedRef = useRef(/* @__PURE__ */ new Set());
|
|
519
|
+
const batchCallIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
520
|
+
const batchResultsRef = useRef(/* @__PURE__ */ new Map());
|
|
521
|
+
const isProcessingRef = useRef(false);
|
|
522
|
+
const batchSubmittedRef = useRef(false);
|
|
523
|
+
useEffect(() => {
|
|
524
|
+
if (!completedToolResults || completedToolResults.size === 0) return;
|
|
525
|
+
completedToolResults.forEach((result, callId) => {
|
|
526
|
+
if (notifiedCompletedRef.current.has(callId)) return;
|
|
527
|
+
notifiedCompletedRef.current.add(callId);
|
|
528
|
+
executedCallsRef.current.add(callId);
|
|
529
|
+
const call = toolCalls.find((c) => c.id === callId);
|
|
530
|
+
if (call) onExecutionChange?.({
|
|
531
|
+
callId,
|
|
532
|
+
name: call.name,
|
|
533
|
+
args: call.args,
|
|
534
|
+
status: "success",
|
|
535
|
+
result
|
|
536
|
+
});
|
|
1004
537
|
});
|
|
1005
538
|
}, [completedToolResults, toolCalls]);
|
|
1006
539
|
/**
|
|
@@ -1349,35 +882,21 @@ function injectStyles() {
|
|
|
1349
882
|
//#endregion
|
|
1350
883
|
//#region src/components/AgentChat.tsx
|
|
1351
884
|
injectStyles();
|
|
1352
|
-
const AgentChat = forwardRef(({
|
|
885
|
+
const AgentChat = forwardRef(({ stream, className = "", tools, contexts, messageConfig, inputConfig, interruptConfig, agentState, welcome }, ref) => {
|
|
1353
886
|
const { onPreSend, ...chatInputConfig } = inputConfig || {};
|
|
1354
887
|
const chatInputRef = useRef(null);
|
|
1355
|
-
const stream = useStream({
|
|
1356
|
-
apiUrl,
|
|
1357
|
-
assistantId,
|
|
1358
|
-
threadId,
|
|
1359
|
-
onThreadId: (newThreadId) => {
|
|
1360
|
-
onThreadIdChange?.(newThreadId);
|
|
1361
|
-
},
|
|
1362
|
-
defaultHeaders: headers,
|
|
1363
|
-
messagesKey: "messages",
|
|
1364
|
-
onError: (error) => {
|
|
1365
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
1366
|
-
onError?.(err);
|
|
1367
|
-
}
|
|
1368
|
-
});
|
|
1369
888
|
useImperativeHandle(ref, () => ({
|
|
1370
889
|
input: chatInputRef.current,
|
|
1371
890
|
setSkill: (skill) => chatInputRef.current?.setSkill?.(skill),
|
|
1372
891
|
clearInput: () => chatInputRef.current?.clear?.(),
|
|
1373
|
-
focusInput: () => chatInputRef.current?.focus?.()
|
|
1374
|
-
stream
|
|
892
|
+
focusInput: () => chatInputRef.current?.focus?.()
|
|
1375
893
|
}));
|
|
1376
|
-
|
|
1377
|
-
if (stream.values && onAgentStateChange) onAgentStateChange(stream.values);
|
|
1378
|
-
}, [stream.values, onAgentStateChange]);
|
|
894
|
+
const interruptEvent = stream.interrupt;
|
|
1379
895
|
const { renderInterrupt: interruptRender } = useInterrupt({
|
|
1380
|
-
interrupt:
|
|
896
|
+
interrupt: interruptEvent ? {
|
|
897
|
+
value: interruptEvent.value,
|
|
898
|
+
id: interruptEvent.id
|
|
899
|
+
} : null,
|
|
1381
900
|
config: interruptConfig,
|
|
1382
901
|
onSubmit: stream.submit
|
|
1383
902
|
});
|
|
@@ -1469,55 +988,533 @@ const AgentChat = forwardRef(({ apiUrl, assistantId, headers, threadId, onThread
|
|
|
1469
988
|
const shouldRenderWelcome = messages.length === 0 && !isLoading && welcome;
|
|
1470
989
|
return /* @__PURE__ */ jsxs("div", {
|
|
1471
990
|
className: `agent-chat-container ${className}`,
|
|
1472
|
-
children: [
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
991
|
+
children: [shouldRenderWelcome ? /* @__PURE__ */ jsx("div", {
|
|
992
|
+
className: "agent-message-list agent-chat-welcome",
|
|
993
|
+
children: welcome
|
|
994
|
+
}) : /* @__PURE__ */ jsx(MessageList, {
|
|
995
|
+
messages,
|
|
996
|
+
isLoading: stream.isLoading,
|
|
997
|
+
tools,
|
|
998
|
+
toolExecutions,
|
|
999
|
+
components: messageConfig?.components,
|
|
1000
|
+
securityConfig: {
|
|
1001
|
+
allowedTags: messageConfig?.allowedTags,
|
|
1002
|
+
literalTagContent: messageConfig?.literalTagContent
|
|
1003
|
+
},
|
|
1004
|
+
loadingColor: messageConfig?.loadingColor,
|
|
1005
|
+
interruptRender
|
|
1006
|
+
}), /* @__PURE__ */ jsx(ChatInput, {
|
|
1007
|
+
ref: chatInputRef,
|
|
1008
|
+
onSend: handleSend,
|
|
1009
|
+
onStop: handleStop,
|
|
1010
|
+
isLoading,
|
|
1011
|
+
className: "agent-chat-input",
|
|
1012
|
+
...chatInputConfig
|
|
1013
|
+
})]
|
|
1014
|
+
});
|
|
1015
|
+
});
|
|
1016
|
+
AgentChat.displayName = "AgentChat";
|
|
1017
|
+
//#endregion
|
|
1018
|
+
//#region src/components/ToolCard.tsx
|
|
1019
|
+
/**
|
|
1020
|
+
* ToolCard 组件 - 用于展示工具调用结果
|
|
1021
|
+
* 样式:圆角矩形框,左侧 icon,label 分两行显示(prefix 小字体,content 默认字体)
|
|
1022
|
+
*/
|
|
1023
|
+
const ToolCard = ({ children, style, ...rest }) => {
|
|
1024
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(ThoughtChain.Item, {
|
|
1025
|
+
variant: "text",
|
|
1026
|
+
...rest,
|
|
1027
|
+
style: {
|
|
1028
|
+
paddingLeft: 0,
|
|
1029
|
+
...style
|
|
1030
|
+
}
|
|
1031
|
+
}), children] });
|
|
1032
|
+
};
|
|
1033
|
+
//#endregion
|
|
1034
|
+
//#region src/components/DebugPanel.tsx
|
|
1035
|
+
const isDevelopment = () => {
|
|
1036
|
+
if (typeof process !== "undefined" && process.env) return process.env.NODE_ENV === "development";
|
|
1037
|
+
const viteEnv = import.meta.env;
|
|
1038
|
+
if (typeof import.meta !== "undefined" && viteEnv) return viteEnv.DEV === true || viteEnv.MODE === "development";
|
|
1039
|
+
return false;
|
|
1040
|
+
};
|
|
1041
|
+
function DebugPanel({ streamState, visible = true }) {
|
|
1042
|
+
if (!isDevelopment() || !visible) return null;
|
|
1043
|
+
const streamMessages = streamState.messages || [];
|
|
1044
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1045
|
+
const [activeTab, setActiveTab] = useState("messages");
|
|
1046
|
+
const [expandedRows, setExpandedRows] = useState(/* @__PURE__ */ new Set());
|
|
1047
|
+
const [buttonPos, setButtonPos] = useState({
|
|
1048
|
+
x: 0,
|
|
1049
|
+
y: 0
|
|
1050
|
+
});
|
|
1051
|
+
const [isDraggingButton, setIsDraggingButton] = useState(false);
|
|
1052
|
+
const buttonDragRef = useRef(null);
|
|
1053
|
+
const [dialogPos, setDialogPos] = useState({
|
|
1054
|
+
x: 0,
|
|
1055
|
+
y: 0
|
|
1056
|
+
});
|
|
1057
|
+
const [isDraggingDialog, setIsDraggingDialog] = useState(false);
|
|
1058
|
+
const dialogDragRef = useRef(null);
|
|
1059
|
+
const handleButtonMouseDown = useCallback((e) => {
|
|
1060
|
+
e.preventDefault();
|
|
1061
|
+
buttonDragRef.current = {
|
|
1062
|
+
startX: e.clientX,
|
|
1063
|
+
startY: e.clientY,
|
|
1064
|
+
initialX: buttonPos.x,
|
|
1065
|
+
initialY: buttonPos.y
|
|
1066
|
+
};
|
|
1067
|
+
setIsDraggingButton(true);
|
|
1068
|
+
}, [buttonPos]);
|
|
1069
|
+
const handleDialogMouseDown = useCallback((e) => {
|
|
1070
|
+
if (!e.target.closest(".debug-panel-header")) return;
|
|
1071
|
+
e.preventDefault();
|
|
1072
|
+
dialogDragRef.current = {
|
|
1073
|
+
startX: e.clientX,
|
|
1074
|
+
startY: e.clientY,
|
|
1075
|
+
initialX: dialogPos.x,
|
|
1076
|
+
initialY: dialogPos.y
|
|
1077
|
+
};
|
|
1078
|
+
setIsDraggingDialog(true);
|
|
1079
|
+
}, [dialogPos]);
|
|
1080
|
+
useEffect(() => {
|
|
1081
|
+
const handleMouseMove = (e) => {
|
|
1082
|
+
if (isDraggingButton && buttonDragRef.current) {
|
|
1083
|
+
const dx = e.clientX - buttonDragRef.current.startX;
|
|
1084
|
+
const dy = e.clientY - buttonDragRef.current.startY;
|
|
1085
|
+
setButtonPos({
|
|
1086
|
+
x: buttonDragRef.current.initialX + dx,
|
|
1087
|
+
y: buttonDragRef.current.initialY + dy
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
if (isDraggingDialog && dialogDragRef.current) {
|
|
1091
|
+
const dx = e.clientX - dialogDragRef.current.startX;
|
|
1092
|
+
const dy = e.clientY - dialogDragRef.current.startY;
|
|
1093
|
+
setDialogPos({
|
|
1094
|
+
x: dialogDragRef.current.initialX + dx,
|
|
1095
|
+
y: dialogDragRef.current.initialY + dy
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
};
|
|
1099
|
+
const handleMouseUp = () => {
|
|
1100
|
+
setIsDraggingButton(false);
|
|
1101
|
+
setIsDraggingDialog(false);
|
|
1102
|
+
buttonDragRef.current = null;
|
|
1103
|
+
dialogDragRef.current = null;
|
|
1104
|
+
};
|
|
1105
|
+
if (isDraggingButton || isDraggingDialog) {
|
|
1106
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1107
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
1108
|
+
}
|
|
1109
|
+
return () => {
|
|
1110
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1111
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
1112
|
+
};
|
|
1113
|
+
}, [isDraggingButton, isDraggingDialog]);
|
|
1114
|
+
const formatJson = (data) => {
|
|
1115
|
+
try {
|
|
1116
|
+
return JSON.stringify(data, null, 2);
|
|
1117
|
+
} catch {
|
|
1118
|
+
return String(data);
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
const toggleRow = (index) => {
|
|
1122
|
+
setExpandedRows((prev) => {
|
|
1123
|
+
const next = new Set(prev);
|
|
1124
|
+
if (next.has(index)) next.delete(index);
|
|
1125
|
+
else next.add(index);
|
|
1126
|
+
return next;
|
|
1127
|
+
});
|
|
1128
|
+
};
|
|
1129
|
+
const getTypeTagStyle = (type) => {
|
|
1130
|
+
const color = {
|
|
1131
|
+
human: {
|
|
1132
|
+
bg: "#e6f4ff",
|
|
1133
|
+
color: "#0958d9"
|
|
1134
|
+
},
|
|
1135
|
+
ai: {
|
|
1136
|
+
bg: "#f6ffed",
|
|
1137
|
+
color: "#389e0d"
|
|
1138
|
+
},
|
|
1139
|
+
tool: {
|
|
1140
|
+
bg: "#fff7e6",
|
|
1141
|
+
color: "#d46b08"
|
|
1142
|
+
},
|
|
1143
|
+
system: {
|
|
1144
|
+
bg: "#f9f0ff",
|
|
1145
|
+
color: "#722ed1"
|
|
1146
|
+
},
|
|
1147
|
+
function: {
|
|
1148
|
+
bg: "#fff2f0",
|
|
1149
|
+
color: "#cf1322"
|
|
1150
|
+
}
|
|
1151
|
+
}[type || ""] || {
|
|
1152
|
+
bg: "#f5f5f5",
|
|
1153
|
+
color: "#666"
|
|
1154
|
+
};
|
|
1155
|
+
return {
|
|
1156
|
+
display: "inline-block",
|
|
1157
|
+
padding: "2px 8px",
|
|
1158
|
+
borderRadius: "4px",
|
|
1159
|
+
fontSize: "12px",
|
|
1160
|
+
fontWeight: 500,
|
|
1161
|
+
background: color.bg,
|
|
1162
|
+
color: color.color
|
|
1163
|
+
};
|
|
1164
|
+
};
|
|
1165
|
+
const formatContent = (content) => {
|
|
1166
|
+
if (!content) return "";
|
|
1167
|
+
if (Array.isArray(content)) return content.map((item) => typeof item === "string" ? item : JSON.stringify(item)).join("");
|
|
1168
|
+
return String(content);
|
|
1169
|
+
};
|
|
1170
|
+
const renderMessageContent = (message) => {
|
|
1171
|
+
const hasToolCalls = message.tool_calls && Array.isArray(message.tool_calls) && message.tool_calls.length > 0;
|
|
1172
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1173
|
+
style: {
|
|
1174
|
+
display: "flex",
|
|
1175
|
+
flexDirection: "column",
|
|
1176
|
+
gap: "8px"
|
|
1177
|
+
},
|
|
1178
|
+
children: [message.content && /* @__PURE__ */ jsx("div", {
|
|
1179
|
+
style: {
|
|
1180
|
+
color: "#333",
|
|
1181
|
+
lineHeight: 1.5,
|
|
1182
|
+
wordBreak: "break-all"
|
|
1485
1183
|
},
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1184
|
+
children: formatContent(message.content)
|
|
1185
|
+
}), hasToolCalls && /* @__PURE__ */ jsxs("div", {
|
|
1186
|
+
style: {
|
|
1187
|
+
marginTop: "4px",
|
|
1188
|
+
padding: "8px",
|
|
1189
|
+
background: "#f6ffed",
|
|
1190
|
+
border: "1px solid #b7eb8f",
|
|
1191
|
+
borderRadius: "6px"
|
|
1192
|
+
},
|
|
1193
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1194
|
+
style: {
|
|
1195
|
+
fontSize: "11px",
|
|
1196
|
+
fontWeight: 600,
|
|
1197
|
+
color: "#389e0d",
|
|
1198
|
+
marginBottom: "6px",
|
|
1199
|
+
display: "flex",
|
|
1200
|
+
alignItems: "center",
|
|
1201
|
+
gap: "4px"
|
|
1202
|
+
},
|
|
1203
|
+
children: [/* @__PURE__ */ jsx("span", { children: "🔧" }), /* @__PURE__ */ jsxs("span", { children: [
|
|
1204
|
+
"Tool Calls (",
|
|
1205
|
+
message.tool_calls.length,
|
|
1206
|
+
")"
|
|
1207
|
+
] })]
|
|
1208
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1209
|
+
style: {
|
|
1210
|
+
...preStyle,
|
|
1211
|
+
background: "#fff",
|
|
1212
|
+
border: "1px solid #d9f7be",
|
|
1213
|
+
maxHeight: "200px",
|
|
1214
|
+
fontSize: "11px"
|
|
1215
|
+
},
|
|
1216
|
+
children: formatJson(message.tool_calls)
|
|
1217
|
+
})]
|
|
1218
|
+
})]
|
|
1219
|
+
});
|
|
1220
|
+
};
|
|
1221
|
+
const buttonStyle = {
|
|
1222
|
+
position: "fixed",
|
|
1223
|
+
right: `${20 - buttonPos.x}px`,
|
|
1224
|
+
bottom: `${20 - buttonPos.y}px`,
|
|
1225
|
+
width: "48px",
|
|
1226
|
+
height: "48px",
|
|
1227
|
+
borderRadius: "50%",
|
|
1228
|
+
background: "#1677ff",
|
|
1229
|
+
color: "#fff",
|
|
1230
|
+
border: "none",
|
|
1231
|
+
cursor: isDraggingButton ? "grabbing" : "grab",
|
|
1232
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
1233
|
+
display: "flex",
|
|
1234
|
+
alignItems: "center",
|
|
1235
|
+
justifyContent: "center",
|
|
1236
|
+
fontSize: "20px",
|
|
1237
|
+
zIndex: 9998,
|
|
1238
|
+
transition: isDraggingButton ? "none" : "box-shadow 0.2s",
|
|
1239
|
+
userSelect: "none"
|
|
1240
|
+
};
|
|
1241
|
+
const dialogStyle = {
|
|
1242
|
+
position: "fixed",
|
|
1243
|
+
left: "50%",
|
|
1244
|
+
top: "50%",
|
|
1245
|
+
transform: `translate(calc(-50% + ${dialogPos.x}px), calc(-50% + ${dialogPos.y}px))`,
|
|
1246
|
+
width: "1000px",
|
|
1247
|
+
maxWidth: "90vw",
|
|
1248
|
+
height: "650px",
|
|
1249
|
+
maxHeight: "85vh",
|
|
1250
|
+
background: "#fff",
|
|
1251
|
+
borderRadius: "12px",
|
|
1252
|
+
boxShadow: "0 8px 32px rgba(0, 0, 0, 0.2)",
|
|
1253
|
+
zIndex: 9999,
|
|
1254
|
+
display: "flex",
|
|
1255
|
+
flexDirection: "column",
|
|
1256
|
+
overflow: "hidden",
|
|
1257
|
+
cursor: isDraggingDialog ? "grabbing" : "default"
|
|
1258
|
+
};
|
|
1259
|
+
const headerStyle = {
|
|
1260
|
+
padding: "12px 16px",
|
|
1261
|
+
background: "#f5f5f5",
|
|
1262
|
+
borderBottom: "1px solid #e8e8e8",
|
|
1263
|
+
display: "flex",
|
|
1264
|
+
alignItems: "center",
|
|
1265
|
+
justifyContent: "space-between",
|
|
1266
|
+
cursor: isDraggingDialog ? "grabbing" : "grab"
|
|
1267
|
+
};
|
|
1268
|
+
const tabContainerStyle = {
|
|
1269
|
+
display: "flex",
|
|
1270
|
+
gap: "8px"
|
|
1271
|
+
};
|
|
1272
|
+
const getTabStyle = (isActive) => ({
|
|
1273
|
+
padding: "6px 16px",
|
|
1274
|
+
borderRadius: "6px",
|
|
1275
|
+
border: "none",
|
|
1276
|
+
background: isActive ? "#1677ff" : "transparent",
|
|
1277
|
+
color: isActive ? "#fff" : "#666",
|
|
1278
|
+
cursor: "pointer",
|
|
1279
|
+
fontSize: "14px",
|
|
1280
|
+
transition: "all 0.2s"
|
|
1503
1281
|
});
|
|
1504
|
-
|
|
1505
|
-
|
|
1282
|
+
const closeButtonStyle = {
|
|
1283
|
+
width: "28px",
|
|
1284
|
+
height: "28px",
|
|
1285
|
+
borderRadius: "50%",
|
|
1286
|
+
border: "none",
|
|
1287
|
+
background: "#ff4d4f",
|
|
1288
|
+
color: "#fff",
|
|
1289
|
+
cursor: "pointer",
|
|
1290
|
+
display: "flex",
|
|
1291
|
+
alignItems: "center",
|
|
1292
|
+
justifyContent: "center",
|
|
1293
|
+
fontSize: "16px",
|
|
1294
|
+
transition: "background 0.2s"
|
|
1295
|
+
};
|
|
1296
|
+
const contentStyle = {
|
|
1297
|
+
flex: 1,
|
|
1298
|
+
overflow: "auto",
|
|
1299
|
+
padding: "16px",
|
|
1300
|
+
background: "#fafafa"
|
|
1301
|
+
};
|
|
1302
|
+
const preStyle = {
|
|
1303
|
+
margin: 0,
|
|
1304
|
+
padding: "12px",
|
|
1305
|
+
background: "#f8f9fa",
|
|
1306
|
+
color: "#333",
|
|
1307
|
+
borderRadius: "8px",
|
|
1308
|
+
fontSize: "12px",
|
|
1309
|
+
fontFamily: "\"Fira Code\", \"Monaco\", \"Consolas\", monospace",
|
|
1310
|
+
lineHeight: 1.5,
|
|
1311
|
+
overflow: "auto",
|
|
1312
|
+
whiteSpace: "pre-wrap",
|
|
1313
|
+
wordBreak: "break-word",
|
|
1314
|
+
border: "1px solid #e8e8e8"
|
|
1315
|
+
};
|
|
1316
|
+
const statsStyle = {
|
|
1317
|
+
padding: "8px 12px",
|
|
1318
|
+
background: "#e6f4ff",
|
|
1319
|
+
borderRadius: "6px",
|
|
1320
|
+
marginBottom: "12px",
|
|
1321
|
+
fontSize: "13px",
|
|
1322
|
+
color: "#0958d9"
|
|
1323
|
+
};
|
|
1324
|
+
const tableStyle = {
|
|
1325
|
+
width: "100%",
|
|
1326
|
+
borderCollapse: "collapse",
|
|
1327
|
+
fontSize: "13px",
|
|
1328
|
+
background: "#fff",
|
|
1329
|
+
borderRadius: "8px",
|
|
1330
|
+
overflow: "hidden",
|
|
1331
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)"
|
|
1332
|
+
};
|
|
1333
|
+
const tableHeaderStyle = {
|
|
1334
|
+
background: "#f5f5f5",
|
|
1335
|
+
fontWeight: 600,
|
|
1336
|
+
color: "#333",
|
|
1337
|
+
textAlign: "left",
|
|
1338
|
+
padding: "10px 12px",
|
|
1339
|
+
borderBottom: "1px solid #e8e8e8",
|
|
1340
|
+
whiteSpace: "nowrap"
|
|
1341
|
+
};
|
|
1342
|
+
const tableCellStyle = {
|
|
1343
|
+
padding: "10px 12px",
|
|
1344
|
+
borderBottom: "1px solid #f0f0f0",
|
|
1345
|
+
verticalAlign: "top"
|
|
1346
|
+
};
|
|
1347
|
+
const expandButtonStyle = {
|
|
1348
|
+
width: "20px",
|
|
1349
|
+
height: "20px",
|
|
1350
|
+
border: "none",
|
|
1351
|
+
background: "transparent",
|
|
1352
|
+
cursor: "pointer",
|
|
1353
|
+
display: "flex",
|
|
1354
|
+
alignItems: "center",
|
|
1355
|
+
justifyContent: "center",
|
|
1356
|
+
fontSize: "12px",
|
|
1357
|
+
color: "#666",
|
|
1358
|
+
borderRadius: "4px",
|
|
1359
|
+
transition: "background 0.2s"
|
|
1360
|
+
};
|
|
1361
|
+
const expandedRowStyle = { background: "#fafafa" };
|
|
1362
|
+
const jsonContainerStyle = {
|
|
1363
|
+
padding: "12px",
|
|
1364
|
+
background: "#fff",
|
|
1365
|
+
borderRadius: "6px",
|
|
1366
|
+
margin: "8px 0",
|
|
1367
|
+
border: "1px solid #e8e8e8"
|
|
1368
|
+
};
|
|
1369
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
|
|
1370
|
+
style: buttonStyle,
|
|
1371
|
+
onMouseDown: handleButtonMouseDown,
|
|
1372
|
+
onClick: () => !isDraggingButton && setIsOpen(true),
|
|
1373
|
+
title: "打开调试面板",
|
|
1374
|
+
children: "🐛"
|
|
1375
|
+
}), isOpen && /* @__PURE__ */ jsxs("div", {
|
|
1376
|
+
style: dialogStyle,
|
|
1377
|
+
onMouseDown: handleDialogMouseDown,
|
|
1378
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1379
|
+
className: "debug-panel-header",
|
|
1380
|
+
style: headerStyle,
|
|
1381
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1382
|
+
style: tabContainerStyle,
|
|
1383
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
1384
|
+
style: getTabStyle(activeTab === "messages"),
|
|
1385
|
+
onClick: () => setActiveTab("messages"),
|
|
1386
|
+
children: [
|
|
1387
|
+
"Messages (",
|
|
1388
|
+
streamMessages.length,
|
|
1389
|
+
")"
|
|
1390
|
+
]
|
|
1391
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
1392
|
+
style: getTabStyle(activeTab === "state"),
|
|
1393
|
+
onClick: () => setActiveTab("state"),
|
|
1394
|
+
children: "State"
|
|
1395
|
+
})]
|
|
1396
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
1397
|
+
style: closeButtonStyle,
|
|
1398
|
+
onClick: () => setIsOpen(false),
|
|
1399
|
+
title: "关闭",
|
|
1400
|
+
children: "×"
|
|
1401
|
+
})]
|
|
1402
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1403
|
+
style: contentStyle,
|
|
1404
|
+
children: activeTab === "messages" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
1405
|
+
style: statsStyle,
|
|
1406
|
+
children: [
|
|
1407
|
+
"共 ",
|
|
1408
|
+
streamMessages.length,
|
|
1409
|
+
" 条消息"
|
|
1410
|
+
]
|
|
1411
|
+
}), /* @__PURE__ */ jsxs("table", {
|
|
1412
|
+
style: tableStyle,
|
|
1413
|
+
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1414
|
+
/* @__PURE__ */ jsx("th", { style: {
|
|
1415
|
+
...tableHeaderStyle,
|
|
1416
|
+
width: "30px"
|
|
1417
|
+
} }),
|
|
1418
|
+
/* @__PURE__ */ jsx("th", {
|
|
1419
|
+
style: {
|
|
1420
|
+
...tableHeaderStyle,
|
|
1421
|
+
width: "60px"
|
|
1422
|
+
},
|
|
1423
|
+
children: "类型"
|
|
1424
|
+
}),
|
|
1425
|
+
/* @__PURE__ */ jsx("th", {
|
|
1426
|
+
style: tableHeaderStyle,
|
|
1427
|
+
children: "内容"
|
|
1428
|
+
})
|
|
1429
|
+
] }) }), /* @__PURE__ */ jsx("tbody", { children: streamMessages.map((msg, index) => {
|
|
1430
|
+
const message = msg;
|
|
1431
|
+
const isExpanded = expandedRows.has(index);
|
|
1432
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("tr", {
|
|
1433
|
+
style: {
|
|
1434
|
+
cursor: "pointer",
|
|
1435
|
+
transition: "background 0.2s"
|
|
1436
|
+
},
|
|
1437
|
+
onClick: () => toggleRow(index),
|
|
1438
|
+
onMouseEnter: (e) => {
|
|
1439
|
+
e.currentTarget.style.background = "#f5f5f5";
|
|
1440
|
+
},
|
|
1441
|
+
onMouseLeave: (e) => {
|
|
1442
|
+
e.currentTarget.style.background = "transparent";
|
|
1443
|
+
},
|
|
1444
|
+
children: [
|
|
1445
|
+
/* @__PURE__ */ jsx("td", {
|
|
1446
|
+
style: tableCellStyle,
|
|
1447
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
1448
|
+
style: expandButtonStyle,
|
|
1449
|
+
onClick: (e) => {
|
|
1450
|
+
e.stopPropagation();
|
|
1451
|
+
toggleRow(index);
|
|
1452
|
+
},
|
|
1453
|
+
children: isExpanded ? "▼" : "▶"
|
|
1454
|
+
})
|
|
1455
|
+
}),
|
|
1456
|
+
/* @__PURE__ */ jsx("td", {
|
|
1457
|
+
style: tableCellStyle,
|
|
1458
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
1459
|
+
style: getTypeTagStyle(message.type),
|
|
1460
|
+
children: message.type || "unknown"
|
|
1461
|
+
})
|
|
1462
|
+
}),
|
|
1463
|
+
/* @__PURE__ */ jsx("td", {
|
|
1464
|
+
style: tableCellStyle,
|
|
1465
|
+
children: renderMessageContent(message)
|
|
1466
|
+
})
|
|
1467
|
+
]
|
|
1468
|
+
}, index), isExpanded && /* @__PURE__ */ jsx("tr", {
|
|
1469
|
+
style: expandedRowStyle,
|
|
1470
|
+
children: /* @__PURE__ */ jsx("td", {
|
|
1471
|
+
colSpan: 3,
|
|
1472
|
+
style: {
|
|
1473
|
+
padding: 0,
|
|
1474
|
+
borderBottom: "1px solid #e8e8e8"
|
|
1475
|
+
},
|
|
1476
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1477
|
+
style: jsonContainerStyle,
|
|
1478
|
+
children: /* @__PURE__ */ jsx("pre", {
|
|
1479
|
+
style: {
|
|
1480
|
+
...preStyle,
|
|
1481
|
+
margin: 0,
|
|
1482
|
+
maxHeight: "300px",
|
|
1483
|
+
overflow: "auto"
|
|
1484
|
+
},
|
|
1485
|
+
children: formatJson(message)
|
|
1486
|
+
})
|
|
1487
|
+
})
|
|
1488
|
+
})
|
|
1489
|
+
})] });
|
|
1490
|
+
}) })]
|
|
1491
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
1492
|
+
style: statsStyle,
|
|
1493
|
+
children: ["State 键数量: ", Object.keys(streamState).length]
|
|
1494
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1495
|
+
style: preStyle,
|
|
1496
|
+
children: formatJson(streamState)
|
|
1497
|
+
})] })
|
|
1498
|
+
})]
|
|
1499
|
+
})] });
|
|
1500
|
+
}
|
|
1506
1501
|
//#endregion
|
|
1507
|
-
//#region src/
|
|
1502
|
+
//#region src/hooks/useAgentStream.ts
|
|
1508
1503
|
/**
|
|
1509
|
-
*
|
|
1510
|
-
*
|
|
1504
|
+
* 包装 useStream hook,为 AgentChat 提供统一的 stream 实例创建方式
|
|
1505
|
+
*
|
|
1506
|
+
* @example
|
|
1507
|
+
* ```tsx
|
|
1508
|
+
* const stream = useAgentStream({
|
|
1509
|
+
* apiUrl: "http://localhost:2026",
|
|
1510
|
+
* assistantId: "demo",
|
|
1511
|
+
* });
|
|
1512
|
+
*
|
|
1513
|
+
* <AgentChat stream={stream} />
|
|
1514
|
+
* ```
|
|
1511
1515
|
*/
|
|
1512
|
-
|
|
1513
|
-
return
|
|
1514
|
-
|
|
1515
|
-
...rest,
|
|
1516
|
-
style: {
|
|
1517
|
-
paddingLeft: 0,
|
|
1518
|
-
...style
|
|
1519
|
-
}
|
|
1520
|
-
}), children] });
|
|
1521
|
-
};
|
|
1516
|
+
function useAgentStream(options) {
|
|
1517
|
+
return useStream(options);
|
|
1518
|
+
}
|
|
1522
1519
|
//#endregion
|
|
1523
|
-
export { AgentChat, MessageContentRenderer, ToolCard };
|
|
1520
|
+
export { AgentChat, DebugPanel, MessageContentRenderer, ToolCard, useAgentStream };
|