skillware 0.3.6__tar.gz → 0.3.8__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.
Files changed (125) hide show
  1. {skillware-0.3.6 → skillware-0.3.8}/MANIFEST.in +1 -0
  2. {skillware-0.3.6/skillware.egg-info → skillware-0.3.8}/PKG-INFO +20 -6
  3. {skillware-0.3.6 → skillware-0.3.8}/README.md +19 -5
  4. skillware-0.3.8/examples/README.md +61 -0
  5. {skillware-0.3.6 → skillware-0.3.8}/pyproject.toml +1 -1
  6. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/card.json +4 -4
  7. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/instructions.md +5 -5
  8. skillware-0.3.8/skills/wellness/mental_coach/__init__.py +3 -0
  9. skillware-0.3.8/skills/wellness/mental_coach/card.json +25 -0
  10. skillware-0.3.8/skills/wellness/mental_coach/constraints.py +93 -0
  11. skillware-0.3.8/skills/wellness/mental_coach/crisis_gate.py +175 -0
  12. skillware-0.3.8/skills/wellness/mental_coach/instructions.md +37 -0
  13. skillware-0.3.8/skills/wellness/mental_coach/kb/corpus.json +214 -0
  14. skillware-0.3.8/skills/wellness/mental_coach/kb/crisis_resources.json +219 -0
  15. skillware-0.3.8/skills/wellness/mental_coach/kb/hard_constraints.yaml +86 -0
  16. skillware-0.3.8/skills/wellness/mental_coach/kb_provider.py +101 -0
  17. skillware-0.3.8/skills/wellness/mental_coach/manifest.yaml +66 -0
  18. skillware-0.3.8/skills/wellness/mental_coach/resources.py +71 -0
  19. skillware-0.3.8/skills/wellness/mental_coach/skill.py +396 -0
  20. skillware-0.3.8/skills/wellness/mental_coach/test_skill.py +112 -0
  21. skillware-0.3.8/skillware/cli.py +725 -0
  22. skillware-0.3.8/skillware/core/__init__.py +0 -0
  23. {skillware-0.3.6 → skillware-0.3.8/skillware.egg-info}/PKG-INFO +20 -6
  24. {skillware-0.3.6 → skillware-0.3.8}/skillware.egg-info/SOURCES.txt +15 -1
  25. skillware-0.3.8/tests/test_cli.py +599 -0
  26. {skillware-0.3.6 → skillware-0.3.8}/tests/test_skill_issuer.py +11 -0
  27. skillware-0.3.6/skillware/cli.py +0 -351
  28. skillware-0.3.6/tests/test_cli.py +0 -281
  29. skillware-0.3.6/tests/test_mica_module.py +0 -66
  30. {skillware-0.3.6 → skillware-0.3.8}/LICENSE +0 -0
  31. {skillware-0.3.6 → skillware-0.3.8}/setup.cfg +0 -0
  32. {skillware-0.3.6 → skillware-0.3.8}/skills/__init__.py +0 -0
  33. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/__init__.py +0 -0
  34. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/mica_module/__init__.py +0 -0
  35. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/mica_module/card.json +0 -0
  36. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/mica_module/instructions.md +0 -0
  37. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/mica_module/manifest.yaml +0 -0
  38. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/mica_module/mica_corpus.json +0 -0
  39. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/mica_module/skill.py +0 -0
  40. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/mica_module/test_skill.py +0 -0
  41. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/pii_masker/__init__.py +0 -0
  42. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/pii_masker/card.json +0 -0
  43. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/pii_masker/instructions.md +0 -0
  44. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/pii_masker/manifest.yaml +0 -0
  45. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/pii_masker/skill.py +0 -0
  46. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/pii_masker/test_skill.py +0 -0
  47. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/tos_evaluator/__init__.py +0 -0
  48. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/tos_evaluator/card.json +0 -0
  49. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/tos_evaluator/instructions.md +0 -0
  50. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/tos_evaluator/manifest.yaml +0 -0
  51. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/tos_evaluator/skill.py +0 -0
  52. {skillware-0.3.6 → skillware-0.3.8}/skills/compliance/tos_evaluator/test_skill.py +0 -0
  53. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/__init__.py +0 -0
  54. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/novelty_extractor/__init__.py +0 -0
  55. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/novelty_extractor/card.json +0 -0
  56. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/novelty_extractor/instructions.md +0 -0
  57. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/novelty_extractor/manifest.yaml +0 -0
  58. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/novelty_extractor/skill.py +0 -0
  59. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/novelty_extractor/test_skill.py +0 -0
  60. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/synthetic_generator/__init__.py +0 -0
  61. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/synthetic_generator/card.json +0 -0
  62. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/synthetic_generator/instructions.md +0 -0
  63. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/synthetic_generator/manifest.yaml +0 -0
  64. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/synthetic_generator/skill.py +0 -0
  65. {skillware-0.3.6 → skillware-0.3.8}/skills/data_engineering/synthetic_generator/test_skill.py +0 -0
  66. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/__init__.py +0 -0
  67. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/__init__.py +0 -0
  68. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/abis.py +0 -0
  69. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/card.json +0 -0
  70. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/config.yaml.example +0 -0
  71. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/data/addressbook.yaml +0 -0
  72. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/data/chains.yaml +0 -0
  73. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/data/tokens.yaml +0 -0
  74. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/instructions.md +0 -0
  75. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/manifest.yaml +0 -0
  76. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/skill.py +0 -0
  77. {skillware-0.3.6 → skillware-0.3.8}/skills/defi/evm_tx_handler/test_skill.py +0 -0
  78. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/__init__.py +0 -0
  79. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/issue_resolver/__init__.py +0 -0
  80. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/issue_resolver/card.json +0 -0
  81. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/issue_resolver/instructions.md +0 -0
  82. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/issue_resolver/manifest.yaml +0 -0
  83. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/issue_resolver/skill.py +0 -0
  84. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/issue_resolver/test_skill.py +0 -0
  85. {skillware-0.3.6 → skillware-0.3.8}/skills/dev_tools/issue_resolver/workflow.py +0 -0
  86. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/__init__.py +0 -0
  87. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/__init__.py +0 -0
  88. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/data/entities.ftm.json +0 -0
  89. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/data/malicious_scs_2025.json +0 -0
  90. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/data/normalized_fbi_lazarus_20250722_180019.json +0 -0
  91. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/data/normalized_israel_nbctf_20250722_180019.json +0 -0
  92. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/data/normalized_uniswap_trm.json +0 -0
  93. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/maintenance/normalization_tool.py +0 -0
  94. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/maintenance/normalize_uniswap_trm.py +0 -0
  95. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/manifest.yaml +0 -0
  96. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/skill.py +0 -0
  97. {skillware-0.3.6 → skillware-0.3.8}/skills/finance/wallet_screening/test_skill.py +0 -0
  98. {skillware-0.3.6 → skillware-0.3.8}/skills/office/__init__.py +0 -0
  99. {skillware-0.3.6 → skillware-0.3.8}/skills/office/pdf_form_filler/__init__.py +0 -0
  100. {skillware-0.3.6 → skillware-0.3.8}/skills/office/pdf_form_filler/card.json +0 -0
  101. {skillware-0.3.6 → skillware-0.3.8}/skills/office/pdf_form_filler/instructions.md +0 -0
  102. {skillware-0.3.6 → skillware-0.3.8}/skills/office/pdf_form_filler/manifest.yaml +0 -0
  103. {skillware-0.3.6 → skillware-0.3.8}/skills/office/pdf_form_filler/skill.py +0 -0
  104. {skillware-0.3.6 → skillware-0.3.8}/skills/office/pdf_form_filler/test_skill.py +0 -0
  105. {skillware-0.3.6 → skillware-0.3.8}/skills/office/pdf_form_filler/utils.py +0 -0
  106. {skillware-0.3.6 → skillware-0.3.8}/skills/optimization/__init__.py +0 -0
  107. {skillware-0.3.6 → skillware-0.3.8}/skills/optimization/prompt_rewriter/__init__.py +0 -0
  108. {skillware-0.3.6 → skillware-0.3.8}/skills/optimization/prompt_rewriter/card.json +0 -0
  109. {skillware-0.3.6 → skillware-0.3.8}/skills/optimization/prompt_rewriter/instructions.md +0 -0
  110. {skillware-0.3.6 → skillware-0.3.8}/skills/optimization/prompt_rewriter/manifest.yaml +0 -0
  111. {skillware-0.3.6 → skillware-0.3.8}/skills/optimization/prompt_rewriter/skill.py +0 -0
  112. {skillware-0.3.6 → skillware-0.3.8}/skills/optimization/prompt_rewriter/test_skill.py +0 -0
  113. {skillware-0.3.6/skillware → skillware-0.3.8/skills/wellness}/__init__.py +0 -0
  114. {skillware-0.3.6/skillware/core → skillware-0.3.8/skillware}/__init__.py +0 -0
  115. {skillware-0.3.6 → skillware-0.3.8}/skillware/__main__.py +0 -0
  116. {skillware-0.3.6 → skillware-0.3.8}/skillware/core/base_skill.py +0 -0
  117. {skillware-0.3.6 → skillware-0.3.8}/skillware/core/env.py +0 -0
  118. {skillware-0.3.6 → skillware-0.3.8}/skillware/core/loader.py +0 -0
  119. {skillware-0.3.6 → skillware-0.3.8}/skillware/version_policy.py +0 -0
  120. {skillware-0.3.6 → skillware-0.3.8}/skillware.egg-info/dependency_links.txt +0 -0
  121. {skillware-0.3.6 → skillware-0.3.8}/skillware.egg-info/entry_points.txt +0 -0
  122. {skillware-0.3.6 → skillware-0.3.8}/skillware.egg-info/requires.txt +0 -0
  123. {skillware-0.3.6 → skillware-0.3.8}/skillware.egg-info/top_level.txt +0 -0
  124. {skillware-0.3.6 → skillware-0.3.8}/tests/test_loader.py +0 -0
  125. {skillware-0.3.6 → skillware-0.3.8}/tests/test_version_policy.py +0 -0
