skilllite 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- skilllite/core/__init__.py +2 -0
- skilllite/core/adapters/__init__.py +74 -0
- skilllite/core/adapters/langchain.py +362 -0
- skilllite/core/adapters/llamaindex.py +264 -0
- skilllite/core/handler.py +179 -4
- skilllite/core/loops.py +175 -13
- skilllite/core/manager.py +82 -15
- skilllite/core/metadata.py +14 -7
- skilllite/core/security.py +420 -0
- skilllite/mcp/server.py +266 -58
- skilllite/quick.py +14 -4
- skilllite/sandbox/context.py +155 -0
- skilllite/sandbox/execution_service.py +254 -0
- skilllite/sandbox/skillbox/executor.py +124 -19
- skilllite/sandbox/unified_executor.py +359 -0
- {skilllite-0.1.1.dist-info → skilllite-0.1.2.dist-info}/METADATA +98 -1
- {skilllite-0.1.1.dist-info → skilllite-0.1.2.dist-info}/RECORD +21 -14
- {skilllite-0.1.1.dist-info → skilllite-0.1.2.dist-info}/WHEEL +0 -0
- {skilllite-0.1.1.dist-info → skilllite-0.1.2.dist-info}/entry_points.txt +0 -0
- {skilllite-0.1.1.dist-info → skilllite-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {skilllite-0.1.1.dist-info → skilllite-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LlamaIndex adapter for SkillLite.
|
|
3
|
+
|
|
4
|
+
Provides SkillLiteToolSpec for integrating SkillLite skills into LlamaIndex agents.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
from skilllite import SkillManager
|
|
8
|
+
from skilllite.core.adapters.llamaindex import SkillLiteToolSpec
|
|
9
|
+
|
|
10
|
+
manager = SkillManager(skills_dir="./skills")
|
|
11
|
+
tool_spec = SkillLiteToolSpec.from_manager(manager)
|
|
12
|
+
tools = tool_spec.to_tool_list()
|
|
13
|
+
|
|
14
|
+
# Use with LlamaIndex agent
|
|
15
|
+
from llama_index.core.agent import ReActAgent
|
|
16
|
+
agent = ReActAgent.from_tools(tools, llm=llm, verbose=True)
|
|
17
|
+
|
|
18
|
+
Security Confirmation:
|
|
19
|
+
For sandbox level 3, the adapter supports security confirmation callbacks:
|
|
20
|
+
|
|
21
|
+
def my_confirmation_callback(security_report: str, scan_id: str) -> bool:
|
|
22
|
+
print(security_report)
|
|
23
|
+
return input("Continue? [y/N]: ").lower() == 'y'
|
|
24
|
+
|
|
25
|
+
tool_spec = SkillLiteToolSpec.from_manager(
|
|
26
|
+
manager,
|
|
27
|
+
sandbox_level=3,
|
|
28
|
+
confirmation_callback=my_confirmation_callback
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
Requirements:
|
|
32
|
+
pip install skilllite[llamaindex]
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
from typing import Any, Callable, Dict, List, Optional, TYPE_CHECKING
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
from llama_index.core.tools import FunctionTool, ToolMetadata
|
|
39
|
+
from llama_index.core.tools.types import BaseTool as LlamaBaseTool
|
|
40
|
+
except ImportError as e:
|
|
41
|
+
raise ImportError(
|
|
42
|
+
"LlamaIndex adapter requires llama-index. "
|
|
43
|
+
"Install with: pip install skilllite[llamaindex]"
|
|
44
|
+
) from e
|
|
45
|
+
|
|
46
|
+
if TYPE_CHECKING:
|
|
47
|
+
from ..manager import SkillManager
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Type alias for confirmation callback
|
|
51
|
+
# Signature: (security_report: str, scan_id: str) -> bool
|
|
52
|
+
ConfirmationCallback = Callable[[str, str], bool]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Import SecurityScanResult from langchain adapter to share the implementation
|
|
56
|
+
# This avoids code duplication
|
|
57
|
+
try:
|
|
58
|
+
from .langchain import SecurityScanResult
|
|
59
|
+
except ImportError:
|
|
60
|
+
# Fallback: define a minimal SecurityScanResult if langchain adapter not available
|
|
61
|
+
from dataclasses import dataclass, field
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class SecurityScanResult:
|
|
65
|
+
"""Result of a security scan for LlamaIndex adapter."""
|
|
66
|
+
|
|
67
|
+
is_safe: bool
|
|
68
|
+
issues: List[Dict[str, Any]] = field(default_factory=list)
|
|
69
|
+
scan_id: str = ""
|
|
70
|
+
code_hash: str = ""
|
|
71
|
+
high_severity_count: int = 0
|
|
72
|
+
medium_severity_count: int = 0
|
|
73
|
+
low_severity_count: int = 0
|
|
74
|
+
timestamp: float = field(default_factory=time.time)
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def requires_confirmation(self) -> bool:
|
|
78
|
+
return self.high_severity_count > 0
|
|
79
|
+
|
|
80
|
+
def format_report(self) -> str:
|
|
81
|
+
if not self.issues:
|
|
82
|
+
return "✅ Security scan passed. No issues found."
|
|
83
|
+
|
|
84
|
+
lines = [
|
|
85
|
+
f"📋 Security Scan Report (ID: {self.scan_id[:8]})",
|
|
86
|
+
f" Found {len(self.issues)} item(s) for review:",
|
|
87
|
+
"",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
severity_icons = {"Critical": "🔴", "High": "🟠", "Medium": "🟡", "Low": "🟢"}
|
|
91
|
+
|
|
92
|
+
for idx, issue in enumerate(self.issues, 1):
|
|
93
|
+
severity = issue.get("severity", "Medium")
|
|
94
|
+
icon = severity_icons.get(severity, "⚪")
|
|
95
|
+
lines.append(f" {icon} #{idx} [{severity}] {issue.get('issue_type', 'Unknown')}")
|
|
96
|
+
lines.append(f" └─ {issue.get('description', '')}")
|
|
97
|
+
|
|
98
|
+
if self.high_severity_count > 0:
|
|
99
|
+
lines.append("\n⚠️ High severity issues found. Confirmation required.")
|
|
100
|
+
|
|
101
|
+
return "\n".join(lines)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class SkillLiteToolSpec:
|
|
105
|
+
"""
|
|
106
|
+
LlamaIndex ToolSpec for SkillLite.
|
|
107
|
+
|
|
108
|
+
Provides a way to create LlamaIndex tools from SkillLite skills.
|
|
109
|
+
|
|
110
|
+
Usage:
|
|
111
|
+
manager = SkillManager(skills_dir="./skills")
|
|
112
|
+
tool_spec = SkillLiteToolSpec.from_manager(manager)
|
|
113
|
+
tools = tool_spec.to_tool_list()
|
|
114
|
+
|
|
115
|
+
# Use with ReActAgent
|
|
116
|
+
agent = ReActAgent.from_tools(tools, llm=llm)
|
|
117
|
+
response = agent.chat("Your query")
|
|
118
|
+
|
|
119
|
+
Security Confirmation (sandbox_level=3):
|
|
120
|
+
def confirm(report: str, scan_id: str) -> bool:
|
|
121
|
+
print(report)
|
|
122
|
+
return input("Continue? [y/N]: ").lower() == 'y'
|
|
123
|
+
|
|
124
|
+
tool_spec = SkillLiteToolSpec.from_manager(
|
|
125
|
+
manager, sandbox_level=3, confirmation_callback=confirm
|
|
126
|
+
)
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
def __init__(
|
|
130
|
+
self,
|
|
131
|
+
manager: "SkillManager",
|
|
132
|
+
skill_names: Optional[List[str]] = None,
|
|
133
|
+
allow_network: bool = False,
|
|
134
|
+
timeout: Optional[int] = None,
|
|
135
|
+
sandbox_level: int = 3,
|
|
136
|
+
confirmation_callback: Optional[ConfirmationCallback] = None
|
|
137
|
+
):
|
|
138
|
+
"""
|
|
139
|
+
Initialize SkillLiteToolSpec.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
manager: SkillManager instance with registered skills
|
|
143
|
+
skill_names: Optional list of skill names to include (default: all)
|
|
144
|
+
allow_network: Whether to allow network access
|
|
145
|
+
timeout: Execution timeout in seconds
|
|
146
|
+
sandbox_level: Sandbox security level (1=no sandbox, 2=sandbox only, 3=sandbox+scan)
|
|
147
|
+
confirmation_callback: Callback for security confirmation (report, scan_id) -> bool
|
|
148
|
+
"""
|
|
149
|
+
self.manager = manager
|
|
150
|
+
self.skill_names = skill_names
|
|
151
|
+
self.allow_network = allow_network
|
|
152
|
+
self.timeout = timeout
|
|
153
|
+
self.sandbox_level = sandbox_level
|
|
154
|
+
self.confirmation_callback = confirmation_callback
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def from_manager(
|
|
158
|
+
cls,
|
|
159
|
+
manager: "SkillManager",
|
|
160
|
+
skill_names: Optional[List[str]] = None,
|
|
161
|
+
allow_network: bool = False,
|
|
162
|
+
timeout: Optional[int] = None,
|
|
163
|
+
sandbox_level: int = 3,
|
|
164
|
+
confirmation_callback: Optional[ConfirmationCallback] = None
|
|
165
|
+
) -> "SkillLiteToolSpec":
|
|
166
|
+
"""
|
|
167
|
+
Create a SkillLiteToolSpec from a SkillManager.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
manager: SkillManager instance
|
|
171
|
+
skill_names: Optional list of skill names to include
|
|
172
|
+
allow_network: Whether to allow network access
|
|
173
|
+
timeout: Execution timeout in seconds
|
|
174
|
+
sandbox_level: Sandbox security level (1/2/3, default: 3)
|
|
175
|
+
confirmation_callback: Callback for security confirmation
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
SkillLiteToolSpec instance
|
|
179
|
+
"""
|
|
180
|
+
return cls(
|
|
181
|
+
manager=manager,
|
|
182
|
+
skill_names=skill_names,
|
|
183
|
+
allow_network=allow_network,
|
|
184
|
+
timeout=timeout,
|
|
185
|
+
sandbox_level=sandbox_level,
|
|
186
|
+
confirmation_callback=confirmation_callback
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
def _create_skill_function(self, skill_name: str):
|
|
190
|
+
"""
|
|
191
|
+
Create a callable function for a skill using UnifiedExecutionService.
|
|
192
|
+
|
|
193
|
+
This method uses the unified execution layer which:
|
|
194
|
+
1. Reads sandbox level at runtime
|
|
195
|
+
2. Handles security scanning and confirmation
|
|
196
|
+
3. Properly downgrades sandbox level after confirmation
|
|
197
|
+
"""
|
|
198
|
+
def skill_fn(**kwargs) -> str:
|
|
199
|
+
try:
|
|
200
|
+
# Get skill info
|
|
201
|
+
skill_info = self.manager.get_skill(skill_name)
|
|
202
|
+
if not skill_info:
|
|
203
|
+
return f"Error: Skill '{skill_name}' not found"
|
|
204
|
+
|
|
205
|
+
# Use UnifiedExecutionService
|
|
206
|
+
from ...sandbox.execution_service import UnifiedExecutionService
|
|
207
|
+
|
|
208
|
+
service = UnifiedExecutionService.get_instance()
|
|
209
|
+
result = service.execute_skill(
|
|
210
|
+
skill_info=skill_info,
|
|
211
|
+
input_data=kwargs,
|
|
212
|
+
confirmation_callback=self.confirmation_callback,
|
|
213
|
+
allow_network=self.allow_network,
|
|
214
|
+
timeout=self.timeout,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
if result.success:
|
|
218
|
+
return result.output or "Execution completed successfully"
|
|
219
|
+
else:
|
|
220
|
+
return f"Error: {result.error}"
|
|
221
|
+
except Exception as e:
|
|
222
|
+
return f"Execution failed: {str(e)}"
|
|
223
|
+
|
|
224
|
+
return skill_fn
|
|
225
|
+
|
|
226
|
+
def to_tool_list(self) -> List[LlamaBaseTool]:
|
|
227
|
+
"""
|
|
228
|
+
Convert all skills to a list of LlamaIndex tools.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
List of FunctionTool instances
|
|
232
|
+
"""
|
|
233
|
+
tools = []
|
|
234
|
+
|
|
235
|
+
# Get executable skills
|
|
236
|
+
skills = self.manager.list_executable_skills()
|
|
237
|
+
|
|
238
|
+
for skill in skills:
|
|
239
|
+
# Filter by name if specified
|
|
240
|
+
if self.skill_names and skill.name not in self.skill_names:
|
|
241
|
+
continue
|
|
242
|
+
|
|
243
|
+
# Create function for this skill
|
|
244
|
+
fn = self._create_skill_function(skill.name)
|
|
245
|
+
|
|
246
|
+
# Create tool metadata
|
|
247
|
+
metadata = ToolMetadata(
|
|
248
|
+
name=skill.name,
|
|
249
|
+
description=skill.description or f"Execute the {skill.name} skill"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
# Create FunctionTool
|
|
253
|
+
tool = FunctionTool.from_defaults(
|
|
254
|
+
fn=fn,
|
|
255
|
+
name=skill.name,
|
|
256
|
+
description=skill.description or f"Execute the {skill.name} skill"
|
|
257
|
+
)
|
|
258
|
+
tools.append(tool)
|
|
259
|
+
|
|
260
|
+
return tools
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
__all__ = ["SkillLiteToolSpec", "SecurityScanResult", "ConfirmationCallback"]
|
|
264
|
+
|
skilllite/core/handler.py
CHANGED
|
@@ -5,16 +5,22 @@ This module handles:
|
|
|
5
5
|
- Parsing tool calls from LLM responses
|
|
6
6
|
- Executing tool calls
|
|
7
7
|
- Formatting tool results
|
|
8
|
+
|
|
9
|
+
Updated to support UnifiedExecutionService for consistent sandbox level handling.
|
|
8
10
|
"""
|
|
9
11
|
|
|
10
12
|
import json
|
|
11
|
-
from typing import Any, Dict, List, Optional, TYPE_CHECKING
|
|
13
|
+
from typing import Any, Callable, Dict, List, Optional, TYPE_CHECKING
|
|
12
14
|
|
|
13
15
|
from .executor import ExecutionResult, SkillExecutor
|
|
14
16
|
from .tools import ToolResult, ToolUseRequest
|
|
15
17
|
|
|
16
18
|
if TYPE_CHECKING:
|
|
17
19
|
from .registry import SkillRegistry
|
|
20
|
+
from ..sandbox.execution_service import UnifiedExecutionService
|
|
21
|
+
|
|
22
|
+
# Type alias for confirmation callback
|
|
23
|
+
ConfirmationCallback = Callable[[str, str], bool]
|
|
18
24
|
|
|
19
25
|
|
|
20
26
|
class ToolCallHandler:
|
|
@@ -95,7 +101,71 @@ class ToolCallHandler:
|
|
|
95
101
|
allow_network=allow_network,
|
|
96
102
|
timeout=timeout
|
|
97
103
|
)
|
|
98
|
-
|
|
104
|
+
|
|
105
|
+
def execute_with_unified_service(
|
|
106
|
+
self,
|
|
107
|
+
skill_name: str,
|
|
108
|
+
input_data: Dict[str, Any],
|
|
109
|
+
confirmation_callback: Optional[ConfirmationCallback] = None,
|
|
110
|
+
allow_network: Optional[bool] = None,
|
|
111
|
+
timeout: Optional[int] = None
|
|
112
|
+
) -> ExecutionResult:
|
|
113
|
+
"""
|
|
114
|
+
Execute a skill using the UnifiedExecutionService.
|
|
115
|
+
|
|
116
|
+
This method uses the unified execution layer which:
|
|
117
|
+
1. Reads sandbox level at runtime (not from instance variables)
|
|
118
|
+
2. Handles security scanning and confirmation
|
|
119
|
+
3. Properly downgrades sandbox level after confirmation
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
skill_name: Name of the skill or multi-script tool
|
|
123
|
+
input_data: Input data for the skill
|
|
124
|
+
confirmation_callback: Callback for security confirmation
|
|
125
|
+
allow_network: Whether to allow network access
|
|
126
|
+
timeout: Execution timeout in seconds
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
ExecutionResult with output or error
|
|
130
|
+
"""
|
|
131
|
+
from ..sandbox.execution_service import UnifiedExecutionService
|
|
132
|
+
|
|
133
|
+
service = UnifiedExecutionService.get_instance()
|
|
134
|
+
|
|
135
|
+
# Check if it's a multi-script tool
|
|
136
|
+
tool_info = self._registry.get_multi_script_tool_info(skill_name)
|
|
137
|
+
if tool_info:
|
|
138
|
+
parent_skill = self._registry.get_skill(tool_info["skill_name"])
|
|
139
|
+
if not parent_skill:
|
|
140
|
+
return ExecutionResult(
|
|
141
|
+
success=False,
|
|
142
|
+
error=f"Parent skill not found: {tool_info['skill_name']}"
|
|
143
|
+
)
|
|
144
|
+
return service.execute_skill(
|
|
145
|
+
skill_info=parent_skill,
|
|
146
|
+
input_data=input_data,
|
|
147
|
+
entry_point=tool_info["script_path"],
|
|
148
|
+
confirmation_callback=confirmation_callback,
|
|
149
|
+
allow_network=allow_network,
|
|
150
|
+
timeout=timeout,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Regular skill execution
|
|
154
|
+
info = self._registry.get_skill(skill_name)
|
|
155
|
+
if not info:
|
|
156
|
+
return ExecutionResult(
|
|
157
|
+
success=False,
|
|
158
|
+
error=f"Skill not found: {skill_name}"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
return service.execute_skill(
|
|
162
|
+
skill_info=info,
|
|
163
|
+
input_data=input_data,
|
|
164
|
+
confirmation_callback=confirmation_callback,
|
|
165
|
+
allow_network=allow_network,
|
|
166
|
+
timeout=timeout,
|
|
167
|
+
)
|
|
168
|
+
|
|
99
169
|
def execute_tool_call(
|
|
100
170
|
self,
|
|
101
171
|
request: ToolUseRequest,
|
|
@@ -130,7 +200,45 @@ class ToolCallHandler:
|
|
|
130
200
|
tool_use_id=request.id,
|
|
131
201
|
error=result.error or "Unknown error"
|
|
132
202
|
)
|
|
133
|
-
|
|
203
|
+
|
|
204
|
+
def execute_tool_call_with_unified_service(
|
|
205
|
+
self,
|
|
206
|
+
request: ToolUseRequest,
|
|
207
|
+
confirmation_callback: Optional[ConfirmationCallback] = None,
|
|
208
|
+
allow_network: Optional[bool] = None,
|
|
209
|
+
timeout: Optional[int] = None
|
|
210
|
+
) -> ToolResult:
|
|
211
|
+
"""
|
|
212
|
+
Execute a tool call using the UnifiedExecutionService.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
request: Tool use request from LLM
|
|
216
|
+
confirmation_callback: Callback for security confirmation
|
|
217
|
+
allow_network: Whether to allow network access
|
|
218
|
+
timeout: Execution timeout in seconds
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
ToolResult with success or error
|
|
222
|
+
"""
|
|
223
|
+
result = self.execute_with_unified_service(
|
|
224
|
+
skill_name=request.name,
|
|
225
|
+
input_data=request.input,
|
|
226
|
+
confirmation_callback=confirmation_callback,
|
|
227
|
+
allow_network=allow_network,
|
|
228
|
+
timeout=timeout
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
if result.success:
|
|
232
|
+
return ToolResult.success(
|
|
233
|
+
tool_use_id=request.id,
|
|
234
|
+
content=result.output
|
|
235
|
+
)
|
|
236
|
+
else:
|
|
237
|
+
return ToolResult.error(
|
|
238
|
+
tool_use_id=request.id,
|
|
239
|
+
error=result.error or "Unknown error"
|
|
240
|
+
)
|
|
241
|
+
|
|
134
242
|
# ==================== LLM Response Parsing ====================
|
|
135
243
|
|
|
136
244
|
def parse_tool_calls(self, response: Any) -> List[ToolUseRequest]:
|
|
@@ -186,7 +294,74 @@ class ToolCallHandler:
|
|
|
186
294
|
)
|
|
187
295
|
results.append(result)
|
|
188
296
|
return results
|
|
189
|
-
|
|
297
|
+
|
|
298
|
+
def handle_tool_calls_with_unified_service(
|
|
299
|
+
self,
|
|
300
|
+
response: Any,
|
|
301
|
+
confirmation_callback: Optional[ConfirmationCallback] = None,
|
|
302
|
+
allow_network: Optional[bool] = None,
|
|
303
|
+
timeout: Optional[int] = None
|
|
304
|
+
) -> List[ToolResult]:
|
|
305
|
+
"""
|
|
306
|
+
Parse and execute all tool calls using UnifiedExecutionService.
|
|
307
|
+
|
|
308
|
+
This method uses the unified execution layer which:
|
|
309
|
+
1. Reads sandbox level at runtime
|
|
310
|
+
2. Handles security scanning and confirmation per-skill
|
|
311
|
+
3. Properly downgrades sandbox level after confirmation
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
response: Response from OpenAI-compatible API
|
|
315
|
+
confirmation_callback: Callback for security confirmation
|
|
316
|
+
allow_network: Whether to allow network access
|
|
317
|
+
timeout: Execution timeout in seconds
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
List of ToolResult objects
|
|
321
|
+
"""
|
|
322
|
+
requests = self.parse_tool_calls(response)
|
|
323
|
+
results = []
|
|
324
|
+
for request in requests:
|
|
325
|
+
result = self.execute_tool_call_with_unified_service(
|
|
326
|
+
request,
|
|
327
|
+
confirmation_callback=confirmation_callback,
|
|
328
|
+
allow_network=allow_network,
|
|
329
|
+
timeout=timeout
|
|
330
|
+
)
|
|
331
|
+
results.append(result)
|
|
332
|
+
return results
|
|
333
|
+
|
|
334
|
+
def handle_tool_calls_claude_native_with_unified_service(
|
|
335
|
+
self,
|
|
336
|
+
response: Any,
|
|
337
|
+
confirmation_callback: Optional[ConfirmationCallback] = None,
|
|
338
|
+
allow_network: Optional[bool] = None,
|
|
339
|
+
timeout: Optional[int] = None
|
|
340
|
+
) -> List[ToolResult]:
|
|
341
|
+
"""
|
|
342
|
+
Parse and execute all Claude tool calls using UnifiedExecutionService.
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
response: Response from Claude's native API
|
|
346
|
+
confirmation_callback: Callback for security confirmation
|
|
347
|
+
allow_network: Whether to allow network access
|
|
348
|
+
timeout: Execution timeout in seconds
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
List of ToolResult objects
|
|
352
|
+
"""
|
|
353
|
+
requests = self.parse_tool_calls_claude_native(response)
|
|
354
|
+
results = []
|
|
355
|
+
for request in requests:
|
|
356
|
+
result = self.execute_tool_call_with_unified_service(
|
|
357
|
+
request,
|
|
358
|
+
confirmation_callback=confirmation_callback,
|
|
359
|
+
allow_network=allow_network,
|
|
360
|
+
timeout=timeout
|
|
361
|
+
)
|
|
362
|
+
results.append(result)
|
|
363
|
+
return results
|
|
364
|
+
|
|
190
365
|
def handle_tool_calls_claude_native(
|
|
191
366
|
self,
|
|
192
367
|
response: Any,
|