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.
@@ -0,0 +1,359 @@
1
+ """
2
+ Unified Executor - Single source of truth for all skill execution.
3
+
4
+ This module provides the UnifiedExecutor class which handles all execution logic.
5
+ It uses ExecutionContext to get configuration at runtime, ensuring that any
6
+ changes to environment variables or context overrides are immediately reflected.
7
+
8
+ Key Design Principles:
9
+ 1. Never use instance variables for configuration
10
+ 2. Always read from ExecutionContext at execution time
11
+ 3. Single command building logic
12
+ 4. Single subprocess execution logic
13
+ """
14
+
15
+ import json
16
+ import os
17
+ import subprocess
18
+ from pathlib import Path
19
+ from typing import Any, Dict, List, Optional
20
+
21
+ from .base import ExecutionResult
22
+ from .context import ExecutionContext
23
+
24
+
25
+ class UnifiedExecutor:
26
+ """
27
+ Unified executor - all skill execution goes through this class.
28
+
29
+ This class is stateless regarding configuration. All configuration
30
+ comes from ExecutionContext passed to each method.
31
+ """
32
+
33
+ def __init__(self):
34
+ """Initialize the executor."""
35
+ from .skillbox import find_binary
36
+ self._binary_path = find_binary()
37
+ if not self._binary_path:
38
+ raise RuntimeError("skillbox binary not found")
39
+
40
+ @property
41
+ def binary_path(self) -> str:
42
+ """Path to the skillbox binary."""
43
+ return self._binary_path
44
+
45
+ @property
46
+ def is_available(self) -> bool:
47
+ """Check if skillbox is available."""
48
+ return self._binary_path is not None and os.path.exists(self._binary_path)
49
+
50
+ def execute(
51
+ self,
52
+ context: ExecutionContext,
53
+ skill_dir: Path,
54
+ input_data: Dict[str, Any],
55
+ entry_point: Optional[str] = None,
56
+ args: Optional[List[str]] = None,
57
+ ) -> ExecutionResult:
58
+ """
59
+ Execute a skill with the given context.
60
+
61
+ Args:
62
+ context: Execution context with all configuration
63
+ skill_dir: Path to the skill directory
64
+ input_data: Input data for the skill
65
+ entry_point: Optional specific script to execute
66
+ args: Optional command line arguments
67
+
68
+ Returns:
69
+ ExecutionResult with output or error
70
+ """
71
+ if entry_point:
72
+ return self.exec_script(
73
+ context=context,
74
+ skill_dir=skill_dir,
75
+ script_path=entry_point,
76
+ input_data=input_data,
77
+ args=args,
78
+ )
79
+
80
+ # Build command for skillbox run
81
+ cmd = self._build_run_command(context, skill_dir, input_data)
82
+ return self._run_subprocess(cmd, context, skill_dir)
83
+
84
+ def exec_script(
85
+ self,
86
+ context: ExecutionContext,
87
+ skill_dir: Path,
88
+ script_path: str,
89
+ input_data: Dict[str, Any],
90
+ args: Optional[List[str]] = None,
91
+ ) -> ExecutionResult:
92
+ """
93
+ Execute a specific script directly.
94
+
95
+ Args:
96
+ context: Execution context with all configuration
97
+ skill_dir: Path to the skill directory
98
+ script_path: Relative path to the script
99
+ input_data: Input data for the script
100
+ args: Optional command line arguments
101
+
102
+ Returns:
103
+ ExecutionResult with output or error
104
+ """
105
+ # Convert JSON input to CLI args if no explicit args provided
106
+ if args is None and input_data:
107
+ args = self._convert_json_to_cli_args(input_data)
108
+
109
+ # For Level 1/2 Python scripts, use direct execution for better performance
110
+ if script_path.endswith('.py') and context.sandbox_level != "3":
111
+ return self._exec_python_direct(context, skill_dir, script_path, args)
112
+
113
+ # Build command for skillbox exec
114
+ cmd = self._build_exec_command(context, skill_dir, script_path, input_data, args)
115
+ return self._run_subprocess(cmd, context, skill_dir)
116
+
117
+ def _build_run_command(
118
+ self,
119
+ context: ExecutionContext,
120
+ skill_dir: Path,
121
+ input_data: Dict[str, Any],
122
+ ) -> List[str]:
123
+ """Build command for skillbox run."""
124
+ # Convert to absolute path to avoid path issues
125
+ abs_skill_dir = Path(skill_dir).resolve()
126
+ cmd = [
127
+ self._binary_path,
128
+ "run",
129
+ str(abs_skill_dir),
130
+ json.dumps(input_data),
131
+ ]
132
+
133
+ # Add sandbox level from context (NOT from instance variable)
134
+ cmd.extend(["--sandbox-level", context.sandbox_level])
135
+
136
+ if context.allow_network:
137
+ cmd.append("--allow-network")
138
+
139
+ cmd.extend(["--timeout", str(context.timeout)])
140
+ cmd.extend(["--max-memory", str(context.max_memory_mb)])
141
+
142
+ return cmd
143
+
144
+ def _build_exec_command(
145
+ self,
146
+ context: ExecutionContext,
147
+ skill_dir: Path,
148
+ script_path: str,
149
+ input_data: Dict[str, Any],
150
+ args: Optional[List[str]] = None,
151
+ ) -> List[str]:
152
+ """Build command for skillbox exec."""
153
+ # Convert to absolute path to avoid path issues
154
+ abs_skill_dir = Path(skill_dir).resolve()
155
+ cmd = [
156
+ self._binary_path,
157
+ "exec",
158
+ str(abs_skill_dir),
159
+ script_path,
160
+ json.dumps(input_data),
161
+ ]
162
+
163
+ if args:
164
+ args_str = " ".join(args) if isinstance(args, list) else args
165
+ cmd.extend(["--args", args_str])
166
+
167
+ # Add sandbox level from context (NOT from instance variable)
168
+ cmd.extend(["--sandbox-level", context.sandbox_level])
169
+
170
+ if context.allow_network:
171
+ cmd.append("--allow-network")
172
+
173
+ cmd.extend(["--timeout", str(context.timeout)])
174
+ cmd.extend(["--max-memory", str(context.max_memory_mb)])
175
+
176
+ return cmd
177
+
178
+ def _run_subprocess(
179
+ self,
180
+ cmd: List[str],
181
+ context: ExecutionContext,
182
+ skill_dir: Path,
183
+ ) -> ExecutionResult:
184
+ """Run subprocess with the given command."""
185
+ env = self._build_env(context, skill_dir)
186
+
187
+ try:
188
+ if context.sandbox_level == "3" and not context.confirmed:
189
+ # Level 3 without confirmation: allow stderr for prompts
190
+ result = subprocess.run(
191
+ cmd,
192
+ stdin=None,
193
+ stdout=subprocess.PIPE,
194
+ stderr=None,
195
+ text=True,
196
+ timeout=context.timeout,
197
+ env=env,
198
+ )
199
+ return self._parse_output(result.stdout, "", result.returncode)
200
+ else:
201
+ # Level 1/2 or confirmed: capture all output
202
+ result = subprocess.run(
203
+ cmd,
204
+ capture_output=True,
205
+ text=True,
206
+ timeout=context.timeout,
207
+ env=env,
208
+ )
209
+ return self._parse_output(result.stdout, result.stderr, result.returncode)
210
+
211
+ except subprocess.TimeoutExpired:
212
+ return ExecutionResult(
213
+ success=False,
214
+ error=f"Execution timed out after {context.timeout} seconds",
215
+ exit_code=-1,
216
+ )
217
+ except FileNotFoundError:
218
+ return ExecutionResult(
219
+ success=False,
220
+ error=f"skillbox binary not found at: {self._binary_path}",
221
+ exit_code=-1,
222
+ )
223
+ except Exception as e:
224
+ return ExecutionResult(
225
+ success=False,
226
+ error=f"Execution failed: {str(e)}",
227
+ exit_code=-1,
228
+ )
229
+
230
+ def _build_env(
231
+ self,
232
+ context: ExecutionContext,
233
+ skill_dir: Path,
234
+ ) -> Dict[str, str]:
235
+ """Build environment variables for subprocess."""
236
+ env = os.environ.copy()
237
+
238
+ # Set sandbox level in environment (for consistency)
239
+ env["SKILLBOX_SANDBOX_LEVEL"] = context.sandbox_level
240
+ env["SKILLBOX_AUTO_APPROVE"] = "1" if context.auto_approve or context.confirmed else "1"
241
+
242
+ # Set skill-specific environment
243
+ env["SKILL_DIR"] = str(skill_dir)
244
+ env["SKILLBOX_TIMEOUT_SECS"] = str(context.timeout)
245
+ env["SKILLBOX_MAX_MEMORY_MB"] = str(context.max_memory_mb)
246
+
247
+ return env
248
+
249
+ def _exec_python_direct(
250
+ self,
251
+ context: ExecutionContext,
252
+ skill_dir: Path,
253
+ script_path: str,
254
+ args: Optional[List[str]] = None,
255
+ ) -> ExecutionResult:
256
+ """Execute Python script directly (for Level 1/2)."""
257
+ import sys
258
+
259
+ # Convert to absolute path to avoid path duplication issues
260
+ abs_skill_dir = Path(skill_dir).resolve()
261
+ full_script_path = abs_skill_dir / script_path
262
+
263
+ if not full_script_path.exists():
264
+ return ExecutionResult(
265
+ success=False,
266
+ error=f"Script not found: {full_script_path}",
267
+ exit_code=-1,
268
+ )
269
+
270
+ cmd = [sys.executable, str(full_script_path)]
271
+ if args:
272
+ cmd.extend(args)
273
+
274
+ env = self._build_env(context, abs_skill_dir)
275
+ env["PYTHONPATH"] = str(abs_skill_dir)
276
+
277
+ try:
278
+ # Don't set cwd to skill_dir - let scripts run from project root
279
+ # Scripts can use SKILL_DIR env var to find their own location
280
+ # This allows scripts like skill-creator to work with relative paths
281
+ # that are relative to the project root, not the skill directory
282
+ result = subprocess.run(
283
+ cmd,
284
+ capture_output=True,
285
+ text=True,
286
+ timeout=context.timeout,
287
+ env=env,
288
+ )
289
+ return self._parse_output(result.stdout, result.stderr, result.returncode)
290
+ except subprocess.TimeoutExpired:
291
+ return ExecutionResult(
292
+ success=False,
293
+ error=f"Execution timed out after {context.timeout} seconds",
294
+ exit_code=-1,
295
+ )
296
+ except Exception as e:
297
+ return ExecutionResult(
298
+ success=False,
299
+ error=f"Execution failed: {str(e)}",
300
+ exit_code=-1,
301
+ )
302
+
303
+ def _convert_json_to_cli_args(self, input_data: Dict[str, Any]) -> List[str]:
304
+ """Convert JSON input to CLI arguments.
305
+
306
+ Delegates to the shared utility function that properly handles
307
+ positional arguments like 'skill_name'.
308
+ """
309
+ from .utils import convert_json_to_cli_args
310
+ return convert_json_to_cli_args(input_data)
311
+
312
+ def _parse_output(
313
+ self,
314
+ stdout: str,
315
+ stderr: str,
316
+ returncode: int,
317
+ ) -> ExecutionResult:
318
+ """Parse subprocess output into ExecutionResult."""
319
+ combined = stdout + stderr
320
+
321
+ # Try to parse JSON output
322
+ try:
323
+ # Look for JSON in output
324
+ for line in combined.split('\n'):
325
+ line = line.strip()
326
+ if line.startswith('{') and line.endswith('}'):
327
+ data = json.loads(line)
328
+ if isinstance(data, dict):
329
+ return ExecutionResult(
330
+ success=returncode == 0,
331
+ output=data,
332
+ exit_code=returncode,
333
+ stdout=stdout,
334
+ stderr=stderr,
335
+ )
336
+ except json.JSONDecodeError:
337
+ pass
338
+
339
+ # Return as plain text
340
+ if returncode == 0:
341
+ return ExecutionResult(
342
+ success=True,
343
+ output={"result": stdout.strip()} if stdout.strip() else None,
344
+ exit_code=returncode,
345
+ stdout=stdout,
346
+ stderr=stderr,
347
+ )
348
+ else:
349
+ error_msg = stderr.strip() if stderr.strip() else stdout.strip()
350
+ return ExecutionResult(
351
+ success=False,
352
+ error=f"Skill execution failed with exit code {returncode}: {error_msg}",
353
+ exit_code=returncode,
354
+ stdout=stdout,
355
+ stderr=stderr,
356
+ )
357
+
358
+
359
+ __all__ = ["UnifiedExecutor"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skilllite
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A lightweight Skills execution engine with LLM integration for LLM agents
5
5
  Author-email: SkillLite Team <skilllite@example.com>
6
6
  License: MIT
@@ -32,10 +32,16 @@ Provides-Extra: anthropic
32
32
  Requires-Dist: anthropic>=0.18.0; extra == "anthropic"
33
33
  Provides-Extra: mcp
34
34
  Requires-Dist: mcp>=1.0.0; extra == "mcp"
35
+ Provides-Extra: langchain
36
+ Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
37
+ Provides-Extra: llamaindex
38
+ Requires-Dist: llama-index-core>=0.10.0; extra == "llamaindex"
35
39
  Provides-Extra: all
36
40
  Requires-Dist: openai>=1.0.0; extra == "all"
37
41
  Requires-Dist: anthropic>=0.18.0; extra == "all"
38
42
  Requires-Dist: mcp>=1.0.0; extra == "all"
43
+ Requires-Dist: langchain-core>=0.1.0; extra == "all"
44
+ Requires-Dist: llama-index-core>=0.10.0; extra == "all"
39
45
  Provides-Extra: dev
40
46
  Requires-Dist: pytest>=7.0; extra == "dev"
41
47
  Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
@@ -288,6 +294,97 @@ Enum for LLM provider formats:
288
294
  - `ToolFormat.CLAUDE`
289
295
  - `ToolFormat.OPENAI`
290
296
 
297
+ ## Framework Adapters
298
+
299
+ SkillLite provides adapters for popular AI frameworks with security confirmation support.
300
+
301
+ ### LangChain Integration
302
+
303
+ For LangChain/LangGraph integration, we recommend using the dedicated **[langchain-skilllite](https://pypi.org/project/langchain-skilllite/)** package:
304
+
305
+ ```bash
306
+ pip install langchain-skilllite
307
+ ```
308
+
309
+ ```python
310
+ from langchain_skilllite import SkillLiteToolkit
311
+ from langchain_openai import ChatOpenAI
312
+ from langgraph.prebuilt import create_react_agent
313
+
314
+ # Load all skills from a directory as LangChain tools
315
+ tools = SkillLiteToolkit.from_directory("./skills")
316
+
317
+ # Create a LangGraph agent
318
+ agent = create_react_agent(ChatOpenAI(model="gpt-4"), tools)
319
+
320
+ # Run the agent
321
+ result = agent.invoke({
322
+ "messages": [("user", "Convert 'hello world' to uppercase")]
323
+ })
324
+ ```
325
+
326
+ With security confirmation (sandbox_level=3):
327
+
328
+ ```python
329
+ def confirm_execution(report: str, scan_id: str) -> bool:
330
+ print(report)
331
+ return input("Continue? [y/N]: ").lower() == 'y'
332
+
333
+ tools = SkillLiteToolkit.from_directory(
334
+ "./skills",
335
+ sandbox_level=3, # 1=no sandbox, 2=sandbox only, 3=sandbox+scan
336
+ confirmation_callback=confirm_execution
337
+ )
338
+ ```
339
+
340
+ For more details, see the [langchain-skilllite documentation](../langchain-skilllite/README.md).
341
+
342
+ **Alternative**: You can also use the built-in adapter:
343
+
344
+ ```python
345
+ from skilllite import SkillManager
346
+ from skilllite.core.adapters.langchain import SkillLiteToolkit
347
+
348
+ manager = SkillManager(skills_dir="./skills")
349
+ tools = SkillLiteToolkit.from_manager(manager).get_tools()
350
+ ```
351
+
352
+ ### LlamaIndex Integration
353
+
354
+ ```python
355
+ from skilllite import SkillManager
356
+ from skilllite.core.adapters.llamaindex import SkillLiteToolSpec
357
+
358
+ manager = SkillManager(skills_dir="./skills")
359
+
360
+ # Basic usage
361
+ tool_spec = SkillLiteToolSpec.from_manager(manager)
362
+ tools = tool_spec.to_tool_list()
363
+
364
+ # With security confirmation
365
+ def confirm(report: str, scan_id: str) -> bool:
366
+ print(report)
367
+ return input("Continue? [y/N]: ").lower() == 'y'
368
+
369
+ tool_spec = SkillLiteToolSpec.from_manager(
370
+ manager,
371
+ sandbox_level=3,
372
+ confirmation_callback=confirm
373
+ )
374
+
375
+ # Use with LlamaIndex agent
376
+ from llama_index.core.agent import ReActAgent
377
+ agent = ReActAgent.from_tools(tools, llm=llm)
378
+ ```
379
+
380
+ ### Security Levels
381
+
382
+ | Level | Description |
383
+ |-------|-------------|
384
+ | 1 | No sandbox - direct execution |
385
+ | 2 | Sandbox isolation only |
386
+ | 3 | Sandbox + static security scan (requires confirmation for high-severity issues) |
387
+
291
388
  ## OpenCode Integration
292
389
 
293
390
  SkillLite can be integrated with [OpenCode](https://github.com/opencode-ai/opencode) as an MCP (Model Context Protocol) server, providing secure sandbox execution capabilities.
@@ -1,7 +1,7 @@
1
1
  skilllite/__init__.py,sha256=D_6otb8PNLUqpxlsp_7WtLJlX7JDziOxGBc8iQhER9Q,3984
2
2
  skilllite/analyzer.py,sha256=YG-ZJ6bO59pkP8LGECjcyCDPpH6wUYOm5QGx6et-ItA,14504
3
3
  skilllite/builtin_tools.py,sha256=MGIlMlYTfj590PCY4ngbQteDIryfH7sDoKQyrDTH6L8,8067
4
- skilllite/quick.py,sha256=TNqKaww92WHUMf9nkjMZkdVjzz222lOKyjCwNp90_9c,16132
4
+ skilllite/quick.py,sha256=_NWMBMywn0EK0dNeicbz37-M3UfnC7di3wjdBB0rPA4,16768
5
5
  skilllite/validation.py,sha256=K3Hn6VKT7aybdKX8GXSRaxLbKmyVAnMYmP9cqh-D4s4,4308
6
6
  skilllite/cli/__init__.py,sha256=PATRR5ZeAoB9H4gzVgw_5VAiP1GybZOuiAa1rOKFdW0,611
7
7
  skilllite/cli/__main__.py,sha256=69kpU78u45_64qSgv1v6x3m3xxaWjHwb-QdjbpxXZCo,152
@@ -10,29 +10,36 @@ skilllite/cli/main.py,sha256=cyLb6l7dDuvmu7ZCJhUsU9MeTzQo0qKLrnC75EKf5Sw,3983
10
10
  skilllite/cli/mcp.py,sha256=Kp-Z6aRZ7NB3T-y-b56jx6AnRyPOkfzfFQmBxYAB23Q,767
11
11
  skilllite/cli/integrations/__init__.py,sha256=-NWqUaDEPCRpykfDOvl2zfpUfLIH3UxG1qUbmTvb92o,120
12
12
  skilllite/cli/integrations/opencode.py,sha256=wT7rCqOkmX9GdhI994-0HhUtZEJ3PELPOC9PRscQDls,10521
13
- skilllite/core/__init__.py,sha256=nU9yWE_M7xuWaIa1Ks_0dPfilRpW9GhlKfTV6eEU7-U,2044
13
+ skilllite/core/__init__.py,sha256=N6ZEqHBnmnhtZksqVDayCZ0oPEM_rACRsGhzNm191tU,2089
14
14
  skilllite/core/executor.py,sha256=eNPcVKxKcLUjHJ7K2hstKtxobZiDIvPjk2IhbZv3nxo,6517
15
- skilllite/core/handler.py,sha256=pbQo5Gv-YSecufqpVbC0y8KP7Ra4uxxYpOW1nBimn5g,10354
16
- skilllite/core/loops.py,sha256=SQEhQolo2_yD3Vk5NAZ_3D1OPX0zpQ2N3SIIfay6Gao,32325
17
- skilllite/core/manager.py,sha256=uYAO5JtHM4DQvPnybBChHe0hUdOse1yBiQyc7vZ4nB8,19798
18
- skilllite/core/metadata.py,sha256=mdZdK-qfK7wSaZrAAn2U25k0I63NrYuibtBHIrYR5RA,11221
15
+ skilllite/core/handler.py,sha256=wVucut7ZfDxgCa3b6A99hxq-6OycRRQaMfGyBuxNMWk,16623
16
+ skilllite/core/loops.py,sha256=MVPMUOYgJT6VEvtAavB1PR-6kBh5kE7BlFE4ndBRgzE,39195
17
+ skilllite/core/manager.py,sha256=t87Qyql2YZQrUTiGAbI3q-8LF5Hiuy81HUvKCzwWtyQ,22451
18
+ skilllite/core/metadata.py,sha256=N-EOtPIRVM8sCAvvd75ogpqE3w2qIN-WKQ562mKHtPI,11607
19
19
  skilllite/core/prompt_builder.py,sha256=rsubLzien9lKjOqM6iTn5nourPnz1-QQGzljiO0Z_3I,12844
20
20
  skilllite/core/registry.py,sha256=AeljsV1uuYEJFGjpSwYxU6JGJ6EUuW8uNO3KirzHkuQ,6622
21
+ skilllite/core/security.py,sha256=Z91v4lltHDTJsk2tM1Ezu2TwjmZiWUqKlFKDABZEv2k,14185
21
22
  skilllite/core/skill_info.py,sha256=4_jsArmn1e7jEUXDEkmDAzjSI_903sdpfNLHOp1t1-M,6079
22
23
  skilllite/core/tool_builder.py,sha256=k28ze50h7AjBiEfgKR6Y4DUFIGZJ1sCYbHEk_VkYl7w,12866
23
24
  skilllite/core/tools.py,sha256=3RiAnZ_7S7iE6ZHXTPNKmAYQFY8SBUEzcQJZA0tZmX8,8168
25
+ skilllite/core/adapters/__init__.py,sha256=cvPkwBxRCyoNi4GWkAYwsoNuJqR-BdziLm83EEkBhio,2698
26
+ skilllite/core/adapters/langchain.py,sha256=osacceLNv3mo5x8Oe9obzefGpH1hhxhbXqMavSKAo5Y,13169
27
+ skilllite/core/adapters/llamaindex.py,sha256=El-oQxzniMv9rPVdH6udmzrzz_hE50rd1goVWxzib68,9037
24
28
  skilllite/mcp/__init__.py,sha256=xrpoWy9zs8IJkW6fkkR4XjQrITo5PWvFW9NkmK8E2Fg,1028
25
- skilllite/mcp/server.py,sha256=3s7pYHZY3785QS120C1O6cF1RnVfrteEkhAGbJwDMHw,38091
29
+ skilllite/mcp/server.py,sha256=VsdR36dF4YR3l5IUEsE7NfXd_zppy5J6egRVs_PhfSM,47934
26
30
  skilllite/sandbox/__init__.py,sha256=6LPisVXB94SJ-C34nBAxd05NGEZR4PPxz2xaDpX4qEk,918
27
31
  skilllite/sandbox/base.py,sha256=-Ul2QufoQ3myJNzBOEdv30A2HVSR9Oe4zEqpe9oJGqY,2628
28
32
  skilllite/sandbox/config.py,sha256=eA3ceou6jF4S5kptv6cmIGKynQTaGDx3_vRrkJGQaAE,8207
33
+ skilllite/sandbox/context.py,sha256=3C8Z3RiXJCcFI-Sx4nT9Dkf0d38BPzRTCsAbj-NODWc,5982
34
+ skilllite/sandbox/execution_service.py,sha256=vQERxKzRk4rc50qmuPQfR9OY62bybm3KH_Q-kuzCl8s,8937
35
+ skilllite/sandbox/unified_executor.py,sha256=4gSwTd1-EwLWSZ1dyM3eXauhyTd32vCkS6sVr6m3qYM,12229
29
36
  skilllite/sandbox/utils.py,sha256=o5AZVkhqIcZE9veUy7FTfN7uMHVWJJLYXs7gYIXsptg,2572
30
37
  skilllite/sandbox/skillbox/__init__.py,sha256=SFnNlLnnAc_NEEkqOkDbxYNfXROL7n1S09K_HFI_BOE,866
31
38
  skilllite/sandbox/skillbox/binary.py,sha256=TNKQamWucMw-J6L5BjAasNpYqhBcBpHwQPMqjUOkgp4,11838
32
- skilllite/sandbox/skillbox/executor.py,sha256=dXCR8JMwjD-x7-LfOCQbvgSq-29ZLIkXLp4oHed7b1Y,22872
33
- skilllite-0.1.1.dist-info/licenses/LICENSE,sha256=ESBZ3GI5LkrbA2s5jZUQDqdcQ8oRlmk04aIYh34cOsw,1071
34
- skilllite-0.1.1.dist-info/METADATA,sha256=EaYy1mJx-5zAmdE8ZlFbn4cbhKNKV0QG2tBclCu9BV0,9984
35
- skilllite-0.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
36
- skilllite-0.1.1.dist-info/entry_points.txt,sha256=H-meSKN3XzctxMvY6fa-YjAWyzs9t_0IjujOfumn4Wk,84
37
- skilllite-0.1.1.dist-info/top_level.txt,sha256=aqo-9FEJuBbFT7WGE3aycTj27OxyQPCN6TuZtOcClAI,10
38
- skilllite-0.1.1.dist-info/RECORD,,
39
+ skilllite/sandbox/skillbox/executor.py,sha256=xobVd5JmzJnwouVOO3arvN6IuC5VH28SXPqKHCXalHM,27175
40
+ skilllite-0.1.2.dist-info/licenses/LICENSE,sha256=ESBZ3GI5LkrbA2s5jZUQDqdcQ8oRlmk04aIYh34cOsw,1071
41
+ skilllite-0.1.2.dist-info/METADATA,sha256=A56Fqpe_U_BY5vls_YUSxnvqvYb4lunbyQRPaB1Gguc,12706
42
+ skilllite-0.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
43
+ skilllite-0.1.2.dist-info/entry_points.txt,sha256=H-meSKN3XzctxMvY6fa-YjAWyzs9t_0IjujOfumn4Wk,84
44
+ skilllite-0.1.2.dist-info/top_level.txt,sha256=aqo-9FEJuBbFT7WGE3aycTj27OxyQPCN6TuZtOcClAI,10
45
+ skilllite-0.1.2.dist-info/RECORD,,