@@ -1,3 +1,4 @@
1
1
  graft skills
2
+ include examples/README.md
2
3
  global-exclude __pycache__
3
4
  global-exclude *.py[cod]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skillware
3
- Version: 0.3.6
3
+ Version: 0.3.8
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
@@ -79,7 +79,7 @@ Dynamic: license-file
79
79
 
80
80
  <div align="center">
81
81
  <img src="https://img.shields.io/badge/License-MIT-efcefa?style=flat-square" alt="License">
82
- <img src="https://img.shields.io/badge/Python-3.11+-bae6fd?style=flat-square" alt="Python Version">
82
+ <img src="https://img.shields.io/badge/Python-3.10+-bae6fd?style=flat-square" alt="Python Version">
83
83
  <a href="https://pypi.org/project/skillware/"><img src="https://img.shields.io/pypi/v/skillware?style=flat-square&color=bbf7d0" alt="PyPI Version"></a>
84
84
  </div>
85
85
 
@@ -150,6 +150,8 @@ Skillware/
150
150
 
151
151
  ## Quick Start
152
152
 
153
+ Requires **Python 3.10 or newer** (see `requires-python` in `pyproject.toml`).
154
+
153
155
  ### 1. Installation
154
156
 
155
157
  You can install Skillware directly from PyPI:
