-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpolicy.py
More file actions
93 lines (74 loc) · 3.41 KB
/
policy.py
File metadata and controls
93 lines (74 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
Pythonnet Tool Policy
Tool usage limits, deduplication, and tracking for Pythonnet (.NET) tools
"""
import json
from typing import Dict, Any, Type
class PythonnetToolPolicy:
"""Policy for Pythonnet tool usage control and tracking"""
@staticmethod
def get_policy() -> Type['PythonnetToolPolicy']:
"""Return policy class (interface requirement)"""
return PythonnetToolPolicy
@staticmethod
def get_policy_key(tool_name: str, tool_input: Dict[str, Any]) -> str:
"""
Generate deduplication key for tool call
Args:
tool_name: Tool name
tool_input: Tool input parameters
Returns:
Unique key for deduplication
"""
# For most tools, use tool name + main parameter
if tool_name == "pythonnet_load_binary":
binary_path = tool_input.get("binary_path", "")
return f"{tool_name}:{binary_path}"
elif tool_name == "pythonnet_decompile_method":
class_name = tool_input.get("class_name", "")
method_name = tool_input.get("method_name", "")
return f"{tool_name}:{class_name}.{method_name}"
elif tool_name == "pythonnet_decompile_class":
class_name = tool_input.get("class_name", "")
return f"{tool_name}:{class_name}"
elif tool_name == "pythonnet_list_all_methods_inside_class":
class_name = tool_input.get("class_name", "")
return f"{tool_name}:{class_name}"
elif tool_name == "pythonnet_rename_class":
class_name = tool_input.get("class_name", "")
new_name = tool_input.get("new_name", "")
return f"{tool_name}:{class_name}->{new_name}"
elif tool_name == "pythonnet_rename_method":
class_name = tool_input.get("class_name", "")
method_name = tool_input.get("method_name", "")
new_method_name = tool_input.get("new_method_name", "")
return f"{tool_name}:{class_name}.{method_name}->{new_method_name}"
elif tool_name in ("pythonnet_list_all_methods", "pythonnet_list_all_classes"):
# These have no parameters, just use tool name
return tool_name
else:
# Default: tool name + sorted JSON of inputs
input_str = json.dumps(tool_input, sort_keys=True)
return f"{tool_name}:{input_str}"
@staticmethod
def get_max_calls(tool_name: str, lock_clears: int = 0) -> int:
"""
Get maximum allowed calls for a tool
Args:
tool_name: Tool name
lock_clears: Number of times locks have been cleared (for progressive limits)
Returns:
Maximum number of calls allowed
"""
# Base limits
limits = {
"pythonnet_load_binary": 1, # Only load once
"pythonnet_list_all_classes": 3 + lock_clears, # Progressive
"pythonnet_list_all_methods": 3 + lock_clears, # Progressive
"pythonnet_list_all_methods_inside_class": 20 + (lock_clears * 5), # Progressive
"pythonnet_decompile_class": 50 + (lock_clears * 10), # Progressive (can be large)
"pythonnet_decompile_method": 999999, # Unlimited
"pythonnet_rename_class": 20 + lock_clears, # Progressive
"pythonnet_rename_method": 50 + (lock_clears * 10), # Progressive
}
return limits.get(tool_name, 50) # Default limit