skillware 0.2.8__tar.gz → 0.3.1__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.3.1}/PKG-INFO +97 -35
- {skillware-0.2.8 → skillware-0.3.1}/README.md +79 -31
- {skillware-0.2.8 → skillware-0.3.1}/pyproject.toml +27 -4
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/mica_module/manifest.yaml +1 -1
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/mica_module/skill.py +38 -6
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/tos_evaluator/skill.py +12 -9
- skillware-0.3.1/skills/data_engineering/novelty_extractor/__init__.py +3 -0
- skillware-0.3.1/skills/data_engineering/novelty_extractor/card.json +37 -0
- skillware-0.3.1/skills/data_engineering/novelty_extractor/instructions.md +60 -0
- skillware-0.3.1/skills/data_engineering/novelty_extractor/manifest.yaml +45 -0
- skillware-0.3.1/skills/data_engineering/novelty_extractor/skill.py +111 -0
- skillware-0.3.1/skills/data_engineering/novelty_extractor/test_skill.py +105 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/skill.py +8 -9
- skillware-0.3.1/skillware/cli.py +162 -0
- {skillware-0.2.8 → skillware-0.3.1}/skillware/core/loader.py +16 -5
- {skillware-0.2.8 → skillware-0.3.1/skillware.egg-info}/PKG-INFO +97 -35
- {skillware-0.2.8 → skillware-0.3.1}/skillware.egg-info/SOURCES.txt +9 -0
- skillware-0.3.1/skillware.egg-info/entry_points.txt +2 -0
- skillware-0.3.1/skillware.egg-info/requires.txt +32 -0
- skillware-0.3.1/tests/test_cli.py +140 -0
- skillware-0.2.8/skillware.egg-info/requires.txt +0 -12
- {skillware-0.2.8 → skillware-0.3.1}/LICENSE +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/MANIFEST.in +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/setup.cfg +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/mica_module/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/mica_module/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/mica_module/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/mica_module/mica_corpus.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/pii_masker/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/pii_masker/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/pii_masker/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/pii_masker/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/pii_masker/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/tos_evaluator/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/tos_evaluator/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/tos_evaluator/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/tos_evaluator/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/compliance/tos_evaluator/test_skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/data_engineering/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/dev_tools/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/dev_tools/issue_resolver/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/dev_tools/issue_resolver/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/dev_tools/issue_resolver/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/dev_tools/issue_resolver/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/dev_tools/issue_resolver/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/dev_tools/issue_resolver/test_skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/data/entities.ftm.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/data/malicious_scs_2025.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/data/normalized_fbi_lazarus_20250722_180019.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/data/normalized_israel_nbctf_20250722_180019.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/data/normalized_uniswap_trm.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/maintenance/normalization_tool.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/maintenance/normalize_uniswap_trm.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/finance/wallet_screening/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/office/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/office/pdf_form_filler/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/office/pdf_form_filler/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/office/pdf_form_filler/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/office/pdf_form_filler/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/office/pdf_form_filler/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/office/pdf_form_filler/utils.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/optimization/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/optimization/prompt_rewriter/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/optimization/prompt_rewriter/card.json +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/optimization/prompt_rewriter/instructions.md +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/optimization/prompt_rewriter/manifest.yaml +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skills/optimization/prompt_rewriter/skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skillware/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skillware/core/__init__.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skillware/core/base_skill.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skillware/core/env.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skillware.egg-info/dependency_links.txt +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/skillware.egg-info/top_level.txt +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/tests/test_loader.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/tests/test_mica_module.py +0 -0
- {skillware-0.2.8 → skillware-0.3.1}/tests/test_skill_issuer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: skillware
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
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-genai; 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-genai; 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">
|
|
@@ -89,27 +103,34 @@ A **Skill** in this framework provides everything an Agent needs to master a dom
|
|
|
89
103
|
3. **Governance**: Constitution and safety boundaries.
|
|
90
104
|
4. **Interface**: Standardized schemas for LLM tool calling.
|
|
91
105
|
|
|
106
|
+
### Skill library
|
|
107
|
+
|
|
108
|
+
Browse capabilities by category in the [Skill library](docs/skills/README.md).
|
|
109
|
+
|
|
92
110
|
## Architecture
|
|
93
111
|
|
|
94
|
-
This repository is organized into a core framework, a registry of skills, and
|
|
112
|
+
This repository is organized into a core framework, a registry of skills, and
|
|
113
|
+
documentation. Runnable provider scripts are indexed in
|
|
114
|
+
[examples/README.md](examples/README.md).
|
|
95
115
|
|
|
96
116
|
```text
|
|
97
117
|
Skillware/
|
|
98
|
-
├── docs/ #
|
|
99
|
-
├── examples/ #
|
|
100
|
-
│ └── basic_agent.py # Example showing SkillLoader integration
|
|
118
|
+
├── docs/ # Introduction, testing, skill catalog, usage guides (docs/usage/)
|
|
119
|
+
├── examples/ # Provider reference scripts (Gemini, Claude, OpenAI, Ollama, ...)
|
|
101
120
|
├── skills/ # Skill Registry
|
|
102
121
|
│ └── category/ # Domain boundaries (e.g., finance)
|
|
103
122
|
│ └── skill_name/ # The Skill bundle
|
|
104
123
|
│ ├── manifest.yaml # Definition, schema, and constitution
|
|
105
124
|
│ ├── skill.py # Executable Python logic
|
|
106
125
|
│ ├── instructions.md # Cognitive map for the LLM
|
|
107
|
-
│
|
|
126
|
+
│ ├── card.json # Optional UI presentation metadata
|
|
127
|
+
│ └── test_skill.py # Unit tests and schema validation
|
|
108
128
|
├── skillware/ # Core Framework Package
|
|
129
|
+
│ ├── cli.py # Command-line interface
|
|
109
130
|
│ └── core/
|
|
110
131
|
│ ├── base_skill.py # Abstract Base Class for skills
|
|
111
132
|
│ ├── env.py # Environment Management
|
|
112
|
-
│ └── loader.py # Universal Skill Loader
|
|
133
|
+
│ └── loader.py # Universal Skill Loader and Model Adapter
|
|
113
134
|
├── templates/ # Boilerplate templates for new skills
|
|
114
135
|
│ └── python_skill/ # Standard template with required files
|
|
115
136
|
└── tests/ # Automated test suite
|
|
@@ -135,7 +156,16 @@ pip install -e .
|
|
|
135
156
|
|
|
136
157
|
> **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
158
|
|
|
138
|
-
### 2.
|
|
159
|
+
### 2. Verify your installation
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pip install "skillware[cli]"
|
|
163
|
+
skillware list
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
This prints a table of all locally available skills and confirms the install and path resolution are working.
|
|
167
|
+
|
|
168
|
+
### 3. Configuration
|
|
139
169
|
|
|
140
170
|
Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
141
171
|
|
|
@@ -143,10 +173,14 @@ Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
|
143
173
|
GOOGLE_API_KEY="your_key"
|
|
144
174
|
```
|
|
145
175
|
|
|
146
|
-
###
|
|
176
|
+
### 4. Usage Example (Gemini)
|
|
177
|
+
|
|
178
|
+
This example requires the Google SDK optional extra: `pip install "skillware[gemini]"` (local dev: `pip install -e ".[gemini]"`). See the [Gemini usage guide](docs/usage/gemini.md) for setup details.
|
|
147
179
|
|
|
148
180
|
```python
|
|
149
|
-
import
|
|
181
|
+
import os
|
|
182
|
+
import google.genai as genai
|
|
183
|
+
from google.genai import types
|
|
150
184
|
from skillware.core.loader import SkillLoader
|
|
151
185
|
from skillware.core.env import load_env_file
|
|
152
186
|
|
|
@@ -155,35 +189,63 @@ load_env_file()
|
|
|
155
189
|
|
|
156
190
|
# 1. Load the Skill from the Registry
|
|
157
191
|
# The loader reads the code, manifest, and instructions automatically
|
|
158
|
-
skill_bundle = SkillLoader.load_skill("
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
model = genai.GenerativeModel(
|
|
162
|
-
'gemini-2.5-flash',
|
|
163
|
-
tools=[SkillLoader.to_gemini_tool(skill_bundle)], # The "Adapter"
|
|
164
|
-
system_instruction=skill_bundle['instructions'] # The "Mind"
|
|
192
|
+
skill_bundle = SkillLoader.load_skill("finance/wallet_screening")
|
|
193
|
+
skill = skill_bundle["module"].WalletScreeningSkill(
|
|
194
|
+
config={"ETHERSCAN_API_KEY": os.environ.get("ETHERSCAN_API_KEY")}
|
|
165
195
|
)
|
|
166
|
-
|
|
196
|
+
|
|
197
|
+
# 2. Client & Tool Setup
|
|
198
|
+
client = genai.Client()
|
|
199
|
+
tool = SkillLoader.to_gemini_tool(skill_bundle) # The "Adapter"
|
|
200
|
+
system_instruction = skill_bundle['instructions'] # The "Mind"
|
|
167
201
|
|
|
168
202
|
# 3. Agent Loop
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
203
|
+
response = client.models.generate_content(
|
|
204
|
+
model="gemini-2.5-flash",
|
|
205
|
+
contents="Screen wallet 0xd8dA... for risks.",
|
|
206
|
+
config=types.GenerateContentConfig(
|
|
207
|
+
tools=[tool],
|
|
208
|
+
system_instruction=system_instruction,
|
|
209
|
+
),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
for part in response.candidates[0].content.parts:
|
|
213
|
+
if part.function_call:
|
|
214
|
+
result = skill.execute(dict(part.function_call.args))
|
|
215
|
+
follow_up = client.models.generate_content(
|
|
216
|
+
model="gemini-2.5-flash",
|
|
217
|
+
contents=[
|
|
218
|
+
"Use this tool result to answer the original request.",
|
|
219
|
+
{
|
|
220
|
+
"function_response": {
|
|
221
|
+
"name": part.function_call.name,
|
|
222
|
+
"response": {"result": result},
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
config=types.GenerateContentConfig(
|
|
227
|
+
tools=[tool],
|
|
228
|
+
system_instruction=system_instruction,
|
|
229
|
+
),
|
|
230
|
+
)
|
|
231
|
+
print(follow_up.text)
|
|
232
|
+
else:
|
|
233
|
+
print(part.text)
|
|
172
234
|
```
|
|
173
235
|
|
|
236
|
+
For other providers and shared integration patterns, see the [usage guides index](docs/usage/README.md), [agent loops](docs/usage/agent_loops.md), [Gemini](docs/usage/gemini.md), [Claude](docs/usage/claude.md), [OpenAI](docs/usage/openai.md), [DeepSeek](docs/usage/deepseek.md), [Ollama](docs/usage/ollama.md), [API keys for skills](docs/usage/api_keys.md), and the [skill usage template](docs/usage/skill_usage_template.md) for contributors.
|
|
237
|
+
|
|
174
238
|
## Documentation
|
|
175
239
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
* **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
|
|
186
|
-
* **[Skill Library](docs/skills/README.md)**: Available capabilities.
|
|
240
|
+
| Topic | Link |
|
|
241
|
+
| :--- | :--- |
|
|
242
|
+
| Introduction | [docs/introduction.md](docs/introduction.md) |
|
|
243
|
+
| Testing | [docs/TESTING.md](docs/TESTING.md) |
|
|
244
|
+
| Skill library | [docs/skills/README.md](docs/skills/README.md) |
|
|
245
|
+
| Usage guides | [index](docs/usage/README.md) — [Gemini](docs/usage/gemini.md) · [Claude](docs/usage/claude.md) · [OpenAI](docs/usage/openai.md) · [DeepSeek](docs/usage/deepseek.md) · [Ollama](docs/usage/ollama.md); [agent loops](docs/usage/agent_loops.md); [API keys](docs/usage/api_keys.md) |
|
|
246
|
+
| Examples index | [examples/README.md](examples/README.md) |
|
|
247
|
+
| CLI | [docs/usage/cli.md](docs/usage/cli.md) |
|
|
248
|
+
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) · [agent workflow](docs/contributing/ai_native_workflow.md) |
|
|
187
249
|
|
|
188
250
|
## Contributing
|
|
189
251
|
|
|
@@ -41,27 +41,34 @@ A **Skill** in this framework provides everything an Agent needs to master a dom
|
|
|
41
41
|
3. **Governance**: Constitution and safety boundaries.
|
|
42
42
|
4. **Interface**: Standardized schemas for LLM tool calling.
|
|
43
43
|
|
|
44
|
+
### Skill library
|
|
45
|
+
|
|
46
|
+
Browse capabilities by category in the [Skill library](docs/skills/README.md).
|
|
47
|
+
|
|
44
48
|
## Architecture
|
|
45
49
|
|
|
46
|
-
This repository is organized into a core framework, a registry of skills, and
|
|
50
|
+
This repository is organized into a core framework, a registry of skills, and
|
|
51
|
+
documentation. Runnable provider scripts are indexed in
|
|
52
|
+
[examples/README.md](examples/README.md).
|
|
47
53
|
|
|
48
54
|
```text
|
|
49
55
|
Skillware/
|
|
50
|
-
├── docs/ #
|
|
51
|
-
├── examples/ #
|
|
52
|
-
│ └── basic_agent.py # Example showing SkillLoader integration
|
|
56
|
+
├── docs/ # Introduction, testing, skill catalog, usage guides (docs/usage/)
|
|
57
|
+
├── examples/ # Provider reference scripts (Gemini, Claude, OpenAI, Ollama, ...)
|
|
53
58
|
├── skills/ # Skill Registry
|
|
54
59
|
│ └── category/ # Domain boundaries (e.g., finance)
|
|
55
60
|
│ └── skill_name/ # The Skill bundle
|
|
56
61
|
│ ├── manifest.yaml # Definition, schema, and constitution
|
|
57
62
|
│ ├── skill.py # Executable Python logic
|
|
58
63
|
│ ├── instructions.md # Cognitive map for the LLM
|
|
59
|
-
│
|
|
64
|
+
│ ├── card.json # Optional UI presentation metadata
|
|
65
|
+
│ └── test_skill.py # Unit tests and schema validation
|
|
60
66
|
├── skillware/ # Core Framework Package
|
|
67
|
+
│ ├── cli.py # Command-line interface
|
|
61
68
|
│ └── core/
|
|
62
69
|
│ ├── base_skill.py # Abstract Base Class for skills
|
|
63
70
|
│ ├── env.py # Environment Management
|
|
64
|
-
│ └── loader.py # Universal Skill Loader
|
|
71
|
+
│ └── loader.py # Universal Skill Loader and Model Adapter
|
|
65
72
|
├── templates/ # Boilerplate templates for new skills
|
|
66
73
|
│ └── python_skill/ # Standard template with required files
|
|
67
74
|
└── tests/ # Automated test suite
|
|
@@ -87,7 +94,16 @@ pip install -e .
|
|
|
87
94
|
|
|
88
95
|
> **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
96
|
|
|
90
|
-
### 2.
|
|
97
|
+
### 2. Verify your installation
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install "skillware[cli]"
|
|
101
|
+
skillware list
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This prints a table of all locally available skills and confirms the install and path resolution are working.
|
|
105
|
+
|
|
106
|
+
### 3. Configuration
|
|
91
107
|
|
|
92
108
|
Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
93
109
|
|
|
@@ -95,10 +111,14 @@ Create a `.env` file with your API keys (e.g., Google Gemini API Key):
|
|
|
95
111
|
GOOGLE_API_KEY="your_key"
|
|
96
112
|
```
|
|
97
113
|
|
|
98
|
-
###
|
|
114
|
+
### 4. Usage Example (Gemini)
|
|
115
|
+
|
|
116
|
+
This example requires the Google SDK optional extra: `pip install "skillware[gemini]"` (local dev: `pip install -e ".[gemini]"`). See the [Gemini usage guide](docs/usage/gemini.md) for setup details.
|
|
99
117
|
|
|
100
118
|
```python
|
|
101
|
-
import
|
|
119
|
+
import os
|
|
120
|
+
import google.genai as genai
|
|
121
|
+
from google.genai import types
|
|
102
122
|
from skillware.core.loader import SkillLoader
|
|
103
123
|
from skillware.core.env import load_env_file
|
|
104
124
|
|
|
@@ -107,35 +127,63 @@ load_env_file()
|
|
|
107
127
|
|
|
108
128
|
# 1. Load the Skill from the Registry
|
|
109
129
|
# The loader reads the code, manifest, and instructions automatically
|
|
110
|
-
skill_bundle = SkillLoader.load_skill("
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
model = genai.GenerativeModel(
|
|
114
|
-
'gemini-2.5-flash',
|
|
115
|
-
tools=[SkillLoader.to_gemini_tool(skill_bundle)], # The "Adapter"
|
|
116
|
-
system_instruction=skill_bundle['instructions'] # The "Mind"
|
|
130
|
+
skill_bundle = SkillLoader.load_skill("finance/wallet_screening")
|
|
131
|
+
skill = skill_bundle["module"].WalletScreeningSkill(
|
|
132
|
+
config={"ETHERSCAN_API_KEY": os.environ.get("ETHERSCAN_API_KEY")}
|
|
117
133
|
)
|
|
118
|
-
|
|
134
|
+
|
|
135
|
+
# 2. Client & Tool Setup
|
|
136
|
+
client = genai.Client()
|
|
137
|
+
tool = SkillLoader.to_gemini_tool(skill_bundle) # The "Adapter"
|
|
138
|
+
system_instruction = skill_bundle['instructions'] # The "Mind"
|
|
119
139
|
|
|
120
140
|
# 3. Agent Loop
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
141
|
+
response = client.models.generate_content(
|
|
142
|
+
model="gemini-2.5-flash",
|
|
143
|
+
contents="Screen wallet 0xd8dA... for risks.",
|
|
144
|
+
config=types.GenerateContentConfig(
|
|
145
|
+
tools=[tool],
|
|
146
|
+
system_instruction=system_instruction,
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
for part in response.candidates[0].content.parts:
|
|
151
|
+
if part.function_call:
|
|
152
|
+
result = skill.execute(dict(part.function_call.args))
|
|
153
|
+
follow_up = client.models.generate_content(
|
|
154
|
+
model="gemini-2.5-flash",
|
|
155
|
+
contents=[
|
|
156
|
+
"Use this tool result to answer the original request.",
|
|
157
|
+
{
|
|
158
|
+
"function_response": {
|
|
159
|
+
"name": part.function_call.name,
|
|
160
|
+
"response": {"result": result},
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
config=types.GenerateContentConfig(
|
|
165
|
+
tools=[tool],
|
|
166
|
+
system_instruction=system_instruction,
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
print(follow_up.text)
|
|
170
|
+
else:
|
|
171
|
+
print(part.text)
|
|
124
172
|
```
|
|
125
173
|
|
|
174
|
+
For other providers and shared integration patterns, see the [usage guides index](docs/usage/README.md), [agent loops](docs/usage/agent_loops.md), [Gemini](docs/usage/gemini.md), [Claude](docs/usage/claude.md), [OpenAI](docs/usage/openai.md), [DeepSeek](docs/usage/deepseek.md), [Ollama](docs/usage/ollama.md), [API keys for skills](docs/usage/api_keys.md), and the [skill usage template](docs/usage/skill_usage_template.md) for contributors.
|
|
175
|
+
|
|
126
176
|
## Documentation
|
|
127
177
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
* **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
|
|
138
|
-
* **[Skill Library](docs/skills/README.md)**: Available capabilities.
|
|
178
|
+
| Topic | Link |
|
|
179
|
+
| :--- | :--- |
|
|
180
|
+
| Introduction | [docs/introduction.md](docs/introduction.md) |
|
|
181
|
+
| Testing | [docs/TESTING.md](docs/TESTING.md) |
|
|
182
|
+
| Skill library | [docs/skills/README.md](docs/skills/README.md) |
|
|
183
|
+
| Usage guides | [index](docs/usage/README.md) — [Gemini](docs/usage/gemini.md) · [Claude](docs/usage/claude.md) · [OpenAI](docs/usage/openai.md) · [DeepSeek](docs/usage/deepseek.md) · [Ollama](docs/usage/ollama.md); [agent loops](docs/usage/agent_loops.md); [API keys](docs/usage/api_keys.md) |
|
|
184
|
+
| Examples index | [examples/README.md](examples/README.md) |
|
|
185
|
+
| CLI | [docs/usage/cli.md](docs/usage/cli.md) |
|
|
186
|
+
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) · [agent workflow](docs/contributing/ai_native_workflow.md) |
|
|
139
187
|
|
|
140
188
|
## Contributing
|
|
141
189
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "skillware"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
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-genai",
|
|
43
|
+
]
|
|
44
|
+
claude = [
|
|
45
|
+
"anthropic",
|
|
46
|
+
]
|
|
47
|
+
openai = [
|
|
48
|
+
"openai",
|
|
49
|
+
]
|
|
50
|
+
office = [
|
|
51
|
+
"pymupdf",
|
|
52
|
+
]
|
|
53
|
+
all = [
|
|
54
|
+
"rich>=13.0",
|
|
55
|
+
"google-genai",
|
|
56
|
+
"anthropic",
|
|
57
|
+
"openai",
|
|
58
|
+
"pymupdf",
|
|
59
|
+
]
|
|
37
60
|
|
|
38
61
|
[tool.setuptools]
|
|
39
62
|
include-package-data = true
|
|
@@ -21,7 +21,7 @@ parameters:
|
|
|
21
21
|
required:
|
|
22
22
|
- user_prompt
|
|
23
23
|
requirements:
|
|
24
|
-
- google
|
|
24
|
+
- google-genai
|
|
25
25
|
constitution: |
|
|
26
26
|
1. COMPLIANCE: Do not invent or hallucinate financial regulations. Base all enforcement strictly on the provided MiCA corpus blocks.
|
|
27
27
|
2. FOCUS: Act exclusively as a compliance firewall and RAG engine; retrieve relevant chunks incrementally.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
3
|
from typing import Any, Dict, List
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
from skillware.core.base_skill import BaseSkill
|
|
6
6
|
|
|
7
7
|
|
|
@@ -207,11 +207,43 @@ class MiCAModuleSkill(BaseSkill):
|
|
|
207
207
|
"""
|
|
208
208
|
|
|
209
209
|
try:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
210
|
+
import google.genai as genai
|
|
211
|
+
from google.genai import types
|
|
212
|
+
except ImportError:
|
|
213
|
+
return {
|
|
214
|
+
"policy_status": "CAUTION",
|
|
215
|
+
"gemini_evaluator_feedback": {
|
|
216
|
+
"grade": "N/A",
|
|
217
|
+
"holes_found": "google-genai is not installed.",
|
|
218
|
+
"suggestion": "Proceed manually integrating the extracted logic.",
|
|
219
|
+
},
|
|
220
|
+
"final_context_for_agent": (
|
|
221
|
+
f"Output your final answer seamlessly integrating and adhering to these MiCA rules:\n{context}"
|
|
222
|
+
),
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
api_key = os.environ.get("GOOGLE_API_KEY")
|
|
226
|
+
if not api_key:
|
|
227
|
+
return {
|
|
228
|
+
"policy_status": "CAUTION",
|
|
229
|
+
"gemini_evaluator_feedback": {
|
|
230
|
+
"grade": "N/A",
|
|
231
|
+
"holes_found": "GOOGLE_API_KEY is not configured.",
|
|
232
|
+
"suggestion": "Proceed manually integrating the extracted logic.",
|
|
233
|
+
},
|
|
234
|
+
"final_context_for_agent": (
|
|
235
|
+
f"Output your final answer seamlessly integrating and adhering to these MiCA rules:\n{context}"
|
|
236
|
+
),
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
try:
|
|
240
|
+
client = genai.Client(api_key=api_key)
|
|
241
|
+
resp = client.models.generate_content(
|
|
242
|
+
model=model_name,
|
|
243
|
+
contents=prompt_payload,
|
|
244
|
+
config=types.GenerateContentConfig(
|
|
245
|
+
response_mime_type="application/json",
|
|
246
|
+
temperature=0.0,
|
|
215
247
|
),
|
|
216
248
|
)
|
|
217
249
|
return json.loads(resp.text)
|
|
@@ -11,9 +11,11 @@ from bs4 import BeautifulSoup
|
|
|
11
11
|
from skillware.core.base_skill import BaseSkill
|
|
12
12
|
|
|
13
13
|
try:
|
|
14
|
-
import google.
|
|
14
|
+
import google.genai as genai
|
|
15
|
+
from google.genai import types
|
|
15
16
|
except ImportError: # pragma: no cover - dependency is optional at runtime
|
|
16
17
|
genai = None
|
|
18
|
+
types = None
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class TOSEvaluatorSkill(BaseSkill):
|
|
@@ -458,14 +460,13 @@ class TOSEvaluatorSkill(BaseSkill):
|
|
|
458
460
|
"status": "skipped",
|
|
459
461
|
"reason": f"Unsupported llm_provider '{normalized['llm_provider']}'.",
|
|
460
462
|
}
|
|
461
|
-
if genai is None:
|
|
462
|
-
return {"status": "skipped", "reason": "google-
|
|
463
|
+
if genai is None or types is None:
|
|
464
|
+
return {"status": "skipped", "reason": "google-genai is not installed."}
|
|
463
465
|
|
|
464
466
|
api_key = os.environ.get("GOOGLE_API_KEY")
|
|
465
467
|
if not api_key:
|
|
466
468
|
return {"status": "skipped", "reason": "GOOGLE_API_KEY is not configured."}
|
|
467
469
|
|
|
468
|
-
genai.configure(api_key=api_key)
|
|
469
470
|
prompt = {
|
|
470
471
|
"target_url": normalized["target_url"],
|
|
471
472
|
"intended_action": normalized["intended_action"],
|
|
@@ -479,11 +480,13 @@ class TOSEvaluatorSkill(BaseSkill):
|
|
|
479
480
|
}
|
|
480
481
|
|
|
481
482
|
try:
|
|
482
|
-
|
|
483
|
-
response =
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
483
|
+
client = genai.Client(api_key=api_key)
|
|
484
|
+
response = client.models.generate_content(
|
|
485
|
+
model=normalized["llm_model"],
|
|
486
|
+
contents=json.dumps(prompt, ensure_ascii=True),
|
|
487
|
+
config=types.GenerateContentConfig(
|
|
488
|
+
response_mime_type="application/json",
|
|
489
|
+
temperature=0.0,
|
|
487
490
|
),
|
|
488
491
|
)
|
|
489
492
|
parsed = json.loads(response.text)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Novelty Extractor",
|
|
3
|
+
"description": "Filters a text dataset by semantic novelty, retaining only chunks that carry new information above a configurable threshold.",
|
|
4
|
+
"icon": "filter",
|
|
5
|
+
"ui_schema": {
|
|
6
|
+
"dataset_chunk": {
|
|
7
|
+
"ui:widget": "textarea",
|
|
8
|
+
"ui:placeholder": "Paste your raw text dataset here..."
|
|
9
|
+
},
|
|
10
|
+
"novelty_threshold": {
|
|
11
|
+
"ui:widget": "range",
|
|
12
|
+
"ui:options": {
|
|
13
|
+
"min": 0.0,
|
|
14
|
+
"max": 1.0,
|
|
15
|
+
"step": 0.05
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"baseline_chunks": {
|
|
19
|
+
"ui:widget": "textarea",
|
|
20
|
+
"ui:placeholder": "Optional. Paste distilled_content from a previous call here..."
|
|
21
|
+
},
|
|
22
|
+
"chunk_strategy": {
|
|
23
|
+
"ui:widget": "select",
|
|
24
|
+
"ui:options": {
|
|
25
|
+
"enumOptions": [
|
|
26
|
+
{"value": "paragraph", "label": "Paragraph"},
|
|
27
|
+
{"value": "sentence", "label": "Sentence"}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"issuer": {
|
|
33
|
+
"name": "Martin Rizzo Lozano",
|
|
34
|
+
"email": "rizzolozanomartin@gmail.com",
|
|
35
|
+
"github": "rizzoMartin"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Novelty Extractor
|
|
2
|
+
|
|
3
|
+
You are an agent equipped with the Novelty Extractor skill. This skill filters
|
|
4
|
+
large text datasets by semantic similarity, retaining only chunks that carry
|
|
5
|
+
genuinely new information.
|
|
6
|
+
|
|
7
|
+
## When to invoke this skill
|
|
8
|
+
|
|
9
|
+
Invoke `data_engineering/novelty_extractor` when:
|
|
10
|
+
|
|
11
|
+
- You need to distill a large corpus into high-signal content before passing
|
|
12
|
+
it to a model or storing it.
|
|
13
|
+
- You are processing a dataset in multiple turns and want to avoid redundancy
|
|
14
|
+
across turns by passing prior output as `baseline_chunks`.
|
|
15
|
+
- A user asks you to remove repetitive or redundant content from a document
|
|
16
|
+
or dataset.
|
|
17
|
+
|
|
18
|
+
## Parameters
|
|
19
|
+
|
|
20
|
+
- `dataset_chunk` (required): The raw text to filter.
|
|
21
|
+
- `novelty_threshold` (required): A float between 0.0 and 1.0. Chunks with
|
|
22
|
+
maximum cosine similarity to already-seen content below this value are kept.
|
|
23
|
+
Lower values mean stricter filtering. A value of 0.85 is a sensible default
|
|
24
|
+
for most corpora.
|
|
25
|
+
- `baseline_chunks` (optional): Text from a previous call's `distilled_content`.
|
|
26
|
+
Pass this to filter consistently across multiple turns.
|
|
27
|
+
- `chunk_strategy` (optional): How to split the input. Use `"paragraph"`
|
|
28
|
+
(default) for documents with clear paragraph breaks, or `"sentence"` for
|
|
29
|
+
denser text.
|
|
30
|
+
|
|
31
|
+
## Interpreting the output
|
|
32
|
+
|
|
33
|
+
- `distilled_content`: The filtered text. Pass this to downstream tasks or
|
|
34
|
+
store it as the new baseline for the next turn.
|
|
35
|
+
- `compression_ratio`: The percentage of input chunks that were dropped. A
|
|
36
|
+
high ratio (above 80%) may indicate the threshold is too strict or the
|
|
37
|
+
input is highly repetitive.
|
|
38
|
+
- `redundant_chunks_dropped`: The raw count of discarded chunks. Use this
|
|
39
|
+
to audit filtering behavior.
|
|
40
|
+
|
|
41
|
+
## Handling edge cases
|
|
42
|
+
|
|
43
|
+
- If `distilled_content` is empty and no error is returned, all input chunks
|
|
44
|
+
were too similar to the baseline. Consider lowering `novelty_threshold`.
|
|
45
|
+
- If an `error` key is present in the output, the skill encountered an
|
|
46
|
+
unexpected failure. Inspect the value and retry with sanitized input.
|
|
47
|
+
- The first call without a baseline always keeps the first chunk regardless
|
|
48
|
+
of threshold, since there is nothing to compare against.
|
|
49
|
+
|
|
50
|
+
## Multi-turn example
|
|
51
|
+
|
|
52
|
+
Turn 1: pass the first batch without baseline.
|
|
53
|
+
Turn 2: pass the next batch with `baseline_chunks` set to the previous
|
|
54
|
+
`distilled_content`.
|
|
55
|
+
Repeat until the full corpus is processed.
|
|
56
|
+
|
|
57
|
+
Note: the skill only filters each batch against the provided baseline. It does
|
|
58
|
+
not accumulate results across turns automatically. The caller is responsible
|
|
59
|
+
for concatenating `distilled_content` from each turn to build the full
|
|
60
|
+
distilled dataset.
|