@@ -163,9 +165,11 @@ Or for development, clone the repository and install in editable mode:
163
165
  ```bash
164
166
  git clone https://github.com/arpahls/skillware.git
165
167
  cd skillware
166
- pip install -e .
168
+ pip install -e ".[dev,all]"
167
169
  ```
168
170
 
171
+ For documentation-only work, `pip install -e ".[dev]"` is enough. Skill and framework contributors should use `[dev,all]` to match CI (see [TESTING.md](docs/TESTING.md)).
172
+
169
173
  > **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.
170
174
 
171
175
  ### 2. Verify your installation
@@ -184,12 +188,22 @@ your PATH — use `python -m skillware list` as a fallback. See
184
188
 
185
189
  ### 3. Configuration
186
190
 
187
- Create a `.env` file with your API keys (e.g., Google Gemini API Key):
191
+ Copy the environment template and add your keys.
192
+
193
+ **Unix / macOS:**
194
+
195
+ ```bash
196
+ cp .env.example .env
197
+ ```
188
198
 
189
- ```ini
190
- GOOGLE_API_KEY="your_key"
199
+ **Windows (PowerShell):**
200
+
201
+ ```powershell
202
+ Copy-Item .env.example .env
191
203
  ```
192
204
 
205
+ Edit `.env` with agent keys (for example Gemini) and any keys your skills need. Agent keys power your LLM client; skill keys are declared per skill in the [Skill library](docs/skills/README.md). See [API keys for skills](docs/usage/api_keys.md) for setup, security, and framework variables.
206
+
193
207
  ### 4. Usage Example (Gemini)
194
208
 
195
209
  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.
@@ -8,7 +8,7 @@
8
8
 
9
9
  <div align="center">
10
10
  <img src="https://img.shields.io/badge/License-MIT-efcefa?style=flat-square" alt="License">
11
- <img src="https://img.shields.io/badge/Python-3.11+-bae6fd?style=flat-square" alt="Python Version">
11
+ <img src="https://img.shields.io/badge/Python-3.10+-bae6fd?style=flat-square" alt="Python Version">
12
12
  <a href="https://pypi.org/project/skillware/"><img src="https://img.shields.io/pypi/v/skillware?style=flat-square&color=bbf7d0" alt="PyPI Version"></a>
13
13
  </div>
14
14
 
@@ -79,6 +79,8 @@ Skillware/
79
79
 
80
80
  ## Quick Start
81
81
 
82
+ Requires **Python 3.10 or newer** (see `requires-python` in `pyproject.toml`).
83
+
82
84
  ### 1. Installation
83
85
 
84
86
  You can install Skillware directly from PyPI:
@@ -92,9 +94,11 @@ Or for development, clone the repository and install in editable mode:
92
94
  ```bash
93
95
  git clone https://github.com/arpahls/skillware.git
94
96
  cd skillware
95
- pip install -e .
97
+ pip install -e ".[dev,all]"
96
98
  ```
97
99
 
100
+ For documentation-only work, `pip install -e ".[dev]"` is enough. Skill and framework contributors should use `[dev,all]` to match CI (see [TESTING.md](docs/TESTING.md)).
101
+
98
102
  > **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.
99
103
 
100
104
  ### 2. Verify your installation
@@ -113,12 +117,22 @@ your PATH — use `python -m skillware list` as a fallback. See
113
117
 
114
118
  ### 3. Configuration
115
119
 
116
- Create a `.env` file with your API keys (e.g., Google Gemini API Key):
120
+ Copy the environment template and add your keys.
121
+
122
+ **Unix / macOS:**
123
+
124
+ ```bash
125
+ cp .env.example .env
126
+ ```
117
127
 
118
- ```ini
119
- GOOGLE_API_KEY="your_key"
128
+ **Windows (PowerShell):**
129
+
130
+ ```powershell
131
+ Copy-Item .env.example .env
120
132
  ```
