skilllite 0.1.0__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,137 @@
1
+ """
2
+ Validation utilities for Agent Skills specification.
3
+
4
+ This module provides validation functions for skill names and descriptions
5
+ according to the Skills specification.
6
+ """
7
+
8
+ import re
9
+ import warnings
10
+ from pathlib import Path
11
+ from typing import List, Optional, Tuple
12
+
13
+
14
+ class SkillNameValidationError(ValueError):
15
+ """Raised when skill name doesn't conform to Agent Skills specification."""
16
+ pass
17
+
18
+
19
+ class SkillNameValidationWarning(UserWarning):
20
+ """Warning for skill name validation issues."""
21
+ pass
22
+
23
+
24
+ def validate_skill_name(name: str, skill_dir: Optional[Path] = None) -> Tuple[bool, List[str]]:
25
+ """
26
+ Validate skill name according to Agent Skills specification.
27
+
28
+ Rules from Skills specification:
29
+ - Must be 1-64 characters
30
+ - May only contain lowercase alphanumeric characters and hyphens (a-z, 0-9, -)
31
+ - Must not start or end with hyphen (-)
32
+ - Must not contain consecutive hyphens (--)
33
+ - Must match the parent directory name (if skill_dir provided)
34
+
35
+ Args:
36
+ name: The skill name to validate
37
+ skill_dir: Optional path to skill directory for directory name matching
38
+
39
+ Returns:
40
+ Tuple of (is_valid, list_of_errors)
41
+ """
42
+ errors = []
43
+
44
+ # Check length
45
+ if not name:
46
+ errors.append("Skill name cannot be empty")
47
+ elif len(name) > 64:
48
+ errors.append(f"Skill name exceeds 64 characters (got {len(name)})")
49
+
50
+ # Check character set (lowercase alphanumeric and hyphens only)
51
+ if name and not re.match(r'^[a-z0-9-]+$', name):
52
+ invalid_chars = set(re.findall(r'[^a-z0-9-]', name))
53
+ if any(c.isupper() for c in name):
54
+ errors.append("Skill name must be lowercase (found uppercase characters)")
55
+ else:
56
+ errors.append(f"Skill name contains invalid characters: {invalid_chars}")
57
+
58
+ # Check hyphen rules
59
+ if name:
60
+ if name.startswith('-'):
61
+ errors.append("Skill name must not start with a hyphen")
62
+ if name.endswith('-'):
63
+ errors.append("Skill name must not end with a hyphen")
64
+ if '--' in name:
65
+ errors.append("Skill name must not contain consecutive hyphens (--)")
66
+
67
+ # Check directory name match
68
+ if skill_dir and name:
69
+ dir_name = skill_dir.name
70
+ if dir_name != name:
71
+ errors.append(f"Skill name '{name}' must match directory name '{dir_name}'")
72
+
73
+ return len(errors) == 0, errors
74
+
75
+
76
+ def validate_skill_name_strict(name: str, skill_dir: Optional[Path] = None) -> None:
77
+ """
78
+ Validate skill name and raise exception if invalid.
79
+
80
+ Args:
81
+ name: The skill name to validate
82
+ skill_dir: Optional path to skill directory
83
+
84
+ Raises:
85
+ SkillNameValidationError: If name is invalid
86
+ """
87
+ is_valid, errors = validate_skill_name(name, skill_dir)
88
+ if not is_valid:
89
+ raise SkillNameValidationError(
90
+ f"Invalid skill name '{name}': " + "; ".join(errors)
91
+ )
92
+
93
+
94
+ def validate_skill_name_warn(name: str, skill_dir: Optional[Path] = None) -> bool:
95
+ """
96
+ Validate skill name and emit warnings if invalid.
97
+
98
+ Args:
99
+ name: The skill name to validate
100
+ skill_dir: Optional path to skill directory
101
+
102
+ Returns:
103
+ True if valid, False otherwise (with warnings emitted)
104
+ """
105
+ is_valid, errors = validate_skill_name(name, skill_dir)
106
+ if not is_valid:
107
+ for error in errors:
108
+ warnings.warn(
109
+ f"Skill name validation: {error}",
110
+ SkillNameValidationWarning,
111
+ stacklevel=3
112
+ )
113
+ return is_valid
114
+
115
+
116
+ def validate_description(description: Optional[str]) -> Tuple[bool, List[str]]:
117
+ """
118
+ Validate skill description according to Agent Skills specification.
119
+
120
+ Rules:
121
+ - Must be 1-1024 characters
122
+ - Should describe what the skill does and when to use it
123
+
124
+ Args:
125
+ description: The skill description to validate
126
+
127
+ Returns:
128
+ Tuple of (is_valid, list_of_errors)
129
+ """
130
+ errors = []
131
+
132
+ if not description:
133
+ errors.append("Skill description is required")
134
+ elif len(description) > 1024:
135
+ errors.append(f"Skill description exceeds 1024 characters (got {len(description)})")
136
+
137
+ return len(errors) == 0, errors
@@ -0,0 +1,293 @@
1
+ Metadata-Version: 2.4
2
+ Name: skilllite
3
+ Version: 0.1.0
4
+ Summary: A lightweight Skills execution engine with LLM integration for LLM agents
5
+ Author-email: SkillLite Team <skilllite@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/EXboys/skilllite
8
+ Project-URL: Documentation, https://github.com/EXboys/skilllite#readme
9
+ Project-URL: Repository, https://github.com/EXboys/skilllite
10
+ Project-URL: Issues, https://github.com/EXboys/skilllite/issues
11
+ Keywords: agent,skills,llm,claude,openai,sandbox,tools
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: pyyaml>=6.0
29
+ Provides-Extra: openai
30
+ Requires-Dist: openai>=1.0.0; extra == "openai"
31
+ Provides-Extra: anthropic
32
+ Requires-Dist: anthropic>=0.18.0; extra == "anthropic"
33
+ Provides-Extra: mcp
34
+ Requires-Dist: mcp>=1.0.0; extra == "mcp"
35
+ Provides-Extra: all
36
+ Requires-Dist: openai>=1.0.0; extra == "all"
37
+ Requires-Dist: anthropic>=0.18.0; extra == "all"
38
+ Requires-Dist: mcp>=1.0.0; extra == "all"
39
+ Provides-Extra: dev
40
+ Requires-Dist: pytest>=7.0; extra == "dev"
41
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
42
+ Requires-Dist: black>=23.0; extra == "dev"
43
+ Requires-Dist: mypy>=1.0; extra == "dev"
44
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # SkillLite Python SDK
48
+
49
+ A Python SDK for the SkillLite execution engine, using **OpenAI-compatible API format** as the unified interface.
50
+
51
+ ## Supported Providers
52
+
53
+ Works with any OpenAI-compatible LLM provider:
54
+ - **OpenAI** (GPT-4, GPT-3.5, etc.)
55
+ - **Azure OpenAI**
56
+ - **Anthropic Claude** (via OpenAI-compatible endpoint or native)
57
+ - **Google Gemini** (via OpenAI-compatible endpoint)
58
+ - **Local models** (Ollama, vLLM, LMStudio, etc.)
59
+ - **DeepSeek, Qwen, Moonshot, Zhipu**, and other providers
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install skilllite
65
+
66
+ # With OpenAI SDK (recommended, works with all compatible providers)
67
+ pip install skilllite[openai]
68
+
69
+ # With Anthropic SDK (for Claude's native API)
70
+ pip install skilllite[anthropic]
71
+ ```
72
+
73
+ ## Prerequisites
74
+
75
+ You need to have the `skillbox` binary installed:
76
+
77
+ ```bash
78
+ # From the skillbox directory
79
+ cargo install --path .
80
+ ```
81
+
82
+ ## Quick Start
83
+
84
+ ### Basic Usage (Universal - Works with Any Provider)
85
+
86
+ ```python
87
+ from openai import OpenAI
88
+ from skilllite import SkillManager
89
+
90
+ # Works with ANY OpenAI-compatible provider
91
+ # Just change base_url and api_key for different providers:
92
+
93
+ # OpenAI
94
+ client = OpenAI()
95
+
96
+ # Ollama (local)
97
+ # client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
98
+
99
+ # DeepSeek
100
+ # client = OpenAI(base_url="https://api.deepseek.com/v1", api_key="...")
101
+
102
+ # Qwen (通义千问)
103
+ # client = OpenAI(base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="...")
104
+
105
+ # Moonshot (月之暗面)
106
+ # client = OpenAI(base_url="https://api.moonshot.cn/v1", api_key="...")
107
+
108
+ # Initialize SkillManager
109
+ manager = SkillManager(skills_dir="./my_skills")
110
+
111
+ # Get tools (OpenAI-compatible format - works with all providers)
112
+ tools = manager.get_tools()
113
+
114
+ # Call any OpenAI-compatible API
115
+ response = client.chat.completions.create(
116
+ model="gpt-4", # or "llama2", "deepseek-chat", "qwen-turbo", etc.
117
+ tools=tools,
118
+ messages=[{"role": "user", "content": "Please help me with..."}]
119
+ )
120
+
121
+ # Handle tool calls (same code works for all providers!)
122
+ if response.choices[0].message.tool_calls:
123
+ tool_results = manager.handle_tool_calls(response)
124
+
125
+ # Continue conversation with results
126
+ messages = [
127
+ {"role": "user", "content": "Please help me with..."},
128
+ response.choices[0].message,
129
+ *[r.to_openai_format() for r in tool_results]
130
+ ]
131
+
132
+ follow_up = client.chat.completions.create(
133
+ model="gpt-4",
134
+ tools=tools,
135
+ messages=messages
136
+ )
137
+ ```
138
+
139
+ ### Agentic Loop (Automatic Multi-turn Tool Execution)
140
+
141
+ ```python
142
+ from openai import OpenAI
143
+ from skilllite import SkillManager
144
+
145
+ # Works with any provider
146
+ client = OpenAI() # or OpenAI(base_url="...", api_key="...")
147
+ manager = SkillManager(skills_dir="./my_skills")
148
+
149
+ # Create an agentic loop
150
+ loop = manager.create_agentic_loop(
151
+ client=client,
152
+ model="gpt-4",
153
+ system_prompt="You are a helpful assistant with access to various skills.",
154
+ max_iterations=10,
155
+ temperature=0.7 # Additional kwargs passed to chat.completions.create()
156
+ )
157
+
158
+ # Run until completion - handles multiple tool calls automatically
159
+ final_response = loop.run("Please analyze this data and generate a report.")
160
+ print(final_response.choices[0].message.content)
161
+ ```
162
+
163
+ ### Claude Native API (Optional)
164
+
165
+ If you prefer using Claude's native API directly:
166
+
167
+ ```python
168
+ import anthropic
169
+ from skilllite import SkillManager
170
+
171
+ client = anthropic.Anthropic()
172
+ manager = SkillManager(skills_dir="./my_skills")
173
+
174
+ # Use Claude-specific methods
175
+ tools = manager.get_tools_for_claude_native()
176
+ response = client.messages.create(
177
+ model="claude-sonnet-4-20250514",
178
+ max_tokens=4096,
179
+ tools=tools,
180
+ messages=[{"role": "user", "content": "..."}]
181
+ )
182
+
183
+ if response.stop_reason == "tool_use":
184
+ results = manager.handle_tool_calls_claude_native(response)
185
+ ```
186
+
187
+ ## Creating Skills
188
+
189
+ Skills are defined in directories with a `SKILL.md` file:
190
+
191
+ ```
192
+ my_skills/
193
+ ├── web-search/
194
+ │ ├── SKILL.md # Metadata and docs (includes dependency declaration)
195
+ │ └── scripts/
196
+ │ └── main.py
197
+ └── calculator/
198
+ ├── SKILL.md
199
+ └── scripts/
200
+ └── main.py
201
+ ```
202
+
203
+ > **Note**: Python dependencies are declared in the `compatibility` field of `SKILL.md`, not in a separate `requirements.txt` file.
204
+
205
+ ### SKILL.md Format
206
+
207
+ ```markdown
208
+ ---
209
+ name: web-search
210
+ description: Search the web for information
211
+ compatibility: Requires Python 3.x with requests library, network access
212
+ license: MIT
213
+ metadata:
214
+ author: example-org
215
+ version: "1.0"
216
+ ---
217
+
218
+ # Web Search Skill
219
+
220
+ This skill searches the web for information.
221
+
222
+ ## Input Parameters
223
+
224
+ - `query`: The search query (required)
225
+ ```
226
+
227
+ The `compatibility` field is used to:
228
+ - Detect language (Python/Node/Bash)
229
+ - Enable network access (keywords: network, internet, http, api, web)
230
+ - Auto-install dependencies (known packages like requests, pandas, axios, etc.)
231
+
232
+ ### Skill Entry Point
233
+
234
+ ```python
235
+ # main.py
236
+ import json
237
+ import sys
238
+
239
+ def main():
240
+ # Read input from stdin
241
+ input_data = json.loads(sys.stdin.read())
242
+
243
+ # Process the input
244
+ query = input_data.get("query", "")
245
+
246
+ # Do something...
247
+ result = {"results": [f"Result for: {query}"]}
248
+
249
+ # Output JSON to stdout
250
+ print(json.dumps(result))
251
+
252
+ if __name__ == "__main__":
253
+ main()
254
+ ```
255
+
256
+ ## API Reference
257
+
258
+ ### SkillManager
259
+
260
+ The main class for managing and executing skills.
261
+
262
+ #### Constructor
263
+
264
+ ```python
265
+ SkillManager(
266
+ skills_dir: Optional[str] = None, # Directory containing skills
267
+ binary_path: Optional[str] = None, # Path to skillbox binary
268
+ cache_dir: Optional[str] = None, # Cache directory for venvs
269
+ allow_network: bool = False # Default network access
270
+ )
271
+ ```
272
+
273
+ #### Methods
274
+
275
+ - `scan_directory(directory)` - Scan for skills
276
+ - `register_skill(skill_dir)` - Register a single skill
277
+ - `get_skill(name)` - Get skill by name
278
+ - `list_skills()` - List all skills
279
+ - `get_tools_for_claude()` - Get Claude-format tools
280
+ - `get_tools_for_openai()` - Get OpenAI-format tools
281
+ - `execute(skill_name, input_data)` - Execute a skill
282
+ - `handle_tool_calls(response, format)` - Handle LLM tool calls
283
+ - `create_agentic_loop(...)` - Create an agentic loop
284
+
285
+ ### ToolFormat
286
+
287
+ Enum for LLM provider formats:
288
+ - `ToolFormat.CLAUDE`
289
+ - `ToolFormat.OPENAI`
290
+
291
+ ## License
292
+
293
+ MIT License
@@ -0,0 +1,32 @@
1
+ skilllite/__init__.py,sha256=Ws0SEhXeqPTme-ASatdgkIba49zhZItN1Xlh2TVdhDY,3984
2
+ skilllite/analyzer.py,sha256=YG-ZJ6bO59pkP8LGECjcyCDPpH6wUYOm5QGx6et-ItA,14504
3
+ skilllite/builtin_tools.py,sha256=MGIlMlYTfj590PCY4ngbQteDIryfH7sDoKQyrDTH6L8,8067
4
+ skilllite/cli.py,sha256=Ns_wjCWz3Lh67P6QB7HYe2gM94FG8mEwKvPnQIx9uqI,6209
5
+ skilllite/quick.py,sha256=TNqKaww92WHUMf9nkjMZkdVjzz222lOKyjCwNp90_9c,16132
6
+ skilllite/validation.py,sha256=K3Hn6VKT7aybdKX8GXSRaxLbKmyVAnMYmP9cqh-D4s4,4308
7
+ skilllite/core/__init__.py,sha256=nU9yWE_M7xuWaIa1Ks_0dPfilRpW9GhlKfTV6eEU7-U,2044
8
+ skilllite/core/executor.py,sha256=eNPcVKxKcLUjHJ7K2hstKtxobZiDIvPjk2IhbZv3nxo,6517
9
+ skilllite/core/handler.py,sha256=pbQo5Gv-YSecufqpVbC0y8KP7Ra4uxxYpOW1nBimn5g,10354
10
+ skilllite/core/loops.py,sha256=2LEIyhYbHAR5YqvkyQeoRLYJPbKoEPaBK_wSMo47wKI,32210
11
+ skilllite/core/manager.py,sha256=uYAO5JtHM4DQvPnybBChHe0hUdOse1yBiQyc7vZ4nB8,19798
12
+ skilllite/core/metadata.py,sha256=mdZdK-qfK7wSaZrAAn2U25k0I63NrYuibtBHIrYR5RA,11221
13
+ skilllite/core/prompt_builder.py,sha256=rsubLzien9lKjOqM6iTn5nourPnz1-QQGzljiO0Z_3I,12844
14
+ skilllite/core/registry.py,sha256=AeljsV1uuYEJFGjpSwYxU6JGJ6EUuW8uNO3KirzHkuQ,6622
15
+ skilllite/core/skill_info.py,sha256=4_jsArmn1e7jEUXDEkmDAzjSI_903sdpfNLHOp1t1-M,6079
16
+ skilllite/core/tool_builder.py,sha256=k28ze50h7AjBiEfgKR6Y4DUFIGZJ1sCYbHEk_VkYl7w,12866
17
+ skilllite/core/tools.py,sha256=3RiAnZ_7S7iE6ZHXTPNKmAYQFY8SBUEzcQJZA0tZmX8,8168
18
+ skilllite/mcp/__init__.py,sha256=xrpoWy9zs8IJkW6fkkR4XjQrITo5PWvFW9NkmK8E2Fg,1028
19
+ skilllite/mcp/server.py,sha256=vhM0Kgjul1DZ5XFFKjuWZ0iksFP4nWl9n_bpiaakpTM,27912
20
+ skilllite/sandbox/__init__.py,sha256=6LPisVXB94SJ-C34nBAxd05NGEZR4PPxz2xaDpX4qEk,918
21
+ skilllite/sandbox/base.py,sha256=-Ul2QufoQ3myJNzBOEdv30A2HVSR9Oe4zEqpe9oJGqY,2628
22
+ skilllite/sandbox/config.py,sha256=eA3ceou6jF4S5kptv6cmIGKynQTaGDx3_vRrkJGQaAE,8207
23
+ skilllite/sandbox/utils.py,sha256=o5AZVkhqIcZE9veUy7FTfN7uMHVWJJLYXs7gYIXsptg,2572
24
+ skilllite/sandbox/skillbox/__init__.py,sha256=SFnNlLnnAc_NEEkqOkDbxYNfXROL7n1S09K_HFI_BOE,866
25
+ skilllite/sandbox/skillbox/binary.py,sha256=TNKQamWucMw-J6L5BjAasNpYqhBcBpHwQPMqjUOkgp4,11838
26
+ skilllite/sandbox/skillbox/executor.py,sha256=dXCR8JMwjD-x7-LfOCQbvgSq-29ZLIkXLp4oHed7b1Y,22872
27
+ skilllite-0.1.0.dist-info/licenses/LICENSE,sha256=ESBZ3GI5LkrbA2s5jZUQDqdcQ8oRlmk04aIYh34cOsw,1071
28
+ skilllite-0.1.0.dist-info/METADATA,sha256=-uHBXQuqfXHjGqsf5Qc5MELgUe9Lq_0UPUwpTFsyeTQ,8190
29
+ skilllite-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
30
+ skilllite-0.1.0.dist-info/entry_points.txt,sha256=H-meSKN3XzctxMvY6fa-YjAWyzs9t_0IjujOfumn4Wk,84
31
+ skilllite-0.1.0.dist-info/top_level.txt,sha256=aqo-9FEJuBbFT7WGE3aycTj27OxyQPCN6TuZtOcClAI,10
32
+ skilllite-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ skilllite = skilllite.cli:main
3
+ skilllite-mcp = skilllite.mcp:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 SkillLite Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ skilllite