Initial commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
"""Tool planning helpers for Native Runtime V2."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from opc.layer4_tools.registry import ToolDefinition, ToolRegistry
|
||||
|
||||
|
||||
_READ_ONLY_TOOL_NAMES = {
|
||||
"file_read",
|
||||
"file_search",
|
||||
"list_dir",
|
||||
"grep",
|
||||
"glob",
|
||||
"web_search",
|
||||
"web_fetch",
|
||||
"todo_read",
|
||||
"agent_list",
|
||||
"agent_wait",
|
||||
}
|
||||
|
||||
_NON_CONCURRENT_TOOL_NAMES = {
|
||||
"shell_exec",
|
||||
"file_write",
|
||||
"file_edit",
|
||||
"apply_patch",
|
||||
"python_exec",
|
||||
"git_commit",
|
||||
"agent_spawn",
|
||||
"agent_wait",
|
||||
"agent_send",
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class ToolBatch:
|
||||
concurrency_safe: bool
|
||||
calls: list[dict[str, Any]]
|
||||
|
||||
|
||||
class ToolPlanner:
|
||||
"""Determine tool execution ordering and concurrency."""
|
||||
|
||||
def __init__(self, registry: ToolRegistry, max_parallel_read_tools: int = 6) -> None:
|
||||
self.registry = registry
|
||||
self.max_parallel_read_tools = max(1, int(max_parallel_read_tools or 1))
|
||||
|
||||
def is_read_only(self, tool: ToolDefinition | None) -> bool:
|
||||
if tool is None:
|
||||
return False
|
||||
if tool.read_only is not None:
|
||||
return bool(tool.read_only)
|
||||
if tool.name in _READ_ONLY_TOOL_NAMES:
|
||||
return True
|
||||
return tool.category in {"search", "read"} or tool.name.endswith("_read")
|
||||
|
||||
def is_concurrency_safe(self, tool: ToolDefinition | None) -> bool:
|
||||
if tool is None:
|
||||
return False
|
||||
if tool.concurrency_safe is not None:
|
||||
return bool(tool.concurrency_safe)
|
||||
if tool.name in _NON_CONCURRENT_TOOL_NAMES:
|
||||
return False
|
||||
return self.is_read_only(tool)
|
||||
|
||||
def partition(self, tool_calls: list[dict[str, Any]]) -> list[ToolBatch]:
|
||||
batches: list[ToolBatch] = []
|
||||
for call in tool_calls:
|
||||
tool = self.registry.get(str(call.get("function", "") or ""))
|
||||
concurrency_safe = self.is_concurrency_safe(tool)
|
||||
if concurrency_safe and batches and batches[-1].concurrency_safe:
|
||||
batches[-1].calls.append(call)
|
||||
else:
|
||||
batches.append(ToolBatch(concurrency_safe=concurrency_safe, calls=[call]))
|
||||
return batches
|
||||
Reference in New Issue
Block a user