| 18 | |
| 19 | @dataclass(slots=True) |
| 20 | class WorkflowDefinition: |
| 21 | context: WorkflowContext |
| 22 | prompts: PromptBundle |
| 23 | tool_specs: list[ToolSpec] |
| 24 | nodes: NodeSet | None = None |
| 25 | edges: dict[str, list[str]] = field(default_factory=dict) |
| 26 | metadata: dict[str, Any] = field(default_factory=dict) |
| 27 | |
| 28 | def compile(self, llm: "BaseChatModel") -> Any: |
| 29 | try: |
| 30 | from langgraph.graph import END, START, StateGraph |
| 31 | except ImportError as exc: |
| 32 | raise RuntimeError( |
| 33 | "LangGraph is required to compile the workflow graph." |
| 34 | ) from exc |
| 35 | |
| 36 | self.nodes = build_nodes( |
| 37 | llm=llm, |
| 38 | prompts=self.prompts, |
| 39 | tool_specs=self.tool_specs, |
| 40 | context=self.context, |
| 41 | ) |
| 42 | |
| 43 | workflow = StateGraph(WorkflowState) |
| 44 | workflow.add_node("Scan", self.nodes.scan) |
| 45 | workflow.add_node("Inquire", self.nodes.inquire) |
| 46 | workflow.add_node("Exploit", self.nodes.exploit) |
| 47 | workflow.add_node("Vuln_select", self.nodes.vuln_select) |
| 48 | workflow.add_node("Check", self.nodes.check) |
| 49 | |
| 50 | workflow.add_conditional_edges("Scan", route_next, {"Vuln_select": "Vuln_select"}) |
| 51 | workflow.add_conditional_edges("Inquire", route_next, {"Exploit": "Exploit"}) |
| 52 | workflow.add_conditional_edges("Exploit", route_next, {"Check": "Check"}) |
| 53 | workflow.add_conditional_edges("Vuln_select", route_next, {"Inquire": "Inquire"}) |
| 54 | workflow.add_conditional_edges( |
| 55 | "Check", |
| 56 | route_next, |
| 57 | {"Vuln_select": "Vuln_select", "Exploit": "Exploit", "__end__": END}, |
| 58 | ) |
| 59 | workflow.add_edge(START, "Scan") |
| 60 | return workflow.compile(debug=self.context.debug_enabled()) |
| 61 | |
| 62 | |
| 63 | def build_workflow_definition( |
no outgoing calls
no test coverage detected