skillware 0.2.9__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.9/skillware.egg-info → skillware-0.3.1}/PKG-INFO +70 -33
- {skillware-0.2.9 → skillware-0.3.1}/README.md +67 -30
- {skillware-0.2.9 → skillware-0.3.1}/pyproject.toml +3 -3
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/mica_module/manifest.yaml +1 -1
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/mica_module/skill.py +38 -6
- {skillware-0.2.9 → 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.9 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/skill.py +8 -9
- {skillware-0.2.9 → skillware-0.3.1}/skillware/core/loader.py +16 -5
- {skillware-0.2.9 → skillware-0.3.1/skillware.egg-info}/PKG-INFO +70 -33
- {skillware-0.2.9 → skillware-0.3.1}/skillware.egg-info/SOURCES.txt +6 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware.egg-info/requires.txt +2 -2
- {skillware-0.2.9 → skillware-0.3.1}/LICENSE +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/MANIFEST.in +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/setup.cfg +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/mica_module/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/mica_module/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/mica_module/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/mica_module/mica_corpus.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/pii_masker/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/pii_masker/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/pii_masker/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/pii_masker/manifest.yaml +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/pii_masker/skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/tos_evaluator/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/tos_evaluator/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/tos_evaluator/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/tos_evaluator/manifest.yaml +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/compliance/tos_evaluator/test_skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/data_engineering/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/data_engineering/synthetic_generator/manifest.yaml +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/dev_tools/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/dev_tools/issue_resolver/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/dev_tools/issue_resolver/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/dev_tools/issue_resolver/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/dev_tools/issue_resolver/manifest.yaml +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/dev_tools/issue_resolver/skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/dev_tools/issue_resolver/test_skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/data/entities.ftm.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/data/malicious_scs_2025.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/data/normalized_fbi_lazarus_20250722_180019.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/data/normalized_israel_nbctf_20250722_180019.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/data/normalized_uniswap_trm.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/maintenance/normalization_tool.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/maintenance/normalize_uniswap_trm.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/manifest.yaml +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/finance/wallet_screening/skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/office/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/office/pdf_form_filler/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/office/pdf_form_filler/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/office/pdf_form_filler/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/office/pdf_form_filler/manifest.yaml +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/office/pdf_form_filler/skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/office/pdf_form_filler/utils.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/optimization/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/optimization/prompt_rewriter/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/optimization/prompt_rewriter/card.json +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/optimization/prompt_rewriter/instructions.md +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/optimization/prompt_rewriter/manifest.yaml +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skills/optimization/prompt_rewriter/skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware/cli.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware/core/__init__.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware/core/base_skill.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware/core/env.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware.egg-info/dependency_links.txt +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware.egg-info/entry_points.txt +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/skillware.egg-info/top_level.txt +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/tests/test_cli.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/tests/test_loader.py +0 -0
- {skillware-0.2.9 → skillware-0.3.1}/tests/test_mica_module.py +0 -0
- {skillware-0.2.9 → 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
|
|
@@ -45,7 +45,7 @@ Requires-Dist: black; extra == "dev"
|
|
|
45
45
|
Provides-Extra: cli
|
|
46
46
|
Requires-Dist: rich>=13.0; extra == "cli"
|
|
47
47
|
Provides-Extra: gemini
|
|
48
|
-
Requires-Dist: google-
|
|
48
|
+
Requires-Dist: google-genai; extra == "gemini"
|
|
49
49
|
Provides-Extra: claude
|
|
50
50
|
Requires-Dist: anthropic; extra == "claude"
|
|
51
51
|
Provides-Extra: openai
|
|
@@ -54,7 +54,7 @@ Provides-Extra: office
|
|
|
54
54
|
Requires-Dist: pymupdf; extra == "office"
|
|
55
55
|
Provides-Extra: all
|
|
56
56
|
Requires-Dist: rich>=13.0; extra == "all"
|
|
57
|
-
Requires-Dist: google-
|
|
57
|
+
Requires-Dist: google-genai; extra == "all"
|
|
58
58
|
Requires-Dist: anthropic; extra == "all"
|
|
59
59
|
Requires-Dist: openai; extra == "all"
|
|
60
60
|
Requires-Dist: pymupdf; extra == "all"
|
|
@@ -103,28 +103,34 @@ A **Skill** in this framework provides everything an Agent needs to master a dom
|
|
|
103
103
|
3. **Governance**: Constitution and safety boundaries.
|
|
104
104
|
4. **Interface**: Standardized schemas for LLM tool calling.
|
|
105
105
|
|
|
106
|
+
### Skill library
|
|
107
|
+
|
|
108
|
+
Browse capabilities by category in the [Skill library](docs/skills/README.md).
|
|
109
|
+
|
|
106
110
|
## Architecture
|
|
107
111
|
|
|
108
|
-
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).
|
|
109
115
|
|
|
110
116
|
```text
|
|
111
117
|
Skillware/
|
|
112
|
-
├── docs/ #
|
|
113
|
-
├── examples/ #
|
|
114
|
-
│ └── 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, ...)
|
|
115
120
|
├── skills/ # Skill Registry
|
|
116
121
|
│ └── category/ # Domain boundaries (e.g., finance)
|
|
117
122
|
│ └── skill_name/ # The Skill bundle
|
|
118
123
|
│ ├── manifest.yaml # Definition, schema, and constitution
|
|
119
124
|
│ ├── skill.py # Executable Python logic
|
|
120
125
|
│ ├── instructions.md # Cognitive map for the LLM
|
|
121
|
-
│
|
|
126
|
+
│ ├── card.json # Optional UI presentation metadata
|
|
127
|
+
│ └── test_skill.py # Unit tests and schema validation
|
|
122
128
|
├── skillware/ # Core Framework Package
|
|
123
129
|
│ ├── cli.py # Command-line interface
|
|
124
130
|
│ └── core/
|
|
125
131
|
│ ├── base_skill.py # Abstract Base Class for skills
|
|
126
132
|
│ ├── env.py # Environment Management
|
|
127
|
-
│ └── loader.py # Universal Skill Loader
|
|
133
|
+
│ └── loader.py # Universal Skill Loader and Model Adapter
|
|
128
134
|
├── templates/ # Boilerplate templates for new skills
|
|
129
135
|
│ └── python_skill/ # Standard template with required files
|
|
130
136
|
└── tests/ # Automated test suite
|
|
@@ -169,8 +175,12 @@ GOOGLE_API_KEY="your_key"
|
|
|
169
175
|
|
|
170
176
|
### 4. Usage Example (Gemini)
|
|
171
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.
|
|
179
|
+
|
|
172
180
|
```python
|
|
173
|
-
import
|
|
181
|
+
import os
|
|
182
|
+
import google.genai as genai
|
|
183
|
+
from google.genai import types
|
|
174
184
|
from skillware.core.loader import SkillLoader
|
|
175
185
|
from skillware.core.env import load_env_file
|
|
176
186
|
|
|
@@ -179,36 +189,63 @@ load_env_file()
|
|
|
179
189
|
|
|
180
190
|
# 1. Load the Skill from the Registry
|
|
181
191
|
# The loader reads the code, manifest, and instructions automatically
|
|
182
|
-
skill_bundle = SkillLoader.load_skill("
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
model = genai.GenerativeModel(
|
|
186
|
-
'gemini-2.5-flash',
|
|
187
|
-
tools=[SkillLoader.to_gemini_tool(skill_bundle)], # The "Adapter"
|
|
188
|
-
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")}
|
|
189
195
|
)
|
|
190
|
-
|
|
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"
|
|
191
201
|
|
|
192
202
|
# 3. Agent Loop
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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)
|
|
196
234
|
```
|
|
197
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
|
+
|
|
198
238
|
## Documentation
|
|
199
239
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
* **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
|
|
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.
|
|
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) |
|
|
212
249
|
|
|
213
250
|
## Contributing
|
|
214
251
|
|
|
@@ -41,28 +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
|
|
61
67
|
│ ├── cli.py # Command-line interface
|
|
62
68
|
│ └── core/
|
|
63
69
|
│ ├── base_skill.py # Abstract Base Class for skills
|
|
64
70
|
│ ├── env.py # Environment Management
|
|
65
|
-
│ └── loader.py # Universal Skill Loader
|
|
71
|
+
│ └── loader.py # Universal Skill Loader and Model Adapter
|
|
66
72
|
├── templates/ # Boilerplate templates for new skills
|
|
67
73
|
│ └── python_skill/ # Standard template with required files
|
|
68
74
|
└── tests/ # Automated test suite
|
|
@@ -107,8 +113,12 @@ GOOGLE_API_KEY="your_key"
|
|
|
107
113
|
|
|
108
114
|
### 4. Usage Example (Gemini)
|
|
109
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.
|
|
117
|
+
|
|
110
118
|
```python
|
|
111
|
-
import
|
|
119
|
+
import os
|
|
120
|
+
import google.genai as genai
|
|
121
|
+
from google.genai import types
|
|
112
122
|
from skillware.core.loader import SkillLoader
|
|
113
123
|
from skillware.core.env import load_env_file
|
|
114
124
|
|
|
@@ -117,36 +127,63 @@ load_env_file()
|
|
|
117
127
|
|
|
118
128
|
# 1. Load the Skill from the Registry
|
|
119
129
|
# The loader reads the code, manifest, and instructions automatically
|
|
120
|
-
skill_bundle = SkillLoader.load_skill("
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
model = genai.GenerativeModel(
|
|
124
|
-
'gemini-2.5-flash',
|
|
125
|
-
tools=[SkillLoader.to_gemini_tool(skill_bundle)], # The "Adapter"
|
|
126
|
-
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")}
|
|
127
133
|
)
|
|
128
|
-
|
|
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"
|
|
129
139
|
|
|
130
140
|
# 3. Agent Loop
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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)
|
|
134
172
|
```
|
|
135
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
|
+
|
|
136
176
|
## Documentation
|
|
137
177
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
|
|
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.
|
|
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) |
|
|
150
187
|
|
|
151
188
|
## Contributing
|
|
152
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 = [
|
|
@@ -39,7 +39,7 @@ cli = [
|
|
|
39
39
|
"rich>=13.0",
|
|
40
40
|
]
|
|
41
41
|
gemini = [
|
|
42
|
-
"google-
|
|
42
|
+
"google-genai",
|
|
43
43
|
]
|
|
44
44
|
claude = [
|
|
45
45
|
"anthropic",
|
|
@@ -52,7 +52,7 @@ office = [
|
|
|
52
52
|
]
|
|
53
53
|
all = [
|
|
54
54
|
"rich>=13.0",
|
|
55
|
-
"google-
|
|
55
|
+
"google-genai",
|
|
56
56
|
"anthropic",
|
|
57
57
|
"openai",
|
|
58
58
|
"pymupdf",
|
|
@@ -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.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: "data_engineering/novelty_extractor"
|
|
2
|
+
version: "0.1.0"
|
|
3
|
+
description: "Filters a text dataset by semantic novelty, retaining only chunks that carry new information above a configurable threshold."
|
|
4
|
+
issuer:
|
|
5
|
+
name: Martin Rizzo Lozano
|
|
6
|
+
email: rizzolozanomartin@gmail.com
|
|
7
|
+
github: rizzoMartin
|
|
8
|
+
org: ""
|
|
9
|
+
parameters:
|
|
10
|
+
type: object
|
|
11
|
+
properties:
|
|
12
|
+
dataset_chunk:
|
|
13
|
+
type: string
|
|
14
|
+
description: "Raw text to filter. Will be split into chunks before embedding."
|
|
15
|
+
novelty_threshold:
|
|
16
|
+
type: number
|
|
17
|
+
description: "Similarity ceiling (0.0-1.0). Chunks with max cosine similarity below this value are kept. Lower = stricter filtering."
|
|
18
|
+
baseline_chunks:
|
|
19
|
+
type: string
|
|
20
|
+
description: "Optional. Previously seen text to compare against. Pass distilled_content from a prior call to filter across turns."
|
|
21
|
+
chunk_strategy:
|
|
22
|
+
type: string
|
|
23
|
+
description: "How to split dataset_chunk before embedding. 'paragraph' (default) or 'sentence'."
|
|
24
|
+
required:
|
|
25
|
+
- dataset_chunk
|
|
26
|
+
- novelty_threshold
|
|
27
|
+
outputs:
|
|
28
|
+
distilled_content:
|
|
29
|
+
type: string
|
|
30
|
+
description: "Novel chunks joined by newline."
|
|
31
|
+
compression_ratio:
|
|
32
|
+
type: string
|
|
33
|
+
description: "Percentage of input chunks that were dropped."
|
|
34
|
+
redundant_chunks_dropped:
|
|
35
|
+
type: integer
|
|
36
|
+
description: "Number of chunks discarded as redundant."
|
|
37
|
+
requirements:
|
|
38
|
+
- fastembed
|
|
39
|
+
- numpy
|
|
40
|
+
constitution: |
|
|
41
|
+
1. STATELESS: Do not retain any state between calls. All context must be passed explicitly via baseline_chunks.
|
|
42
|
+
2. DETERMINISM: Given the same inputs, always return the same outputs.
|
|
43
|
+
3. PRIVACY: Do not log, store, or transmit any content from dataset_chunk or baseline_chunks.
|
|
44
|
+
4. SCOPE: Only filter for semantic novelty. Do not summarize, rewrite, or alter the content of kept chunks.
|
|
45
|
+
5. TRANSPARENCY: Always report compression_ratio and redundant_chunks_dropped so the caller can audit the filtering.
|