|
|
@@ -11,14 +11,23 @@ interface TopBarProps {
|
|
|
selectedNode: Goal | Message | null;
|
|
|
onTraceSelect: (traceId: string) => void;
|
|
|
onTraceCreated?: () => void;
|
|
|
+ onMessageInserted?: () => void;
|
|
|
}
|
|
|
|
|
|
-export const TopBar: FC<TopBarProps> = ({ selectedTraceId, selectedNode, onTraceSelect, onTraceCreated }) => {
|
|
|
+export const TopBar: FC<TopBarProps> = ({
|
|
|
+ selectedTraceId,
|
|
|
+ selectedNode,
|
|
|
+ onTraceSelect,
|
|
|
+ onTraceCreated,
|
|
|
+ onMessageInserted,
|
|
|
+}) => {
|
|
|
const [title, setTitle] = useState("流程图可视化系统");
|
|
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
|
|
+ const [isInsertModalVisible, setIsInsertModalVisible] = useState(false);
|
|
|
const [isExperienceModalVisible, setIsExperienceModalVisible] = useState(false);
|
|
|
const [experienceContent, setExperienceContent] = useState("");
|
|
|
const formApiRef = useRef<{ getValues: () => { system_prompt: string; user_prompt: string } } | null>(null);
|
|
|
+ const insertFormApiRef = useRef<{ getValues: () => { insert_prompt: string } } | null>(null);
|
|
|
|
|
|
const isMessageNode = (node: Goal | Message): node is Message =>
|
|
|
"message_id" in node || "role" in node || "content" in node || "goal_id" in node || "tokens" in node;
|
|
|
@@ -64,7 +73,15 @@ export const TopBar: FC<TopBarProps> = ({ selectedTraceId, selectedNode, onTrace
|
|
|
const values = formApiRef.current?.getValues();
|
|
|
if (!values) return;
|
|
|
|
|
|
- await traceApi.createTrace(values);
|
|
|
+ const messages: Array<{ role: "system" | "user"; content: string }> = [];
|
|
|
+ if (values.system_prompt) {
|
|
|
+ messages.push({ role: "system", content: values.system_prompt });
|
|
|
+ }
|
|
|
+ if (values.user_prompt) {
|
|
|
+ messages.push({ role: "user", content: values.user_prompt });
|
|
|
+ }
|
|
|
+
|
|
|
+ await traceApi.createTrace({ messages });
|
|
|
await loadTraces();
|
|
|
onTraceCreated?.();
|
|
|
setIsModalVisible(false);
|
|
|
@@ -75,9 +92,7 @@ export const TopBar: FC<TopBarProps> = ({ selectedTraceId, selectedNode, onTrace
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const handleRun = async () => {
|
|
|
- console.log("%c [ selectedNode ]-72", "font-size:13px; background:pink; color:#bf2c9f;", selectedNode);
|
|
|
-
|
|
|
+ const handleRun = () => {
|
|
|
if (!selectedNode) {
|
|
|
Toast.warning("请选择插入节点");
|
|
|
return;
|
|
|
@@ -88,18 +103,47 @@ export const TopBar: FC<TopBarProps> = ({ selectedTraceId, selectedNode, onTrace
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const messageId = getMessageId(selectedNode);
|
|
|
+ setIsInsertModalVisible(true);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleInsertConfirm = async () => {
|
|
|
+ const node = selectedNode;
|
|
|
+ if (!node) {
|
|
|
+ Toast.warning("请选择插入节点");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isMessageNode(node)) {
|
|
|
+ Toast.warning("插入位置错误");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const values = insertFormApiRef.current?.getValues();
|
|
|
+ const insertPrompt = values?.insert_prompt?.trim();
|
|
|
+ if (!insertPrompt) {
|
|
|
+ Toast.warning("请输入指令");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const messageId = getMessageId(node);
|
|
|
if (!messageId) {
|
|
|
Toast.error("消息ID缺失");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- await traceApi.runTrace(messageId);
|
|
|
- Toast.success("已开始运行");
|
|
|
+ const sequence = (node as Message & { sequence?: number }).sequence;
|
|
|
+ const payload = {
|
|
|
+ messages: [{ role: "user" as const, content: insertPrompt }],
|
|
|
+ after_sequence: typeof sequence === "number" ? sequence : undefined,
|
|
|
+ };
|
|
|
+ await traceApi.runTrace(messageId, payload);
|
|
|
+ Toast.success("插入成功");
|
|
|
+ setIsInsertModalVisible(false);
|
|
|
+ onMessageInserted?.();
|
|
|
} catch (error) {
|
|
|
console.error("Failed to run trace:", error);
|
|
|
- Toast.error("运行请求失败");
|
|
|
+ Toast.error("插入失败");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -164,7 +208,7 @@ export const TopBar: FC<TopBarProps> = ({ selectedTraceId, selectedNode, onTrace
|
|
|
className={styles.buttonPrimary}
|
|
|
onClick={handleRun}
|
|
|
>
|
|
|
- 运行
|
|
|
+ 插入
|
|
|
</button>
|
|
|
<button
|
|
|
className={styles.buttonDanger}
|
|
|
@@ -209,6 +253,24 @@ export const TopBar: FC<TopBarProps> = ({ selectedTraceId, selectedNode, onTrace
|
|
|
/>
|
|
|
</Form>
|
|
|
</Modal>
|
|
|
+ <Modal
|
|
|
+ title="插入指令"
|
|
|
+ visible={isInsertModalVisible}
|
|
|
+ onOk={handleInsertConfirm}
|
|
|
+ onCancel={() => setIsInsertModalVisible(false)}
|
|
|
+ centered
|
|
|
+ style={{ width: 600 }}
|
|
|
+ >
|
|
|
+ {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
|
|
|
+ <Form getFormApi={(api: any) => (insertFormApiRef.current = api)}>
|
|
|
+ <Form.TextArea
|
|
|
+ field="insert_prompt"
|
|
|
+ label="指令"
|
|
|
+ placeholder="请输入插入指令"
|
|
|
+ autosize={{ minRows: 3, maxRows: 6 }}
|
|
|
+ />
|
|
|
+ </Form>
|
|
|
+ </Modal>
|
|
|
<Modal
|
|
|
title="经验列表"
|
|
|
visible={isExperienceModalVisible}
|