121
133
 
134
+ Edit `.env` with agent keys (for example Gemini) and any keys your skills need. Agent keys power your LLM client; skill keys are declared per skill in the [Skill library](docs/skills/README.md). See [API keys for skills](docs/usage/api_keys.md) for setup, security, and framework variables.
135
+
122
136
  ### 4. Usage Example (Gemini)
123
137
 
124
138
  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.
@@ -0,0 +1,61 @@
1
+ # Skillware Examples Index
2
+
3
+ > **These are usage examples, not tests.** Runnable provider demos live here; automated tests live in `skills/**/test_skill.py` (bundle) and `tests/` (framework and optional maintainer depth). See [TESTING.md](../docs/TESTING.md).
4
+
5
+ Runnable examples in this directory show how to load Skillware skills, adapt
6
+ them for a provider, execute local skill logic, and return tool results to an
7
+ agent loop. From the repository root, run `skillware examples` or
8
+ `skillware list --examples` to browse the index in the terminal (see
9
+ [CLI reference](../docs/usage/cli.md)). Provider setup details live in the usage guides:
10
+
11
+ - [API keys for skills](../docs/usage/api_keys.md)
12
+ - [Gemini](../docs/usage/gemini.md)
13
+ - [Claude](../docs/usage/claude.md)
14
+ - [OpenAI](../docs/usage/openai.md)
15
+ - [DeepSeek](../docs/usage/deepseek.md)
16
+ - [Ollama](../docs/usage/ollama.md)
17
+ - [Agent loops](../docs/usage/agent_loops.md)
18
+
19
+ Use the package extra shown below when installing from PyPI:
20
+ `pip install "skillware[gemini]"`. For local development, use the same extra
21
+ with editable install: `pip install -e ".[gemini]"`.
22
+
23
+ ## Runnable Scripts
24
+
25
+ | Script | Skill ID | Provider | Required extra | Required env vars | Description |
26
+ | :--- | :--- | :--- | :--- | :--- | :--- |
27
+ | `mental_coach_demo.py` | `wellness/mental_coach` | Local execute | base install only | None | Demonstrates coaching, crisis escalation, and blocked clinical paths locally. |
28
+ | `build_dataset_demo.py` | `data_engineering/synthetic_generator` | Local execute (Gemini backend) | `[gemini]` | `GOOGLE_API_KEY` | Generates a JSONL synthetic dataset with the synthetic generator skill. |
29
+ | `claude_pdf_form_filler.py` | `office/pdf_form_filler` | Claude | `[claude]`, `[office]` | `ANTHROPIC_API_KEY` | Uses Claude with the PDF form filler skill to map instructions to fields. |
30
+ | `claude_tos_evaluator.py` | `compliance/tos_evaluator` | Claude | `[claude]` | `ANTHROPIC_API_KEY` | Runs a Claude tool loop for website automation policy review. |
31
+ | `claude_issue_resolver.py` | `dev_tools/issue_resolver` | Claude | `[claude]` | `ANTHROPIC_API_KEY`; optional `GITHUB_TOKEN` | Claude loop for GitHub issue analysis; fetches issue data after `prepare` (sample: issue #123). |
32
+ | `claude_wallet_check.py` | `finance/wallet_screening` | Claude | `[claude]` | `ANTHROPIC_API_KEY`, `ETHERSCAN_API_KEY` | Screens an Ethereum wallet and returns the result through a Claude tool loop. |
33
+ | `deepseek_tos_evaluator.py` | `compliance/tos_evaluator` | DeepSeek | `[openai]` | `DEEPSEEK_API_KEY` | Uses the OpenAI-compatible DeepSeek API for terms-of-service evaluation. |
34
+ | `gemini_pdf_form_filler.py` | `office/pdf_form_filler` | Gemini | `[gemini]`, `[office]` | `GOOGLE_API_KEY`, `ANTHROPIC_API_KEY` | Uses Gemini as the agent while the PDF skill calls Anthropic for form filling. |
35
+ | `gemini_tos_evaluator.py` | `compliance/tos_evaluator` | Gemini | `[gemini]` | `GOOGLE_API_KEY` | Runs the terms-of-service evaluator with a Gemini function-calling loop. |
36
+ | `gemini_wallet_check.py` | `finance/wallet_screening` | Gemini | `[gemini]` | `GOOGLE_API_KEY`, `ETHERSCAN_API_KEY` | Screens an Ethereum wallet with Gemini orchestration and Etherscan data. |
37
+ | `gemini_evm_tx_handler.py` | `defi/evm_tx_handler` | Gemini | `[gemini]` | `GOOGLE_API_KEY`; for live swaps also `AGENT_WALLET_PRIVATE_KEY`, `BASE_RPC_URL` or `ETHEREUM_RPC_URL`. Set `EVM_TX_HANDLER_EXAMPLE_DEMO=1` for mocked flow without keys. | Resolve → quote → preview → execute buy flow via Gemini tool loop (or demo mode). |
38
+ | `claude_evm_tx_handler.py` | `defi/evm_tx_handler` | Claude | `[claude]` | `ANTHROPIC_API_KEY`; for live swaps also `AGENT_WALLET_PRIVATE_KEY`, RPC URLs. Demo: `EVM_TX_HANDLER_EXAMPLE_DEMO=1`. | Claude tool loop for structured DeFi intent and optional execute after confirmation. |
39
+ | `mica_claude_flow.py` | `compliance/mica_module` | Claude | `[claude]` | `ANTHROPIC_API_KEY` | Runs a MiCA compliance agent loop through Claude. |
40
+ | `mica_ollama_flow.py` | `compliance/mica_module` | Ollama | No Skillware extra; install `ollama` separately | None | Runs a local Ollama MiCA flow with prompt-mode tool calling. |
41
+ | `mica_rag_flow.py` | `compliance/mica_module` | Gemini | `[gemini]` | `GOOGLE_API_KEY` | Runs the MiCA RAG flow with Gemini. |
42
+ | `ollama_skills_test.py` | `finance/wallet_screening`, `office/pdf_form_filler`, `optimization/prompt_rewriter` | Ollama | `[office]`; install `ollama` separately | `ETHERSCAN_API_KEY`, `ANTHROPIC_API_KEY` | Loads multiple skills and tests prompt-mode tool calling with Ollama. |
43
+ | `ollama_tos_evaluator.py` | `compliance/tos_evaluator` | Ollama | No Skillware extra; install `ollama` separately | None | Runs the terms-of-service evaluator with local Ollama prompt-mode calls. |
44
+ | `openai_tos_evaluator.py` | `compliance/tos_evaluator` | OpenAI | `[openai]` | `OPENAI_API_KEY` | Runs the terms-of-service evaluator with OpenAI function calling. |
45
+ | `pii_guardrail_flow.py` | `compliance/pii_masker` | Local execute | base install only | None | Demonstrates local PII masking before passing text to an external agent. |
46
+ | `prompt_compression_demo.py` | `optimization/prompt_rewriter` | Local execute | base install only | None | Demonstrates prompt compression without a provider loop. |
47
+ | `novelty_extractor_demo.py` | `data_engineering/novelty_extractor` | Local execute | `pip install fastembed numpy` | None | Demonstrates multi-turn corpus distillation using local embeddings with no API key. |
48
+ | `gemini_novelty_extractor.py` | `data_engineering/novelty_extractor` | Gemini | `[gemini]`, `pip install fastembed numpy` | `GOOGLE_API_KEY` | Runs the novelty extractor with a Gemini function-calling loop. |
49
+ | `ollama_novelty_extractor.py` | `data_engineering/novelty_extractor` | Ollama | `pip install fastembed numpy`; install `ollama` separately | None | Runs the novelty extractor with local Ollama prompt-mode calls. |
50
+ | `gemini_issue_resolver.py` | `dev_tools/issue_resolver` | Gemini | `[gemini]` | `GOOGLE_API_KEY`; optional `GITHUB_TOKEN` | Gemini loop for GitHub issue analysis; fetches issue data after `prepare` (sample: issue #123). |
51
+ | `ollama_issue_resolver.py` | `dev_tools/issue_resolver` | Ollama | No Skillware extra; install `ollama` separately | optional `GITHUB_TOKEN`; `OLLAMA_MODEL` (default `gemma4:e2b`) | Ollama prompt-mode loop for GitHub issue analysis (sample: issue #123). |
52
+
53
+ ## Notes
54
+
55
+ - Agent-side model keys such as `GOOGLE_API_KEY`, `ANTHROPIC_API_KEY`,
56
+ `OPENAI_API_KEY`, and `DEEPSEEK_API_KEY` are documented in the provider
57
+ guides.
58
+ - Skill runtime keys such as `ETHERSCAN_API_KEY` are documented in each skill
59
+ manifest and on the skill catalog pages.
60
+ - Ollama examples require the Python `ollama` package, a local Ollama server,
61
+ and the model named in the script, but no cloud API key.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "skillware"
7
- version = "0.3.6"
7
+ version = "0.3.8"
8
8
  description = "A framework for modular, self-contained AI skills."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -12,10 +12,10 @@
12
12
  "ui_schema": {
13
13
  "type": "card",
14
14
  "fields": [
15
- {"key": "summary.address", "label": "Address"},
16
- {"key": "summary.sanctioned", "label": "Sanctioned", "type": "status_badge"},
17
- {"key": "summary.malicious_interactions_count", "label": "Risky Interactions", "type": "count"},
18
- {"key": "summary.pnl_eth", "label": "PnL (ETH)", "type": "currency"}
15
+ {"key": "metadata.wallet_address", "label": "Address"},
16
+ {"key": "summary.sanctioned_entity_match", "label": "Sanctioned", "type": "status_badge"},
17
+ {"key": "summary.malicious_interaction_count", "label": "Risky Interactions", "type": "count"},
18
+ {"key": "financial_analysis.pnl_eth", "label": "PnL (ETH)", "type": "currency"}
19
19
  ]
20
20
  }
21
21
  }
@@ -1,6 +1,6 @@
1
1
  # Wallet Screening Skill Instructions
2
2
 
3
- You are equipped with the `wallet_screening` skill. This tool allows you to perform due diligence on Ethereum addresses.
3
+ You are equipped with the `finance/wallet_screening` skill. This tool allows you to perform due diligence on Ethereum addresses.
4
4
 
5
5
  ## When to use
6
6
  Use this skill when the user:
@@ -13,10 +13,10 @@ Use this skill when the user:
13
13
  The tool returns a JSON object. You should summarize this for the user in a professional, "Compliance Officer" tone.
14
14
 
15
15
  ### Key Fields to Check:
16
- 1. **`summary.sanctioned` (Boolean)**: If `true`, this is CRITICAL. Report the `sanctions_hits` immediately.
17
- 2. **`summary.malicious_interactions` (Integer)**: If > 0, the wallet has touched bad actors. List the `malicious_contracts_check.matches`.
18
- 3. **`summary.pnl`**: Profit and Loss. Useful for determining if it's a profitable trader or a victim.
19
- 4. **`counterparty_analysis`**: Who are they sending money to?
16
+ 1. **`summary.sanctioned_entity_match` (Boolean)**: If `true`, this is CRITICAL. Report the `risk_details.sanctions_hits` immediately.
17
+ 2. **`summary.malicious_interaction_count` (Integer)**: If > 0, the wallet has touched bad actors. List the `risk_details.malicious_interactions`.
18
+ 3. **`financial_analysis.pnl_eth` / `pnl_usd`**: Profit and Loss. Useful for determining if it's a profitable trader or a victim.
19
+ 4. **`network_analysis.top_10_counterparties`**: Who are they sending money to?
20
20
 
21
21
  ## Safety Protocol
22
22
  * If a wallet is **Sanctioned**: severe warning. "⚠️ WARNING: This wallet appears on the following sanctions lists..."
@@ -0,0 +1,3 @@
1
+ from .skill import MentalCoachSkill
2
+
3
+ __all__ = ["MentalCoachSkill"]
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "Mental Coach",
3
+ "description": "Wellness coaching guardrail with crisis triage and grounded KB retrieval.",
4
+ "issuer": {
5
+ "name": "Masa",
6
+ "email": "masa88keith@gmail.com",
7
+ "github": "mrmasa88",
8
+ "org": "AO"
9
+ },
10
+ "icon": "heart",
11
+ "color": "blue",
12
+ "ui_schema": {
13
+ "type": "card",
14
+ "fields": [
15
+ {
16
+ "key": "policy_status",
17
+ "label": "Policy Status"
18
+ },
19
+ {
20
+ "key": "scope",
21
+ "label": "Scope"
22
+ }
23
+ ]
24
+ }
25
+ }
@@ -0,0 +1,93 @@
1
+ """Load and apply hard constraints from kb/hard_constraints.yaml."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ from functools import lru_cache
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ import yaml
11
+
12
+ _CONSTRAINTS_PATH = os.path.join(
13
+ os.path.dirname(__file__), "kb", "hard_constraints.yaml"
14
+ )
15
+
16
+ CLINICAL_PATTERNS: Dict[str, List[str]] = {
17
+ "no_diagnosis": [
18
+ r"\bdiagnos(e|is|ing)\b",
19
+ r"\bdo i have (depression|anxiety|bipolar|adhd|ptsd|ocd)\b",
20
+ r"\bwhat (disorder|condition|illness) do i have\b",
21
+ r"\bam i (depressed|bipolar|schizophrenic)\b",
22
+ ],
23
+ "no_medication_advice": [
24
+ r"\b(should i|can i) (take|stop|start) (my )?(medication|meds|antidepressant)\b",
25
+ r"\bwhat medication\b",
26
+ r"\bwhat dose\b",
27
+ r"\bprescribe\b",
28
+ r"\b(increase|decrease) my (dose|dosage)\b",
29
+ ],
30
+ "no_clinical_interpretation": [
31
+ r"\binterpret my (lab|blood test|test results)\b",
32
+ r"\bwhat do my results mean\b",
33
+ r"\bclinical record\b",
34
+ ],
35
+ }
36
+
37
+ INJECTION_PATTERNS = [
38
+ r"ignore (your|all|previous) (rules|instructions|constraints)",
39
+ r"disregard (your|the) (policy|safety|guidelines)",
40
+ r"pretend you are (a )?(doctor|therapist|psychiatrist)",
41
+ r"jailbreak",
42
+ r"bypass (your|the) (rules|safety|filter)",
43
+ ]
44
+
45
+
46
+ @lru_cache(maxsize=1)
47
+ def load_constraints_config() -> Dict[str, Any]:
48
+ with open(_CONSTRAINTS_PATH, "r", encoding="utf-8") as handle:
49
+ data = yaml.safe_load(handle)
50
+ return data if isinstance(data, dict) else {}
51
+
52
+
53
+ def get_disclaimers(kind: str = "default") -> List[str]:
54
+ config = load_constraints_config()
55
+ disclaimers = config.get("disclaimers_required", {})
56
+ items = disclaimers.get(kind, disclaimers.get("default", []))
57
+ return list(items) if isinstance(items, list) else []
58
+
59
+
60
+ def detect_clinical_violation(text: str) -> Optional[str]:
61
+ normalized = text.lower()
62
+ for constraint_id, patterns in CLINICAL_PATTERNS.items():
63
+ for pattern in patterns:
64
+ if re.search(pattern, normalized):
65
+ return constraint_id
66
+ return None
67
+
68
+
69
+ def detect_injection_attempt(text: str) -> bool:
70
+ normalized = text.lower()
71
+ return any(re.search(pattern, normalized) for pattern in INJECTION_PATTERNS)
72
+
73
+
74
+ def get_playbook_entry(decision: str) -> Dict[str, Any]:
75
+ config = load_constraints_config()
76
+ playbook = config.get("escalation_playbook", {})
77
+ key = {
78
+ "ESCALATE": "on_escalate",
79
+ "CAUTION": "on_caution",
80
+ "OK": "on_ok",
81
+ }.get(decision, "on_ok")
82
+ entry = playbook.get(key, {})
83
+ return entry if isinstance(entry, dict) else {}
84
+
85
+
86
+ def list_hard_constraint_ids() -> List[str]:
87
+ config = load_constraints_config()
88
+ items = config.get("hard_constraints", [])
89
+ ids: List[str] = []
90
+ for item in items:
91
+ if isinstance(item, dict) and item.get("id"):
92
+ ids.append(str(item["id"]))
93
+ return ids
@@ -0,0 +1,175 @@
1
+ """Deterministic crisis gate — runs before retrieval, no LLM dependency."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ import unicodedata
7
+ from dataclasses import dataclass, field
8
+ from typing import Dict, List, Sequence, Tuple
9
+
10
+ # Minimal conservative signal sets (intent-level, not exhaustive lexicons).
11
+ CRISIS_SIGNALS: Dict[str, Sequence[str]] = {
12
+ "suicidal_ideation": (
13
+ "kill myself",
14
+ "end my life",
15
+ "want to die",
16
+ "suicidal",
17
+ "not want to live",
18
+ "better off dead",
19
+ "end it all",
20
+ ),
21
+ "self_harm": (
22
+ "hurt myself",
23
+ "harm myself",
24
+ "cut myself",
25
+ "self harm",
26
+ "self-harm",
27
+ ),
28
+ "harm_to_others": (
29
+ "hurt someone",
30
+ "kill him",
31
+ "kill her",
32
+ "kill them",
33
+ "harm others",
34
+ "going to hurt",
35
+ ),
36
+ "abuse_or_violence": (
37
+ "being abused",
38
+ "he hits me",
39
+ "she hits me",
40
+ "sexually assaulted",
41
+ "domestic violence",
42
+ "partner hurts me",
43
+ ),
44
+ "acute_medical_emergency": (
45
+ "can't breathe",
46
+ "cannot breathe",
47
+ "chest pain",
48
+ "overdose",
49
+ "heart attack",
50
+ "having a stroke",
51
+ ),
52
+ "severe_acute_distress": (
53
+ "can't cope",
54
+ "cannot cope",
55
+ "falling apart",
56
+ "panic attack",
57
+ "overwhelmed can't function",
58
+ "completely overwhelmed",
59
+ ),
60
+ }
61
+
62
+ CATEGORY_ACTION = {
63
+ "suicidal_ideation": "ESCALATE",
64
+ "self_harm": "ESCALATE",
65
+ "harm_to_others": "ESCALATE",
66
+ "abuse_or_violence": "ESCALATE",
67
+ "acute_medical_emergency": "ESCALATE",
68
+ "severe_acute_distress": "CAUTION",
69
+ }
70
+
71
+ NEGATION_PREFIXES = (
72
+ "don't ",
73
+ "do not ",
74
+ "never ",
75
+ "not going to ",
76
+ "won't ",
77
+ "wouldn't ",
78
+ )
79
+
80
+ CJK_RE = re.compile(r"[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uac00-\ud7af]")
81
+ NON_ASCII_RE = re.compile(r"[^\x00-\x7F]")
82
+
83
+
84
+ @dataclass
85
+ class LanguageAssessment:
86
+ is_english: bool
87
+ non_english: bool
88
+ reason: str = ""
89
+
90
+
91
+ @dataclass
92
+ class GateResult:
93
+ policy_status: str
94
+ crisis_categories: List[str] = field(default_factory=list)
95
+ ambiguous: bool = False
96
+
97
+
98
+ def normalize_text(text: str) -> str:
99
+ normalized = unicodedata.normalize("NFKC", text or "")
100
+ normalized = re.sub(r"\s+", " ", normalized).strip().lower()
101
+ return normalized
102
+
103
+
104
+ def assess_language(text: str) -> LanguageAssessment:
105
+ if not text.strip():
106
+ return LanguageAssessment(is_english=True, non_english=False)
107
+
108
+ if CJK_RE.search(text):
109
+ return LanguageAssessment(
110
+ is_english=False,
111
+ non_english=True,
112
+ reason="CJK characters detected; v0.1 is EN-first.",
113
+ )
114
+
115
+ non_ascii = len(NON_ASCII_RE.findall(text))
116
+ if non_ascii >= 8 or (len(text) > 0 and non_ascii / len(text) > 0.15):
117
+ return LanguageAssessment(
118
+ is_english=False,
119
+ non_english=True,
120
+ reason="High non-ASCII ratio; v0.1 is EN-first.",
121
+ )
122
+
123
+ return LanguageAssessment(is_english=True, non_english=False)
124
+
125
+
126
+ def _has_negation_before(text: str, index: int) -> bool:
127
+ window = text[max(0, index - 48) : index]
128
+ return any(prefix in window for prefix in NEGATION_PREFIXES)
129
+
130
+
131
+ def _match_signals(normalized: str) -> Tuple[List[str], bool]:
132
+ matched: List[str] = []
133
+ ambiguous = False
134
+ for category, signals in CRISIS_SIGNALS.items():
135
+ for signal in signals:
136
+ start = 0
137
+ while True:
138
+ idx = normalized.find(signal, start)
139
+ if idx < 0:
140
+ break
141
+ if _has_negation_before(normalized, idx):
142
+ ambiguous = True
143
+ else:
144
+ matched.append(category)
145
+ start = idx + len(signal)
146
+ # Preserve order, dedupe
147
+ seen = set()
148
+ ordered: List[str] = []
149
+ for cat in matched:
150
+ if cat not in seen:
151
+ ordered.append(cat)
152
+ seen.add(cat)
153
+ return ordered, ambiguous
154
+
155
+
156
+ def _resolve_policy(categories: Sequence[str], ambiguous: bool) -> str:
157
+ if categories:
158
+ if any(CATEGORY_ACTION.get(c) == "ESCALATE" for c in categories):
159
+ return "ESCALATE"
160
+ if any(CATEGORY_ACTION.get(c) == "CAUTION" for c in categories):
161
+ return "CAUTION"
162
+ if ambiguous:
163
+ return "CAUTION"
164
+ return "OK"
165
+
166
+
167
+ def evaluate_crisis_gate(user_prompt: str) -> GateResult:
168
+ normalized = normalize_text(user_prompt)
169
+ categories, ambiguous = _match_signals(normalized)
170
+ policy_status = _resolve_policy(categories, ambiguous)
171
+ return GateResult(
172
+ policy_status=policy_status,
173
+ crisis_categories=categories,
174
+ ambiguous=ambiguous and policy_status != "ESCALATE",
175
+ )
@@ -0,0 +1,37 @@
1
+ # Operational Instructions: Mental Coach
2
+
3
+ You are an agent equipped with the `wellness/mental_coach` skill.
4
+
5
+ ## When to use this skill
6
+
7
+ - Before responding to wellness, stress, coping, or psychoeducation requests.
8
+ - When you need deterministic crisis triage and non-clinical scope enforcement.
9
+ - When you must ground coaching guidance in cited KB chunks with required disclaimers.
10
+
11
+ ## What this skill does
12
+
13
+ 1. Runs a deterministic crisis gate first (no LLM) and escalates on danger signals.
14
+ 2. Blocks clinical requests (diagnosis, medication advice, clinical interpretation).
15
+ 3. Retrieves grounded coaching chunks from the embedded public KB when safe to coach.
16
+ 4. Optionally runs a scope evaluator (Gemini) when `run_evaluator` is enabled.
17
+
18
+ ## How to interpret output
19
+
20
+ - `policy_status: ESCALATE` — stop coaching; use `final_context_for_agent` and resources only.
21
+ - `policy_status: BLOCKED` — decline the clinical request; offer non-clinical alternatives.
22
+ - `policy_status: CAUTION` — proceed gently; include disclaimers and consider resources.
23
+ - `policy_status: OK` — coaching path; follow retrieved citations exactly.
24
+
25
+ Always surface `disclaimers_required` verbatim in the user-facing reply.
26
+
27
+ ## Limitations
28
+
29
+ - Supportive coaching and psychoeducation only; not emergency services or licensed care.
30
+ - v0.1 is English-first; non-English input is routed to CAUTION with resources.
31
+ - Optional evaluator requires `GOOGLE_API_KEY` when enabled.
32
+
33
+ ## Example uses
34
+
35
+ - User: "I feel stressed at work and need coping strategies." -> coaching retrieval path.
36
+ - User: "Can you diagnose my anxiety?" -> blocked clinical path.
37
+ - User: "I want to hurt myself." -> crisis escalation path (no coaching content).