skillware 0.2.8__tar.gz → 0.2.9__tar.gz
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.
- {skillware-0.2.8/skillware.egg-info → skillware-0.2.9}/PKG-INFO +31 -6
- {skillware-0.2.8 → skillware-0.2.9}/README.md +13 -2
- {skillware-0.2.8 → skillware-0.2.9}/pyproject.toml +27 -4
- skillware-0.2.9/skillware/cli.py +162 -0
- {skillware-0.2.8 → skillware-0.2.9/skillware.egg-info}/PKG-INFO +31 -6
- {skillware-0.2.8 → skillware-0.2.9}/skillware.egg-info/SOURCES.txt +3 -0
- skillware-0.2.9/skillware.egg-info/entry_points.txt +2 -0
- skillware-0.2.9/skillware.egg-info/requires.txt +32 -0
- skillware-0.2.9/tests/test_cli.py +140 -0
- skillware-0.2.8/skillware.egg-info/requires.txt +0 -12
- {skillware-0.2.8 → skillware-0.2.9}/LICENSE +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/MANIFEST.in +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/setup.cfg +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/mica_module/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/mica_module/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/mica_module/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/mica_module/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/mica_module/mica_corpus.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/mica_module/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/pii_masker/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/pii_masker/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/pii_masker/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/pii_masker/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/pii_masker/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/tos_evaluator/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/tos_evaluator/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/tos_evaluator/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/tos_evaluator/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/tos_evaluator/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/compliance/tos_evaluator/test_skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/dev_tools/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/dev_tools/issue_resolver/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/dev_tools/issue_resolver/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/dev_tools/issue_resolver/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/dev_tools/issue_resolver/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/dev_tools/issue_resolver/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/dev_tools/issue_resolver/test_skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/data/entities.ftm.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/data/malicious_scs_2025.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/data/normalized_fbi_lazarus_20250722_180019.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/data/normalized_israel_nbctf_20250722_180019.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/data/normalized_uniswap_trm.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/maintenance/normalization_tool.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/maintenance/normalize_uniswap_trm.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/office/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/office/pdf_form_filler/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/office/pdf_form_filler/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/office/pdf_form_filler/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/office/pdf_form_filler/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/office/pdf_form_filler/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/office/pdf_form_filler/utils.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/optimization/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/optimization/prompt_rewriter/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/optimization/prompt_rewriter/card.json +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/optimization/prompt_rewriter/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/optimization/prompt_rewriter/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skills/optimization/prompt_rewriter/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skillware/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skillware/core/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skillware/core/base_skill.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skillware/core/env.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skillware/core/loader.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skillware.egg-info/dependency_links.txt +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/skillware.egg-info/top_level.txt +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/tests/test_loader.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/tests/test_mica_module.py +0 -0
- {skillware-0.2.8 → skillware-0.2.9}/tests/test_skill_issuer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: skillware
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: A framework for modular, self-contained AI skills.
|
|
5
5
|
Author-email: ARPA Hellenic Logical Systems <skillware-os@arpacorp.net>
|
|
6
6
|
License: MIT License
|
|
@@ -35,15 +35,29 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
Requires-Dist: requests
|
|
37
37
|
Requires-Dist: pyyaml
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist: google-generativeai
|
|
40
|
-
Requires-Dist: pymupdf
|
|
38
|
+
Requires-Dist: python-dotenv
|
|
41
39
|
Requires-Dist: beautifulsoup4
|
|
42
40
|
Provides-Extra: dev
|
|
43
41
|
Requires-Dist: pytest; extra == "dev"
|
|
44
42
|
Requires-Dist: pytest-mock; extra == "dev"
|
|
45
43
|
Requires-Dist: flake8; extra == "dev"
|
|
46
44
|
Requires-Dist: black; extra == "dev"
|
|
45
|
+
Provides-Extra: cli
|
|
46
|
+
Requires-Dist: rich>=13.0; extra == "cli"
|
|
47
|
+
Provides-Extra: gemini
|
|
48
|
+
Requires-Dist: google-generativeai; extra == "gemini"
|
|
49
|
+
Provides-Extra: claude
|
|
50
|
+
Requires-Dist: anthropic; extra == "claude"
|
|
51
|
+
Provides-Extra: openai
|
|
52
|
+
Requires-Dist: openai; extra == "openai"
|
|
53
|
+
Provides-Extra: office
|
|
54
|
+
Requires-Dist: pymupdf; extra == "office"
|
|
55
|
+
Provides-Extra: all
|
|
56
|
+
Requires-Dist: rich>=13.0; extra == "all"
|
|
57
|
+
Requires-Dist: google-generativeai; extra == "all"
|
|
58
|
+
Requires-Dist: anthropic; extra == "all"
|
|
59
|
+
Requires-Dist: openai; extra == "all"
|
|
60
|
+
Requires-Dist: pymupdf; extra == "all"
|
|
47
61
|
Dynamic: license-file
|
|
48
62
|
|
|
49
63
|
<div align="center">
|
|
@@ -106,6 +120,7 @@ Skillware/
|
|
|
106
120
|
│ ├── instructions.md # Cognitive map for the LLM
|
|
107
121
|
│ └── test_skill.py # Unit tests & schema validation
|
|
108
122
|
├── skillware/ # Core Framework Package
|
|
123
|
+
│ ├── cli.py # Command-line interface
|
|
109
124
|
│ └── core/
|
|
110
125
|
│ ├── base_skill.py # Abstract Base Class for skills
|
|
111
126
|
│ ├── env.py # Environment Management
|
|
@@ -135,7 +150,16 @@ pip install -e .
|
|
|
135
150
|
|
|
136
151
|
> **Note**: Individual skills may have their own dependencies. The `SkillLoader` validates `manifest.yaml` and warns of missing packages (e.g., `requests`, `pandas`) upon loading a skill.
|
|
137
152
|
|
|
138
|
-
### 2.
|
|
153
|
+
### 2. Verify your installation
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pip install "skillware[cli]"
|
|
157
|
+
skillware list
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This prints a table of all locally available skills and confirms the install and path resolution are working.
|
|
161
|
+
|
|
162
|
+
### 3. Configuration
|
|
139
163
|
|
|
140
164
|
Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
141
165
|
|
|
@@ -143,7 +167,7 @@ Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
|
143
167
|
GOOGLE_API_KEY="your_key"
|
|
144
168
|
```
|
|
145
169
|
|
|
146
|
-
###
|
|
170
|
+
### 4. Usage Example (Gemini)
|
|
147
171
|
|
|
148
172
|
```python
|
|
149
173
|
import google.generativeai as genai
|
|
@@ -184,6 +208,7 @@ print(response.text)
|
|
|
184
208
|
* **[Usage Guide: Ollama](docs/usage/ollama.md)**: Native integration for local models via Ollama.
|
|
185
209
|
* **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
|
|
186
210
|
* **[Skill Library](docs/skills/README.md)**: Available capabilities.
|
|
211
|
+
* **[CLI Reference](docs/usage/cli.md)**: Discover and inspect locally installed skills from the terminal.
|
|
187
212
|
|
|
188
213
|
## Contributing
|
|
189
214
|
|
|
@@ -58,6 +58,7 @@ Skillware/
|
|
|
58
58
|
│ ├── instructions.md # Cognitive map for the LLM
|
|
59
59
|
│ └── test_skill.py # Unit tests & schema validation
|
|
60
60
|
├── skillware/ # Core Framework Package
|
|
61
|
+
│ ├── cli.py # Command-line interface
|
|
61
62
|
│ └── core/
|
|
62
63
|
│ ├── base_skill.py # Abstract Base Class for skills
|
|
63
64
|
│ ├── env.py # Environment Management
|
|
@@ -87,7 +88,16 @@ pip install -e .
|
|
|
87
88
|
|
|
88
89
|
> **Note**: Individual skills may have their own dependencies. The `SkillLoader` validates `manifest.yaml` and warns of missing packages (e.g., `requests`, `pandas`) upon loading a skill.
|
|
89
90
|
|
|
90
|
-
### 2.
|
|
91
|
+
### 2. Verify your installation
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install "skillware[cli]"
|
|
95
|
+
skillware list
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This prints a table of all locally available skills and confirms the install and path resolution are working.
|
|
99
|
+
|
|
100
|
+
### 3. Configuration
|
|
91
101
|
|
|
92
102
|
Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
93
103
|
|
|
@@ -95,7 +105,7 @@ Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
|
95
105
|
GOOGLE_API_KEY="your_key"
|
|
96
106
|
```
|
|
97
107
|
|
|
98
|
-
###
|
|
108
|
+
### 4. Usage Example (Gemini)
|
|
99
109
|
|
|
100
110
|
```python
|
|
101
111
|
import google.generativeai as genai
|
|
@@ -136,6 +146,7 @@ print(response.text)
|
|
|
136
146
|
* **[Usage Guide: Ollama](docs/usage/ollama.md)**: Native integration for local models via Ollama.
|
|
137
147
|
* **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
|
|
138
148
|
* **[Skill Library](docs/skills/README.md)**: Available capabilities.
|
|
149
|
+
* **[CLI Reference](docs/usage/cli.md)**: Discover and inspect locally installed skills from the terminal.
|
|
139
150
|
|
|
140
151
|
## Contributing
|
|
141
152
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "skillware"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.9"
|
|
8
8
|
description = "A framework for modular, self-contained AI skills."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -20,13 +20,14 @@ classifiers = [
|
|
|
20
20
|
dependencies = [
|
|
21
21
|
"requests",
|
|
22
22
|
"pyyaml",
|
|
23
|
-
"
|
|
24
|
-
"google-generativeai",
|
|
25
|
-
"pymupdf",
|
|
23
|
+
"python-dotenv",
|
|
26
24
|
"beautifulsoup4",
|
|
27
25
|
]
|
|
28
26
|
requires-python = ">=3.10"
|
|
29
27
|
|
|
28
|
+
[project.scripts]
|
|
29
|
+
skillware = "skillware.cli:main"
|
|
30
|
+
|
|
30
31
|
[project.optional-dependencies]
|
|
31
32
|
dev = [
|
|
32
33
|
"pytest",
|
|
@@ -34,6 +35,28 @@ dev = [
|
|
|
34
35
|
"flake8",
|
|
35
36
|
"black",
|
|
36
37
|
]
|
|
38
|
+
cli = [
|
|
39
|
+
"rich>=13.0",
|
|
40
|
+
]
|
|
41
|
+
gemini = [
|
|
42
|
+
"google-generativeai",
|
|
43
|
+
]
|
|
44
|
+
claude = [
|
|
45
|
+
"anthropic",
|
|
46
|
+
]
|
|
47
|
+
openai = [
|
|
48
|
+
"openai",
|
|
49
|
+
]
|
|
50
|
+
office = [
|
|
51
|
+
"pymupdf",
|
|
52
|
+
]
|
|
53
|
+
all = [
|
|
54
|
+
"rich>=13.0",
|
|
55
|
+
"google-generativeai",
|
|
56
|
+
"anthropic",
|
|
57
|
+
"openai",
|
|
58
|
+
"pymupdf",
|
|
59
|
+
]
|
|
37
60
|
|
|
38
61
|
[tool.setuptools]
|
|
39
62
|
include-package-data = true
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import yaml
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import List, Dict, Any, Optional
|
|
5
|
+
|
|
6
|
+
from skillware.core.loader import SkillLoader
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _get_skill_roots(skills_root_override: Optional[Path] = None) -> List[Path]:
|
|
10
|
+
"""Return the list of roots to search for skills, mirrors SkillLoader resolution order."""
|
|
11
|
+
if skills_root_override is not None:
|
|
12
|
+
if skills_root_override.exists():
|
|
13
|
+
return [skills_root_override]
|
|
14
|
+
return []
|
|
15
|
+
|
|
16
|
+
roots = []
|
|
17
|
+
seen = set()
|
|
18
|
+
|
|
19
|
+
for root in (
|
|
20
|
+
SkillLoader._env_skill_roots()
|
|
21
|
+
+ SkillLoader._cwd_skill_roots()
|
|
22
|
+
+ [SkillLoader._bundled_skills_root()]
|
|
23
|
+
):
|
|
24
|
+
resolved = root.resolve()
|
|
25
|
+
if resolved not in seen and resolved.exists():
|
|
26
|
+
seen.add(resolved)
|
|
27
|
+
roots.append(resolved)
|
|
28
|
+
|
|
29
|
+
return roots
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _discover_skills(
|
|
33
|
+
skills_root_override: Optional[Path] = None,
|
|
34
|
+
) -> List[Dict[str, Any]]:
|
|
35
|
+
"""Walk all skill roots and return a list of dicts with each skill's metadata."""
|
|
36
|
+
roots = _get_skill_roots(skills_root_override)
|
|
37
|
+
|
|
38
|
+
skills = []
|
|
39
|
+
seen_ids = set()
|
|
40
|
+
|
|
41
|
+
for root in roots:
|
|
42
|
+
for manifest_path in root.glob("*/*/manifest.yaml"):
|
|
43
|
+
|
|
44
|
+
if not SkillLoader._is_skill_dir(manifest_path.parent):
|
|
45
|
+
continue
|
|
46
|
+
|
|
47
|
+
with open(manifest_path, encoding="utf-8") as f:
|
|
48
|
+
data = yaml.safe_load(f) or {}
|
|
49
|
+
|
|
50
|
+
skill_id = f"{manifest_path.parent.parent.name}/{manifest_path.parent.name}"
|
|
51
|
+
|
|
52
|
+
# skip duplicates found in multiple roots
|
|
53
|
+
if skill_id in seen_ids:
|
|
54
|
+
continue
|
|
55
|
+
seen_ids.add(skill_id)
|
|
56
|
+
|
|
57
|
+
issuer = data.get("issuer") or {}
|
|
58
|
+
|
|
59
|
+
skills.append(
|
|
60
|
+
{
|
|
61
|
+
"id": skill_id,
|
|
62
|
+
"category": manifest_path.parent.parent.name,
|
|
63
|
+
"name": manifest_path.parent.name,
|
|
64
|
+
"version": data.get("version", "?").strip(),
|
|
65
|
+
"description": data.get("description", "").strip(),
|
|
66
|
+
"requirements": ", ".join(data.get("requirements") or []).strip(),
|
|
67
|
+
"issuer": issuer.get("github") or issuer.get("name") or "",
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return skills
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def cmd_list(
|
|
75
|
+
skills_root_override: Optional[Path] = None,
|
|
76
|
+
category_filter: Optional[str] = None,
|
|
77
|
+
issuer_filter: Optional[str] = None,
|
|
78
|
+
console=None,
|
|
79
|
+
) -> None:
|
|
80
|
+
"""Print a formatted table of all available skills."""
|
|
81
|
+
try:
|
|
82
|
+
from rich.table import Table
|
|
83
|
+
from rich.console import Console
|
|
84
|
+
except ImportError:
|
|
85
|
+
raise SystemExit(
|
|
86
|
+
"rich is required for the CLI. Install it with: pip install 'skillware[cli]'"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if console is None:
|
|
90
|
+
console = Console()
|
|
91
|
+
|
|
92
|
+
skills = _discover_skills(skills_root_override)
|
|
93
|
+
|
|
94
|
+
if category_filter:
|
|
95
|
+
skills = [s for s in skills if s["category"] == category_filter]
|
|
96
|
+
|
|
97
|
+
if issuer_filter:
|
|
98
|
+
skills = [s for s in skills if s["issuer"] == issuer_filter]
|
|
99
|
+
|
|
100
|
+
if not skills:
|
|
101
|
+
console.print("No skills found.")
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
table = Table()
|
|
105
|
+
|
|
106
|
+
table.add_column("ID")
|
|
107
|
+
table.add_column("VERSION")
|
|
108
|
+
table.add_column("CATEGORY")
|
|
109
|
+
table.add_column("ISSUER")
|
|
110
|
+
table.add_column("DESCRIPTION")
|
|
111
|
+
table.add_column("REQUIREMENTS")
|
|
112
|
+
|
|
113
|
+
for skill in skills:
|
|
114
|
+
table.add_row(
|
|
115
|
+
skill["id"],
|
|
116
|
+
skill["version"],
|
|
117
|
+
skill["category"],
|
|
118
|
+
skill["issuer"],
|
|
119
|
+
skill["description"],
|
|
120
|
+
skill["requirements"],
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
console.print(table)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def main() -> None:
|
|
127
|
+
"""CLI entry point."""
|
|
128
|
+
parser = argparse.ArgumentParser(prog="skillware")
|
|
129
|
+
subparsers = parser.add_subparsers(dest="command")
|
|
130
|
+
|
|
131
|
+
list_parser = subparsers.add_parser("list", help="List all available skills.")
|
|
132
|
+
list_parser.add_argument(
|
|
133
|
+
"--skills-root",
|
|
134
|
+
type=Path,
|
|
135
|
+
default=None,
|
|
136
|
+
help="Override the skills directory path.",
|
|
137
|
+
)
|
|
138
|
+
list_parser.add_argument(
|
|
139
|
+
"--category",
|
|
140
|
+
default=None,
|
|
141
|
+
help="Filter skills by category.",
|
|
142
|
+
)
|
|
143
|
+
list_parser.add_argument(
|
|
144
|
+
"--issuer",
|
|
145
|
+
default=None,
|
|
146
|
+
help="Filter skills by issuer GitHub handle or name.",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
args = parser.parse_args()
|
|
150
|
+
|
|
151
|
+
if args.command == "list":
|
|
152
|
+
cmd_list(
|
|
153
|
+
skills_root_override=args.skills_root,
|
|
154
|
+
category_filter=args.category,
|
|
155
|
+
issuer_filter=args.issuer,
|
|
156
|
+
)
|
|
157
|
+
else:
|
|
158
|
+
parser.print_help()
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if __name__ == "__main__":
|
|
162
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: skillware
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: A framework for modular, self-contained AI skills.
|
|
5
5
|
Author-email: ARPA Hellenic Logical Systems <skillware-os@arpacorp.net>
|
|
6
6
|
License: MIT License
|
|
@@ -35,15 +35,29 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
Requires-Dist: requests
|
|
37
37
|
Requires-Dist: pyyaml
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist: google-generativeai
|
|
40
|
-
Requires-Dist: pymupdf
|
|
38
|
+
Requires-Dist: python-dotenv
|
|
41
39
|
Requires-Dist: beautifulsoup4
|
|
42
40
|
Provides-Extra: dev
|
|
43
41
|
Requires-Dist: pytest; extra == "dev"
|
|
44
42
|
Requires-Dist: pytest-mock; extra == "dev"
|
|
45
43
|
Requires-Dist: flake8; extra == "dev"
|
|
46
44
|
Requires-Dist: black; extra == "dev"
|
|
45
|
+
Provides-Extra: cli
|
|
46
|
+
Requires-Dist: rich>=13.0; extra == "cli"
|
|
47
|
+
Provides-Extra: gemini
|
|
48
|
+
Requires-Dist: google-generativeai; extra == "gemini"
|
|
49
|
+
Provides-Extra: claude
|
|
50
|
+
Requires-Dist: anthropic; extra == "claude"
|
|
51
|
+
Provides-Extra: openai
|
|
52
|
+
Requires-Dist: openai; extra == "openai"
|
|
53
|
+
Provides-Extra: office
|
|
54
|
+
Requires-Dist: pymupdf; extra == "office"
|
|
55
|
+
Provides-Extra: all
|
|
56
|
+
Requires-Dist: rich>=13.0; extra == "all"
|
|
57
|
+
Requires-Dist: google-generativeai; extra == "all"
|
|
58
|
+
Requires-Dist: anthropic; extra == "all"
|
|
59
|
+
Requires-Dist: openai; extra == "all"
|
|
60
|
+
Requires-Dist: pymupdf; extra == "all"
|
|
47
61
|
Dynamic: license-file
|
|
48
62
|
|
|
49
63
|
<div align="center">
|
|
@@ -106,6 +120,7 @@ Skillware/
|
|
|
106
120
|
│ ├── instructions.md # Cognitive map for the LLM
|
|
107
121
|
│ └── test_skill.py # Unit tests & schema validation
|
|
108
122
|
├── skillware/ # Core Framework Package
|
|
123
|
+
│ ├── cli.py # Command-line interface
|
|
109
124
|
│ └── core/
|
|
110
125
|
│ ├── base_skill.py # Abstract Base Class for skills
|
|
111
126
|
│ ├── env.py # Environment Management
|
|
@@ -135,7 +150,16 @@ pip install -e .
|
|
|
135
150
|
|
|
136
151
|
> **Note**: Individual skills may have their own dependencies. The `SkillLoader` validates `manifest.yaml` and warns of missing packages (e.g., `requests`, `pandas`) upon loading a skill.
|
|
137
152
|
|
|
138
|
-
### 2.
|
|
153
|
+
### 2. Verify your installation
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pip install "skillware[cli]"
|
|
157
|
+
skillware list
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This prints a table of all locally available skills and confirms the install and path resolution are working.
|
|
161
|
+
|
|
162
|
+
### 3. Configuration
|
|
139
163
|
|
|
140
164
|
Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
141
165
|
|
|
@@ -143,7 +167,7 @@ Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
|
143
167
|
GOOGLE_API_KEY="your_key"
|
|
144
168
|
```
|
|
145
169
|
|
|
146
|
-
###
|
|
170
|
+
### 4. Usage Example (Gemini)
|
|
147
171
|
|
|
148
172
|
```python
|
|
149
173
|
import google.generativeai as genai
|
|
@@ -184,6 +208,7 @@ print(response.text)
|
|
|
184
208
|
* **[Usage Guide: Ollama](docs/usage/ollama.md)**: Native integration for local models via Ollama.
|
|
185
209
|
* **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
|
|
186
210
|
* **[Skill Library](docs/skills/README.md)**: Available capabilities.
|
|
211
|
+
* **[CLI Reference](docs/usage/cli.md)**: Discover and inspect locally installed skills from the terminal.
|
|
187
212
|
|
|
188
213
|
## Contributing
|
|
189
214
|
|
|
@@ -61,15 +61,18 @@ skills/optimization/prompt_rewriter/instructions.md
|
|
|
61
61
|
skills/optimization/prompt_rewriter/manifest.yaml
|
|
62
62
|
skills/optimization/prompt_rewriter/skill.py
|
|
63
63
|
skillware/__init__.py
|
|
64
|
+
skillware/cli.py
|
|
64
65
|
skillware.egg-info/PKG-INFO
|
|
65
66
|
skillware.egg-info/SOURCES.txt
|
|
66
67
|
skillware.egg-info/dependency_links.txt
|
|
68
|
+
skillware.egg-info/entry_points.txt
|
|
67
69
|
skillware.egg-info/requires.txt
|
|
68
70
|
skillware.egg-info/top_level.txt
|
|
69
71
|
skillware/core/__init__.py
|
|
70
72
|
skillware/core/base_skill.py
|
|
71
73
|
skillware/core/env.py
|
|
72
74
|
skillware/core/loader.py
|
|
75
|
+
tests/test_cli.py
|
|
73
76
|
tests/test_loader.py
|
|
74
77
|
tests/test_mica_module.py
|
|
75
78
|
tests/test_skill_issuer.py
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
requests
|
|
2
|
+
pyyaml
|
|
3
|
+
python-dotenv
|
|
4
|
+
beautifulsoup4
|
|
5
|
+
|
|
6
|
+
[all]
|
|
7
|
+
rich>=13.0
|
|
8
|
+
google-generativeai
|
|
9
|
+
anthropic
|
|
10
|
+
openai
|
|
11
|
+
pymupdf
|
|
12
|
+
|
|
13
|
+
[claude]
|
|
14
|
+
anthropic
|
|
15
|
+
|
|
16
|
+
[cli]
|
|
17
|
+
rich>=13.0
|
|
18
|
+
|
|
19
|
+
[dev]
|
|
20
|
+
pytest
|
|
21
|
+
pytest-mock
|
|
22
|
+
flake8
|
|
23
|
+
black
|
|
24
|
+
|
|
25
|
+
[gemini]
|
|
26
|
+
google-generativeai
|
|
27
|
+
|
|
28
|
+
[office]
|
|
29
|
+
pymupdf
|
|
30
|
+
|
|
31
|
+
[openai]
|
|
32
|
+
openai
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from skillware.cli import _discover_skills, cmd_list
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_discover_skills_returns_skills(tmp_path):
|
|
5
|
+
# Create a fake skill directory structure
|
|
6
|
+
skill_dir = tmp_path / "office" / "pdf_form_filler"
|
|
7
|
+
skill_dir.mkdir(parents=True)
|
|
8
|
+
(skill_dir / "skill.py").touch()
|
|
9
|
+
|
|
10
|
+
manifest = skill_dir / "manifest.yaml"
|
|
11
|
+
manifest.write_text(
|
|
12
|
+
"name: pdf_form_filler\n"
|
|
13
|
+
"version: 0.1.0\n"
|
|
14
|
+
"description: Fills PDF forms.\n"
|
|
15
|
+
"requirements:\n"
|
|
16
|
+
" - pymupdf\n"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
skills = _discover_skills(tmp_path)
|
|
20
|
+
|
|
21
|
+
assert len(skills) == 1
|
|
22
|
+
assert skills[0]["id"] == "office/pdf_form_filler"
|
|
23
|
+
assert skills[0]["version"] == "0.1.0"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_discover_skills_empty_directory(tmp_path):
|
|
27
|
+
# No skills created, directory is empty
|
|
28
|
+
skills = _discover_skills(tmp_path)
|
|
29
|
+
|
|
30
|
+
assert skills == []
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_discover_skills_nonexistent_override_falls_back(tmp_path, monkeypatch):
|
|
34
|
+
# An override path that does not exist should be ignored
|
|
35
|
+
# and fall back to other roots without crashing
|
|
36
|
+
monkeypatch.chdir(tmp_path)
|
|
37
|
+
fake_path = tmp_path / "nonexistent"
|
|
38
|
+
|
|
39
|
+
# Should not raise, just return empty list since no roots have skills
|
|
40
|
+
skills = _discover_skills(fake_path)
|
|
41
|
+
assert skills == []
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_discover_skills_missing_optional_fields(tmp_path):
|
|
45
|
+
# Manifest with only required fields, no version, description or requirements
|
|
46
|
+
skill_dir = tmp_path / "office" / "minimal_skill"
|
|
47
|
+
skill_dir.mkdir(parents=True)
|
|
48
|
+
(skill_dir / "skill.py").touch()
|
|
49
|
+
|
|
50
|
+
manifest = skill_dir / "manifest.yaml"
|
|
51
|
+
manifest.write_text("name: minimal_skill\n")
|
|
52
|
+
|
|
53
|
+
skills = _discover_skills(tmp_path)
|
|
54
|
+
|
|
55
|
+
assert len(skills) == 1
|
|
56
|
+
assert skills[0]["version"] == "?"
|
|
57
|
+
assert skills[0]["description"] == ""
|
|
58
|
+
assert skills[0]["requirements"] == ""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_discover_skills_ignores_deeply_nested_manifest(tmp_path):
|
|
62
|
+
# manifest.yaml three levels deep should not be picked up
|
|
63
|
+
skill_dir = tmp_path / "office" / "pdf_form_filler" / "extra"
|
|
64
|
+
skill_dir.mkdir(parents=True)
|
|
65
|
+
|
|
66
|
+
manifest = skill_dir / "manifest.yaml"
|
|
67
|
+
manifest.write_text("name: should_not_appear\nversion: 0.1.0\n")
|
|
68
|
+
|
|
69
|
+
skills = _discover_skills(tmp_path)
|
|
70
|
+
|
|
71
|
+
assert skills == []
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_discover_skills_includes_issuer(tmp_path):
|
|
75
|
+
# Manifest with issuer github handle
|
|
76
|
+
skill_dir = tmp_path / "office" / "pdf_form_filler"
|
|
77
|
+
skill_dir.mkdir(parents=True)
|
|
78
|
+
(skill_dir / "skill.py").touch()
|
|
79
|
+
|
|
80
|
+
manifest = skill_dir / "manifest.yaml"
|
|
81
|
+
manifest.write_text(
|
|
82
|
+
"name: pdf_form_filler\n"
|
|
83
|
+
"version: 0.1.0\n"
|
|
84
|
+
"description: Fills PDF forms.\n"
|
|
85
|
+
"issuer:\n"
|
|
86
|
+
" name: Ross Peili\n"
|
|
87
|
+
" github: rosspeili\n"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
skills = _discover_skills(tmp_path)
|
|
91
|
+
|
|
92
|
+
assert skills[0]["issuer"] == "rosspeili"
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_discover_skills_issuer_falls_back_to_name(tmp_path):
|
|
96
|
+
# Manifest with issuer name but no github handle
|
|
97
|
+
skill_dir = tmp_path / "office" / "pdf_form_filler"
|
|
98
|
+
skill_dir.mkdir(parents=True)
|
|
99
|
+
(skill_dir / "skill.py").touch()
|
|
100
|
+
|
|
101
|
+
manifest = skill_dir / "manifest.yaml"
|
|
102
|
+
manifest.write_text(
|
|
103
|
+
"name: pdf_form_filler\n"
|
|
104
|
+
"version: 0.1.0\n"
|
|
105
|
+
"description: Fills PDF forms.\n"
|
|
106
|
+
"issuer:\n"
|
|
107
|
+
" name: Ross Peili\n"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
skills = _discover_skills(tmp_path)
|
|
111
|
+
|
|
112
|
+
assert skills[0]["issuer"] == "Ross Peili"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_cmd_list_filter_by_category(tmp_path):
|
|
116
|
+
# Only skills matching the category should appear
|
|
117
|
+
import io
|
|
118
|
+
from rich.console import Console
|
|
119
|
+
|
|
120
|
+
for category, name in [
|
|
121
|
+
("office", "pdf_form_filler"),
|
|
122
|
+
("finance", "wallet_screening"),
|
|
123
|
+
]:
|
|
124
|
+
skill_dir = tmp_path / category / name
|
|
125
|
+
skill_dir.mkdir(parents=True)
|
|
126
|
+
(skill_dir / "skill.py").touch()
|
|
127
|
+
(skill_dir / "manifest.yaml").write_text(
|
|
128
|
+
f"name: {name}\nversion: 0.1.0\ndescription: Test.\n"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
buf = io.StringIO()
|
|
132
|
+
cmd_list(
|
|
133
|
+
skills_root_override=tmp_path,
|
|
134
|
+
category_filter="office",
|
|
135
|
+
console=Console(file=buf, force_terminal=False),
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
output = buf.getvalue()
|
|
139
|
+
assert "office" in output
|
|
140
|
+
assert "finance" not in output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/instructions.md
RENAMED
|
File without changes
|
{skillware-0.2.8 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/manifest.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/data/malicious_scs_2025.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{skillware-0.2.8 → skillware-0.2.9}/skills/finance/wallet_screening/data/normalized_uniswap_trm.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|