drupaltools-tip-generator 0.1.0__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.
- drupaltools_tip_generator-0.1.0/.env.example +22 -0
- drupaltools_tip_generator-0.1.0/.github/workflows/publish.yml +29 -0
- drupaltools_tip_generator-0.1.0/.gitignore +30 -0
- drupaltools_tip_generator-0.1.0/LICENSE +20 -0
- drupaltools_tip_generator-0.1.0/PKG-INFO +253 -0
- drupaltools_tip_generator-0.1.0/PUBLISH.md +105 -0
- drupaltools_tip_generator-0.1.0/README.md +229 -0
- drupaltools_tip_generator-0.1.0/SKILL.md +96 -0
- drupaltools_tip_generator-0.1.0/config.json +122 -0
- drupaltools_tip_generator-0.1.0/example.config.json +10 -0
- drupaltools_tip_generator-0.1.0/pyproject.toml +42 -0
- drupaltools_tip_generator-0.1.0/setup.cfg +4 -0
- drupaltools_tip_generator-0.1.0/src/drupaltools_tip_generator.egg-info/PKG-INFO +253 -0
- drupaltools_tip_generator-0.1.0/src/drupaltools_tip_generator.egg-info/SOURCES.txt +32 -0
- drupaltools_tip_generator-0.1.0/src/drupaltools_tip_generator.egg-info/dependency_links.txt +1 -0
- drupaltools_tip_generator-0.1.0/src/drupaltools_tip_generator.egg-info/entry_points.txt +2 -0
- drupaltools_tip_generator-0.1.0/src/drupaltools_tip_generator.egg-info/requires.txt +2 -0
- drupaltools_tip_generator-0.1.0/src/drupaltools_tip_generator.egg-info/top_level.txt +1 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator/MANIFEST.in +5 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator/__init__.py +1691 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator/config.json +122 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator/templates/about.html +68 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator/templates/index.html +97 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator/url_cache.py +454 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator/viewer.py +200 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator.egg-info/PKG-INFO +253 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator.egg-info/SOURCES.txt +25 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator.egg-info/dependency_links.txt +1 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator.egg-info/entry_points.txt +2 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator.egg-info/requires.txt +2 -0
- drupaltools_tip_generator-0.1.0/src/tip_generator.egg-info/top_level.txt +1 -0
- drupaltools_tip_generator-0.1.0/static/style.css +369 -0
- drupaltools_tip_generator-0.1.0/templates/about.html +68 -0
- drupaltools_tip_generator-0.1.0/templates/index.html +97 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Copy this file to .env and fill in your API keys
|
|
2
|
+
# The tip generator will automatically load these values
|
|
3
|
+
# All variables use TIPGEN_ prefix to avoid overriding global environment variables
|
|
4
|
+
|
|
5
|
+
# Anthropic API (for claude models). See models at https://docs.anthropic.com/en/docs/about-claude/models/overview
|
|
6
|
+
TIPGEN_ANTHROPIC_API_KEY=your_anthropic_key_here
|
|
7
|
+
TIPGEN_ANTHROPIC_MODEL=claude-haiku-4-5
|
|
8
|
+
# Optional: Custom API URL for Anthropic-compatible endpoints (e.g., local LLM servers)
|
|
9
|
+
# TIPGEN_ANTHROPIC_API_URL=https://api.anthropic.com
|
|
10
|
+
|
|
11
|
+
# OpenAI API (for gpt models). See models at https://platform.openai.com/docs/models
|
|
12
|
+
TIPGEN_OPENAI_API_KEY=your_openai_key_here
|
|
13
|
+
TIPGEN_OPENAI_MODEL=gpt-5.4-mini
|
|
14
|
+
# Optional: Custom API URL for OpenAI-compatible endpoints (e.g., local LLM servers, Ollama, vLLM)
|
|
15
|
+
# TIPGEN_OPENAI_API_URL=https://api.openai.com/v1
|
|
16
|
+
|
|
17
|
+
# OpenRouter API (access to many models). See https://openrouter.ai/models
|
|
18
|
+
TIPGEN_OPENROUTER_API_KEY=your_openrouter_key_here
|
|
19
|
+
TIPGEN_OPENROUTER_MODEL=openai/gpt-5.1-codex-mini
|
|
20
|
+
|
|
21
|
+
# Optional: Custom tips directory (default: tips/ folder in package)
|
|
22
|
+
# TIPGEN_TIPS_DIR=/path/to/custom/tips
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Set up Python
|
|
15
|
+
uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: '3.11'
|
|
18
|
+
|
|
19
|
+
- name: Install build dependencies
|
|
20
|
+
run: pip install --upgrade build twine
|
|
21
|
+
|
|
22
|
+
- name: Build package
|
|
23
|
+
run: python -m build
|
|
24
|
+
|
|
25
|
+
- name: Publish to PyPI
|
|
26
|
+
env:
|
|
27
|
+
TWINE_USERNAME: __token__
|
|
28
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
29
|
+
run: twine upload dist/*
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Environment variables (contains API keys)
|
|
2
|
+
.env
|
|
3
|
+
|
|
4
|
+
# Error log
|
|
5
|
+
errors.json
|
|
6
|
+
|
|
7
|
+
# Generated tips (can be regenerated)
|
|
8
|
+
tips/
|
|
9
|
+
|
|
10
|
+
# Cached remote data (URL fetches)
|
|
11
|
+
cache-data/
|
|
12
|
+
|
|
13
|
+
# Python
|
|
14
|
+
__pycache__/
|
|
15
|
+
*.py[cod]
|
|
16
|
+
*$py.class
|
|
17
|
+
.venv/
|
|
18
|
+
venv/
|
|
19
|
+
ENV/
|
|
20
|
+
|
|
21
|
+
# IDE
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
24
|
+
*.swp
|
|
25
|
+
*.swo
|
|
26
|
+
|
|
27
|
+
# Build artifacts
|
|
28
|
+
dist/
|
|
29
|
+
build/
|
|
30
|
+
*.egg-info/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
GNU GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 2, June 1991
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2026 Drupal Tools
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along
|
|
17
|
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
18
|
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
19
|
+
|
|
20
|
+
Full license text: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: drupaltools-tip-generator
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generate static MD tip files for Drupal development tips using various LLM providers
|
|
5
|
+
Author-email: Drupal Tools Team <info@drupaltools.com>
|
|
6
|
+
License-Expression: GPL-2.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/drupaltools/tip-generator
|
|
8
|
+
Project-URL: Repository, https://github.com/drupaltools/tip-generator.git
|
|
9
|
+
Project-URL: Issues, https://github.com/drupaltools/tip-generator/issues
|
|
10
|
+
Keywords: drupal,tips,llm,generator,ai,cli
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: anthropic>=0.18.0
|
|
22
|
+
Requires-Dist: openai>=1.0.0
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# Drupal Tip Generator
|
|
26
|
+
|
|
27
|
+
Generate static MD tip files for the `drupal-tip` skill using various LLM providers.
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
### 1. Create Virtual Environment
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cd ~/.claude/skills/drupal-tip
|
|
35
|
+
python3 -m venv .venv
|
|
36
|
+
source .venv/bin/activate
|
|
37
|
+
pip install openai anthropic
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. Configure API Keys
|
|
41
|
+
|
|
42
|
+
Copy the example environment file and add your keys:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cp .env.example .env
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Edit `.env` with your API keys (use `TIPGEN_` prefix):
|
|
49
|
+
|
|
50
|
+
```env
|
|
51
|
+
TIPGEN_ANTHROPIC_API_KEY=sk-ant-...
|
|
52
|
+
TIPGEN_OPENAI_API_KEY=sk-...
|
|
53
|
+
TIPGEN_OPENROUTER_API_KEY=sk-or-...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
### Get a Random Existing Tip (FAST!)
|
|
59
|
+
|
|
60
|
+
Get a tip from the pre-generated database instantly — no API call needed:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
.venv/bin/python tip_generator.py --random-tip
|
|
64
|
+
.venv/bin/python tip_generator.py --random-tip --tip-category core-service
|
|
65
|
+
.venv/bin/python tip_generator.py --list-existing
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### List Available Categories
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
.venv/bin/python tip_generator.py --list-categories
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Generate Tips
|
|
75
|
+
|
|
76
|
+
**Using Anthropic:**
|
|
77
|
+
```bash
|
|
78
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p anthropic
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Using OpenAI (batch mode - 50% cheaper):**
|
|
82
|
+
```bash
|
|
83
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openai
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Using OpenRouter:**
|
|
87
|
+
```bash
|
|
88
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openrouter
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Arguments
|
|
92
|
+
|
|
93
|
+
| Argument | Description |
|
|
94
|
+
|----------|-------------|
|
|
95
|
+
| `-c, --category` | Category number(s) or `all` |
|
|
96
|
+
| `-n, --count` | Number of tips per category (default: 5) |
|
|
97
|
+
| `-p, --provider` | LLM provider: `anthropic`, `openai`, `openrouter` |
|
|
98
|
+
| `-m, --model` | Override default model |
|
|
99
|
+
| `-u, --api-url` | Custom API URL for OpenAI/Anthropic-compatible endpoints |
|
|
100
|
+
| `-t, --max-tokens` | Maximum tokens for response (default: 4096) |
|
|
101
|
+
| `--tips-dir` | Custom tips directory (or set `TIPGEN_TIPS_DIR` env var or `tips_dir` in config.json) |
|
|
102
|
+
| `--save-truncated` | Save tips even if truncated (use with caution) |
|
|
103
|
+
| `--no-wait` | Don't wait for batch completion |
|
|
104
|
+
| `--dry-run` | Show what would be done without calling API |
|
|
105
|
+
| `--list-categories` | List all available categories |
|
|
106
|
+
| `--random-tip` | Get a random existing tip (fast, no API) |
|
|
107
|
+
| `--list-existing` | List categories with existing tips |
|
|
108
|
+
| `--tip-category` | Filter random tip by category name |
|
|
109
|
+
| `--validate` | Enable validation mode |
|
|
110
|
+
| `--validate-file` | Validate a specific tip file |
|
|
111
|
+
| `--validate-category` | Validate all tips in a category |
|
|
112
|
+
| `--validate-all` | Validate all tips across all categories |
|
|
113
|
+
|
|
114
|
+
### Examples
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Generate 3 tips for category 35 (core-service)
|
|
118
|
+
.venv/bin/python tip_generator.py -c 35 -n 3 -p openrouter
|
|
119
|
+
|
|
120
|
+
# Generate 5 tips for multiple categories
|
|
121
|
+
.venv/bin/python tip_generator.py -c 35,36,37 -n 5 -p openrouter
|
|
122
|
+
|
|
123
|
+
# Generate 1 tip for ALL categories
|
|
124
|
+
.venv/bin/python tip_generator.py -c all -n 1 -p openrouter
|
|
125
|
+
|
|
126
|
+
# Use a specific model
|
|
127
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openrouter -m anthropic/claude-opus-4
|
|
128
|
+
|
|
129
|
+
# Use a custom API URL (e.g., Together.xyz, local LLM server)
|
|
130
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openai -u https://api.together.xyz/v1
|
|
131
|
+
|
|
132
|
+
# Increase max tokens for longer responses (avoid truncation)
|
|
133
|
+
.venv/bin/python tip_generator.py -c 60 -n 20 -p openai --max-tokens 8192
|
|
134
|
+
|
|
135
|
+
# Save tips even if truncated (use with caution)
|
|
136
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openai --save-truncated
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Batch API Notes
|
|
140
|
+
|
|
141
|
+
| Provider | Batch Support | Discount | Notes |
|
|
142
|
+
|----------|---------------|----------|-------|
|
|
143
|
+
| Anthropic | Yes | 50% | Uses `message-batches-2024-09-24` beta |
|
|
144
|
+
| OpenAI | Yes | 50% | Results within 24h |
|
|
145
|
+
| OpenRouter | ⚠️ Sync only | - | Batch API not supported |
|
|
146
|
+
|
|
147
|
+
## Check Batch Status
|
|
148
|
+
|
|
149
|
+
If you ran batch mode with `--no-wait`:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
.venv/bin/python tip_generator.py --check-batch BATCH_ID -p anthropic
|
|
153
|
+
.venv/bin/python tip_generator.py --check-batch BATCH_ID -p openai --save-results
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Output
|
|
157
|
+
|
|
158
|
+
Tips are saved to `tips/{category-name}/{uuid}.md` with 8-character random IDs:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
tips/
|
|
162
|
+
├── core-service/
|
|
163
|
+
│ ├── a1b2c3d4.md
|
|
164
|
+
│ └── e5f6g7h8.md
|
|
165
|
+
└── rare-drush-command/
|
|
166
|
+
└── 9i0j1k2l.md
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Each file has frontmatter:
|
|
170
|
+
|
|
171
|
+
```markdown
|
|
172
|
+
---
|
|
173
|
+
category: core-service
|
|
174
|
+
title: [Generated title]
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
[Tip content]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Configuration
|
|
181
|
+
|
|
182
|
+
Categories and the prompt template are defined in `config.json`:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"prompt_template": "Generate a Drupal tip for category #{cat_id}: {cat_desc}...",
|
|
187
|
+
"code_language": "php",
|
|
188
|
+
"tips_dir": "/path/to/custom/tips",
|
|
189
|
+
"categories": {
|
|
190
|
+
"1": {"name": "proposed-new-module", "desc": "Proposed new module"},
|
|
191
|
+
"35": {"name": "core-service", "desc": "Lesser-known core service"}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Tips Directory Configuration
|
|
197
|
+
|
|
198
|
+
The tips directory can be configured via (in priority order):
|
|
199
|
+
|
|
200
|
+
1. **CLI argument**: `--tips-dir /path/to/tips`
|
|
201
|
+
2. **Environment variable**: `TIPGEN_TIPS_DIR=/path/to/tips`
|
|
202
|
+
3. **Config file**: `"tips_dir": "/path/to/tips"` in `config.json`
|
|
203
|
+
4. **Default**: `tips/` folder in the package directory
|
|
204
|
+
|
|
205
|
+
To add or modify categories, edit `config.json` directly - no code changes needed.
|
|
206
|
+
|
|
207
|
+
## Development
|
|
208
|
+
|
|
209
|
+
### Running Tests
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# Dry run to verify configuration
|
|
213
|
+
.venv/bin/python tip_generator.py -c 35 -n 1 -p openrouter --dry-run
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Validation
|
|
217
|
+
|
|
218
|
+
Validate generated tips for formatting issues, truncation, and quality:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Validate a single file
|
|
222
|
+
.venv/bin/python tip_generator.py --validate --validate-file tips/core-service/a1b2c3d4.md
|
|
223
|
+
|
|
224
|
+
# Validate all tips in a category
|
|
225
|
+
.venv/bin/python tip_generator.py --validate --validate-category core-service
|
|
226
|
+
|
|
227
|
+
# Validate ALL tips across all categories
|
|
228
|
+
.venv/bin/python tip_generator.py --validate --validate-all
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Validation Checks
|
|
232
|
+
|
|
233
|
+
- **Formatting**: Frontmatter structure, code block balance, line counts
|
|
234
|
+
- **Completeness**: Truncation patterns (trailing `...`, `[TODO]`, incomplete code blocks)
|
|
235
|
+
- **Quality**: Generic openings, placeholder text, excessive code ratio
|
|
236
|
+
- **Fake Content**: Non-existent Drupal APIs, hallucinated functions, wrong service names
|
|
237
|
+
|
|
238
|
+
## Web Viewer
|
|
239
|
+
|
|
240
|
+
A simple web UI to browse tips:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pip install flask
|
|
244
|
+
python tip_viewer.py # http://localhost:5000
|
|
245
|
+
python tip_viewer.py --port 8080 # Custom port
|
|
246
|
+
python tip_viewer.py --host 0.0.0.0 # Public access
|
|
247
|
+
python tip_viewer.py --debug # Debug mode
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Features:
|
|
251
|
+
- Filter tips by category
|
|
252
|
+
- Get random tip with one click
|
|
253
|
+
- View all tips or browse by category
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Publishing tip-generator to PyPI
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- Python 3.11+
|
|
6
|
+
- PyPI account with API token
|
|
7
|
+
- Git repository with push access
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
### 1. Install build tools
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install --upgrade build twine
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 2. Configure PyPI credentials
|
|
18
|
+
|
|
19
|
+
Create `~/.pypirc`:
|
|
20
|
+
|
|
21
|
+
```ini
|
|
22
|
+
[pypi]
|
|
23
|
+
username = __token__
|
|
24
|
+
password = pypi-...
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or use environment variable:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
export TWINE_USERNAME=__token__
|
|
31
|
+
export TWINE_PASSWORD=pypi-...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Build
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Clean previous builds
|
|
38
|
+
rm -rf dist/ build/ src/*.egg-info
|
|
39
|
+
|
|
40
|
+
# Build package
|
|
41
|
+
python -m build
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Output:
|
|
45
|
+
- `dist/tip_generator-X.X.X-py3-none-any.whl`
|
|
46
|
+
- `dist/tip_generator-X.X.X.tar.gz`
|
|
47
|
+
|
|
48
|
+
## Publish
|
|
49
|
+
|
|
50
|
+
### Manual publish
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Check package before upload
|
|
54
|
+
twine check dist/*
|
|
55
|
+
|
|
56
|
+
# Upload to PyPI
|
|
57
|
+
twine upload dist/*
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Automated publish via GitHub Actions
|
|
61
|
+
|
|
62
|
+
The workflow `.github/workflows/publish.yml` automatically publishes on tag push:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Update version in pyproject.toml first
|
|
66
|
+
# Then create and push tag
|
|
67
|
+
git tag v0.1.0
|
|
68
|
+
git push origin v0.1.0
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Version Bumping
|
|
72
|
+
|
|
73
|
+
1. Update `version` in `pyproject.toml`
|
|
74
|
+
2. Update `__version__` in `src/tip_generator/__init__.py`
|
|
75
|
+
3. Commit changes
|
|
76
|
+
4. Create tag matching version
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Example: bump to 0.2.0
|
|
80
|
+
sed -i 's/version = "0.1.0"/version = "0.2.0"/' pyproject.toml
|
|
81
|
+
sed -i 's/__version__ = "0.1.0"/__version__ = "0.2.0"/' src/tip_generator/__init__.py
|
|
82
|
+
git commit -am "Bump version to 0.2.0"
|
|
83
|
+
git tag v0.2.0
|
|
84
|
+
git push origin master --tags
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Test Publishing (TestPyPI)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Build
|
|
91
|
+
python -m build
|
|
92
|
+
|
|
93
|
+
# Upload to TestPyPI first
|
|
94
|
+
twine upload --repository testpypi dist/*
|
|
95
|
+
|
|
96
|
+
# Test install
|
|
97
|
+
pip install --index-url https://test.pypi.org/simple/ tip-generator
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Verify Installation
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pip install tip-generator
|
|
104
|
+
drupal-tip-generator --help
|
|
105
|
+
```
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Drupal Tip Generator
|
|
2
|
+
|
|
3
|
+
Generate static MD tip files for the `drupal-tip` skill using various LLM providers.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### 1. Create Virtual Environment
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd ~/.claude/skills/drupal-tip
|
|
11
|
+
python3 -m venv .venv
|
|
12
|
+
source .venv/bin/activate
|
|
13
|
+
pip install openai anthropic
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 2. Configure API Keys
|
|
17
|
+
|
|
18
|
+
Copy the example environment file and add your keys:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
cp .env.example .env
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Edit `.env` with your API keys (use `TIPGEN_` prefix):
|
|
25
|
+
|
|
26
|
+
```env
|
|
27
|
+
TIPGEN_ANTHROPIC_API_KEY=sk-ant-...
|
|
28
|
+
TIPGEN_OPENAI_API_KEY=sk-...
|
|
29
|
+
TIPGEN_OPENROUTER_API_KEY=sk-or-...
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Get a Random Existing Tip (FAST!)
|
|
35
|
+
|
|
36
|
+
Get a tip from the pre-generated database instantly — no API call needed:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
.venv/bin/python tip_generator.py --random-tip
|
|
40
|
+
.venv/bin/python tip_generator.py --random-tip --tip-category core-service
|
|
41
|
+
.venv/bin/python tip_generator.py --list-existing
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### List Available Categories
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
.venv/bin/python tip_generator.py --list-categories
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Generate Tips
|
|
51
|
+
|
|
52
|
+
**Using Anthropic:**
|
|
53
|
+
```bash
|
|
54
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p anthropic
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Using OpenAI (batch mode - 50% cheaper):**
|
|
58
|
+
```bash
|
|
59
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openai
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Using OpenRouter:**
|
|
63
|
+
```bash
|
|
64
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openrouter
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Arguments
|
|
68
|
+
|
|
69
|
+
| Argument | Description |
|
|
70
|
+
|----------|-------------|
|
|
71
|
+
| `-c, --category` | Category number(s) or `all` |
|
|
72
|
+
| `-n, --count` | Number of tips per category (default: 5) |
|
|
73
|
+
| `-p, --provider` | LLM provider: `anthropic`, `openai`, `openrouter` |
|
|
74
|
+
| `-m, --model` | Override default model |
|
|
75
|
+
| `-u, --api-url` | Custom API URL for OpenAI/Anthropic-compatible endpoints |
|
|
76
|
+
| `-t, --max-tokens` | Maximum tokens for response (default: 4096) |
|
|
77
|
+
| `--tips-dir` | Custom tips directory (or set `TIPGEN_TIPS_DIR` env var or `tips_dir` in config.json) |
|
|
78
|
+
| `--save-truncated` | Save tips even if truncated (use with caution) |
|
|
79
|
+
| `--no-wait` | Don't wait for batch completion |
|
|
80
|
+
| `--dry-run` | Show what would be done without calling API |
|
|
81
|
+
| `--list-categories` | List all available categories |
|
|
82
|
+
| `--random-tip` | Get a random existing tip (fast, no API) |
|
|
83
|
+
| `--list-existing` | List categories with existing tips |
|
|
84
|
+
| `--tip-category` | Filter random tip by category name |
|
|
85
|
+
| `--validate` | Enable validation mode |
|
|
86
|
+
| `--validate-file` | Validate a specific tip file |
|
|
87
|
+
| `--validate-category` | Validate all tips in a category |
|
|
88
|
+
| `--validate-all` | Validate all tips across all categories |
|
|
89
|
+
|
|
90
|
+
### Examples
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Generate 3 tips for category 35 (core-service)
|
|
94
|
+
.venv/bin/python tip_generator.py -c 35 -n 3 -p openrouter
|
|
95
|
+
|
|
96
|
+
# Generate 5 tips for multiple categories
|
|
97
|
+
.venv/bin/python tip_generator.py -c 35,36,37 -n 5 -p openrouter
|
|
98
|
+
|
|
99
|
+
# Generate 1 tip for ALL categories
|
|
100
|
+
.venv/bin/python tip_generator.py -c all -n 1 -p openrouter
|
|
101
|
+
|
|
102
|
+
# Use a specific model
|
|
103
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openrouter -m anthropic/claude-opus-4
|
|
104
|
+
|
|
105
|
+
# Use a custom API URL (e.g., Together.xyz, local LLM server)
|
|
106
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openai -u https://api.together.xyz/v1
|
|
107
|
+
|
|
108
|
+
# Increase max tokens for longer responses (avoid truncation)
|
|
109
|
+
.venv/bin/python tip_generator.py -c 60 -n 20 -p openai --max-tokens 8192
|
|
110
|
+
|
|
111
|
+
# Save tips even if truncated (use with caution)
|
|
112
|
+
.venv/bin/python tip_generator.py -c 35 -n 5 -p openai --save-truncated
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Batch API Notes
|
|
116
|
+
|
|
117
|
+
| Provider | Batch Support | Discount | Notes |
|
|
118
|
+
|----------|---------------|----------|-------|
|
|
119
|
+
| Anthropic | Yes | 50% | Uses `message-batches-2024-09-24` beta |
|
|
120
|
+
| OpenAI | Yes | 50% | Results within 24h |
|
|
121
|
+
| OpenRouter | ⚠️ Sync only | - | Batch API not supported |
|
|
122
|
+
|
|
123
|
+
## Check Batch Status
|
|
124
|
+
|
|
125
|
+
If you ran batch mode with `--no-wait`:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
.venv/bin/python tip_generator.py --check-batch BATCH_ID -p anthropic
|
|
129
|
+
.venv/bin/python tip_generator.py --check-batch BATCH_ID -p openai --save-results
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Output
|
|
133
|
+
|
|
134
|
+
Tips are saved to `tips/{category-name}/{uuid}.md` with 8-character random IDs:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
tips/
|
|
138
|
+
├── core-service/
|
|
139
|
+
│ ├── a1b2c3d4.md
|
|
140
|
+
│ └── e5f6g7h8.md
|
|
141
|
+
└── rare-drush-command/
|
|
142
|
+
└── 9i0j1k2l.md
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Each file has frontmatter:
|
|
146
|
+
|
|
147
|
+
```markdown
|
|
148
|
+
---
|
|
149
|
+
category: core-service
|
|
150
|
+
title: [Generated title]
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
[Tip content]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Configuration
|
|
157
|
+
|
|
158
|
+
Categories and the prompt template are defined in `config.json`:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"prompt_template": "Generate a Drupal tip for category #{cat_id}: {cat_desc}...",
|
|
163
|
+
"code_language": "php",
|
|
164
|
+
"tips_dir": "/path/to/custom/tips",
|
|
165
|
+
"categories": {
|
|
166
|
+
"1": {"name": "proposed-new-module", "desc": "Proposed new module"},
|
|
167
|
+
"35": {"name": "core-service", "desc": "Lesser-known core service"}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Tips Directory Configuration
|
|
173
|
+
|
|
174
|
+
The tips directory can be configured via (in priority order):
|
|
175
|
+
|
|
176
|
+
1. **CLI argument**: `--tips-dir /path/to/tips`
|
|
177
|
+
2. **Environment variable**: `TIPGEN_TIPS_DIR=/path/to/tips`
|
|
178
|
+
3. **Config file**: `"tips_dir": "/path/to/tips"` in `config.json`
|
|
179
|
+
4. **Default**: `tips/` folder in the package directory
|
|
180
|
+
|
|
181
|
+
To add or modify categories, edit `config.json` directly - no code changes needed.
|
|
182
|
+
|
|
183
|
+
## Development
|
|
184
|
+
|
|
185
|
+
### Running Tests
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# Dry run to verify configuration
|
|
189
|
+
.venv/bin/python tip_generator.py -c 35 -n 1 -p openrouter --dry-run
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Validation
|
|
193
|
+
|
|
194
|
+
Validate generated tips for formatting issues, truncation, and quality:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Validate a single file
|
|
198
|
+
.venv/bin/python tip_generator.py --validate --validate-file tips/core-service/a1b2c3d4.md
|
|
199
|
+
|
|
200
|
+
# Validate all tips in a category
|
|
201
|
+
.venv/bin/python tip_generator.py --validate --validate-category core-service
|
|
202
|
+
|
|
203
|
+
# Validate ALL tips across all categories
|
|
204
|
+
.venv/bin/python tip_generator.py --validate --validate-all
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Validation Checks
|
|
208
|
+
|
|
209
|
+
- **Formatting**: Frontmatter structure, code block balance, line counts
|
|
210
|
+
- **Completeness**: Truncation patterns (trailing `...`, `[TODO]`, incomplete code blocks)
|
|
211
|
+
- **Quality**: Generic openings, placeholder text, excessive code ratio
|
|
212
|
+
- **Fake Content**: Non-existent Drupal APIs, hallucinated functions, wrong service names
|
|
213
|
+
|
|
214
|
+
## Web Viewer
|
|
215
|
+
|
|
216
|
+
A simple web UI to browse tips:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
pip install flask
|
|
220
|
+
python tip_viewer.py # http://localhost:5000
|
|
221
|
+
python tip_viewer.py --port 8080 # Custom port
|
|
222
|
+
python tip_viewer.py --host 0.0.0.0 # Public access
|
|
223
|
+
python tip_viewer.py --debug # Debug mode
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Features:
|
|
227
|
+
- Filter tips by category
|
|
228
|
+
- Get random tip with one click
|
|
229
|
+
- View all tips or browse by category
|