141 lines
3.9 KiB
TypeScript
141 lines
3.9 KiB
TypeScript
import type { ElkNode } from 'elkjs/lib/elk-api';
|
|
|
|
export interface Edge {
|
|
id: string;
|
|
sources: string[];
|
|
targets: string[];
|
|
section?: any; // { startPoint: { x, y }, endPoint: { x,
|
|
}
|
|
|
|
export type Node = ElkNode & {
|
|
[key: string]: any;
|
|
};
|
|
|
|
export interface DiagramState {
|
|
nodes: Node[];
|
|
edges: Edge[];
|
|
selectedNodeId: string | null;
|
|
[key: string]: any;
|
|
}
|
|
|
|
export interface CanConnectResult {
|
|
canConnect: boolean;
|
|
reason?: string;
|
|
}
|
|
|
|
/**
|
|
* @description 判断两个节点是否可以连接
|
|
*/
|
|
export function invalidConnectionDetector(state: DiagramState, d: Node): CanConnectResult {
|
|
const from = state.selectedNodeId;
|
|
const to = d.id;
|
|
|
|
if (!from) {
|
|
return { canConnect: false, reason: '未选择起始节点' };
|
|
}
|
|
|
|
if (from === to) {
|
|
return { canConnect: false, reason: '不能连接到自身' };
|
|
}
|
|
|
|
// 建立邻接表
|
|
const adjacencyList: Record<string, Set<string>> = {};
|
|
state.edges.forEach(edge => {
|
|
const src = edge.sources[0];
|
|
const tgt = edge.targets[0];
|
|
if (!adjacencyList[src]) {
|
|
adjacencyList[src] = new Set();
|
|
}
|
|
adjacencyList[src].add(tgt);
|
|
});
|
|
|
|
// DFS 检测是否存在
|
|
function hasPath(current: string, target: string, visited: Set<string>): boolean {
|
|
if (current === target) return true;
|
|
visited.add(current);
|
|
const neighbors = adjacencyList[current] || new Set();
|
|
for (const neighbor of neighbors) {
|
|
if (!visited.has(neighbor)) {
|
|
if (hasPath(neighbor, target, visited)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (hasPath(to, from, new Set())) {
|
|
return { canConnect: false, reason: '连接会形成环路' };
|
|
}
|
|
|
|
if (hasPath(from, to, new Set())) {
|
|
return { canConnect: false, reason: '这是一个重复的连接' };
|
|
}
|
|
|
|
return {
|
|
canConnect: true
|
|
}
|
|
}
|
|
|
|
|
|
// export async function generateAIMockData(params: any) {
|
|
// if (!currentTool.value?.inputSchema) return;
|
|
// aiMockLoading.value = true;
|
|
// try {
|
|
// const loop = new TaskLoop({ maxEpochs: 1 });
|
|
// const usePrompt = prompt || `please call the tool ${currentTool.value.name} to make some test`;
|
|
// const chatStorage = {
|
|
// messages: [],
|
|
// settings: {
|
|
// temperature: 0.6,
|
|
// systemPrompt: '',
|
|
// enableTools: [{
|
|
// name: currentTool.value.name,
|
|
// description: currentTool.value.description,
|
|
// inputSchema: currentTool.value.inputSchema,
|
|
// enabled: true
|
|
// }],
|
|
// enableWebSearch: false,
|
|
// contextLength: 5,
|
|
// enableXmlWrapper: enableXmlWrapper.value,
|
|
// parallelToolCalls: false
|
|
// }
|
|
// } as ChatStorage;
|
|
|
|
// loop.setMaxEpochs(1);
|
|
|
|
// let aiMockJson: any = undefined;
|
|
|
|
// loop.registerOnToolCall(toolCall => {
|
|
// console.log(toolCall);
|
|
|
|
// if (toolCall.function?.name === currentTool.value?.name) {
|
|
// try {
|
|
// const toolArgs = JSON.parse(toolCall.function?.arguments || '{}');
|
|
// aiMockJson = toolArgs;
|
|
// } catch (e) {
|
|
// ElMessage.error('AI 生成的 JSON 解析错误');
|
|
// }
|
|
// } else {
|
|
// ElMessage.error('AI 调用了未知的工具');
|
|
// }
|
|
// loop.abort();
|
|
// return toolCall;
|
|
// });
|
|
|
|
// loop.registerOnError(error => {
|
|
// ElMessage.error(error + '');
|
|
// });
|
|
|
|
// await loop.start(chatStorage, usePrompt);
|
|
|
|
// if (aiMockJson && typeof aiMockJson === 'object') {
|
|
// Object.keys(aiMockJson).forEach(key => {
|
|
// tabStorage.formData[key] = aiMockJson[key];
|
|
// });
|
|
// formRef.value?.clearValidate?.();
|
|
// }
|
|
// } finally {
|
|
// aiMockLoading.value = false;
|
|
// }
|
|
// };
|