MCPcopy Create free account
hub / github.com/ShipSecAI/studio / topoSort

Function topoSort

backend/src/dsl/compiler.ts:19–59  ·  view source on GitHub ↗
(nodes: string[], edges: { source: string; target: string }[])

Source from the content-addressed store, hash-verified

17import { validateWorkflowGraph } from './validator';
18
19function topoSort(nodes: string[], edges: { source: string; target: string }[]): string[] {
20 const incoming = new Map<string, number>();
21 const adjacency = new Map<string, string[]>();
22
23 nodes.forEach((id) => {
24 incoming.set(id, 0);
25 adjacency.set(id, []);
26 });
27
28 for (const edge of edges) {
29 if (!incoming.has(edge.target)) {
30 throw new Error(`Edge references unknown node ${edge.target}`);
31 }
32 if (!incoming.has(edge.source)) {
33 throw new Error(`Edge references unknown node ${edge.source}`);
34 }
35 incoming.set(edge.target, (incoming.get(edge.target) ?? 0) + 1);
36 adjacency.get(edge.source)?.push(edge.target);
37 }
38
39 const queue: string[] = nodes.filter((id) => (incoming.get(id) ?? 0) === 0);
40 const result: string[] = [];
41
42 while (queue.length > 0) {
43 const current = queue.shift()!;
44 result.push(current);
45
46 for (const neighbor of adjacency.get(current) ?? []) {
47 incoming.set(neighbor, (incoming.get(neighbor) ?? 1) - 1);
48 if ((incoming.get(neighbor) ?? 0) === 0) {
49 queue.push(neighbor);
50 }
51 }
52 }
53
54 if (result.length !== nodes.length) {
55 throw new Error('Workflow graph contains a cycle');
56 }
57
58 return result;
59}
60
61export function compileWorkflowGraph(graph: WorkflowGraphDto): WorkflowDefinition {
62 // Filter out UI-only nodes (like text-block) that shouldn't be executed

Callers 1

compileWorkflowGraphFunction · 0.85

Calls 4

hasMethod · 0.80
getMethod · 0.65
pushMethod · 0.65
setMethod · 0.45

Tested by

no test coverage detected