@voodocs/cli 1.0.2 → 1.0.4
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.
- package/CHANGELOG.md +181 -0
- package/lib/cli/__init__.py +3 -1
- package/lib/cli/generate.py +55 -9
- package/lib/cli/instruct.py +108 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,184 @@
|
|
|
1
|
+
## v1.0.4 (2024-12-21)
|
|
2
|
+
|
|
3
|
+
### 🐛 Critical Bug Fixes: Documentation Generation
|
|
4
|
+
|
|
5
|
+
This release fixes critical bugs that prevented documentation generation for TypeScript, JavaScript, and Solidity files.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
#### Issue 1: Annotation Parsing Failure
|
|
12
|
+
**Problem:** The generator failed to recognize valid `@voodocs` or `@darkarts` annotations in TypeScript/JavaScript files.
|
|
13
|
+
|
|
14
|
+
**Root Cause:** The `_extract_annotation` function only looked for Python docstring format (`"""@darkarts`), not TypeScript/JavaScript block comments (`/**@voodocs` or `/**@darkarts`).
|
|
15
|
+
|
|
16
|
+
**Fix:**
|
|
17
|
+
- Added regex pattern matching for TypeScript/JavaScript block comments
|
|
18
|
+
- Support both `/**@voodocs` and `/**@darkarts` tags
|
|
19
|
+
- Support both Python (`"""`) and JS/TS (`/**`) comment styles
|
|
20
|
+
|
|
21
|
+
#### Issue 2: File Discovery Limitations
|
|
22
|
+
**Problem:** When running `voodocs generate . ./docs` in a directory, the tool reported "No Python files found to process" even when TypeScript or Solidity files were present.
|
|
23
|
+
|
|
24
|
+
**Root Cause:** The file discovery logic only looked for `.py` files.
|
|
25
|
+
|
|
26
|
+
**Fix:**
|
|
27
|
+
- Extended file discovery to include: `.py`, `.ts`, `.js`, `.jsx`, `.tsx`, `.sol`
|
|
28
|
+
- Updated error message to list all supported extensions
|
|
29
|
+
|
|
30
|
+
#### Issue 3: Natural Language Format Parsing
|
|
31
|
+
**Problem:** YAML-style annotations (e.g., `module_purpose: "..."`, `dependencies: []`) were not being parsed correctly.
|
|
32
|
+
|
|
33
|
+
**Fix:**
|
|
34
|
+
- Added support for natural language format alongside symbolic format
|
|
35
|
+
- Properly handle YAML-style lists with `-` markers
|
|
36
|
+
- Clean up formatting and remove trailing comment markers
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
### Improvements
|
|
41
|
+
|
|
42
|
+
- **Multi-language Support:** Now works with TypeScript, JavaScript, Solidity, and Python
|
|
43
|
+
- **Dual Format Support:** Accepts both natural language (`module_purpose:`) and symbolic (`⊢{}`) formats
|
|
44
|
+
- **Better Error Messages:** Clear indication of supported file extensions
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
### Testing
|
|
49
|
+
|
|
50
|
+
All reported issues have been tested and verified:
|
|
51
|
+
|
|
52
|
+
| Test Case | Status |
|
|
53
|
+
|-----------|--------|
|
|
54
|
+
| TypeScript file with `/**@voodocs` | ✅ Pass |
|
|
55
|
+
| TypeScript file with `/**@darkarts` | ✅ Pass |
|
|
56
|
+
| Natural language format | ✅ Pass |
|
|
57
|
+
| Symbolic format | ✅ Pass |
|
|
58
|
+
| Directory discovery (`.ts` files) | ✅ Pass |
|
|
59
|
+
| Multiple files in directory | ✅ Pass |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### Example: Now Working
|
|
64
|
+
|
|
65
|
+
**File: test.ts**
|
|
66
|
+
```typescript
|
|
67
|
+
/**@voodocs
|
|
68
|
+
module_purpose: Test module
|
|
69
|
+
dependencies: []
|
|
70
|
+
assumptions:
|
|
71
|
+
- Node.js environment
|
|
72
|
+
*/
|
|
73
|
+
export function hello(name: string): string {
|
|
74
|
+
return `Hello, ${name}`;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Command:**
|
|
79
|
+
```bash
|
|
80
|
+
voodocs generate ./test.ts ./docs
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Result:**
|
|
84
|
+
```markdown
|
|
85
|
+
# test.ts
|
|
86
|
+
|
|
87
|
+
**Module:** `Test module`
|
|
88
|
+
|
|
89
|
+
## Assumptions
|
|
90
|
+
|
|
91
|
+
Node.js environment
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### Upgrade Notes
|
|
97
|
+
|
|
98
|
+
No breaking changes. Simply upgrade:
|
|
99
|
+
```bash
|
|
100
|
+
npm install -g @voodocs/cli@1.0.4
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
All existing annotations continue to work. This release only adds support for previously unsupported file types and formats.
|
|
104
|
+
|
|
105
|
+
## v1.0.3 (2024-12-21)
|
|
106
|
+
|
|
107
|
+
### ✨ New Feature: AI Instruction Generation
|
|
108
|
+
|
|
109
|
+
This release adds the `voodocs instruct` command to automatically generate AI-specific instructions for writing symbolic DarkArts annotations.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
#### `voodocs instruct` Command
|
|
116
|
+
- **Auto-detects AI environment** (Cursor, Claude, Gemini, etc.)
|
|
117
|
+
- **Generates tailored instructions** for each AI assistant
|
|
118
|
+
- **Supports multiple output formats** (console or file)
|
|
119
|
+
- **Lists available templates** with `--list-templates` flag
|
|
120
|
+
|
|
121
|
+
**Usage:**
|
|
122
|
+
```bash
|
|
123
|
+
voodocs instruct # Auto-detect and print instructions
|
|
124
|
+
voodocs instruct --ai cursor # Generate for specific AI
|
|
125
|
+
voodocs instruct --output .cursorrules # Save to file
|
|
126
|
+
voodocs instruct --list-templates # List available templates
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Updated Instruction Templates
|
|
130
|
+
- **Symbolic DarkArts format** - All templates updated to use symbolic annotations
|
|
131
|
+
- **Cursor template** - Tailored for Cursor AI
|
|
132
|
+
- **Claude template** - Tailored for Claude AI
|
|
133
|
+
- **Default template** - Generic instructions for any AI
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### Improved
|
|
138
|
+
|
|
139
|
+
- **AI Instructions** - Now guide AIs to write symbolic `@darkarts` annotations instead of natural language `@voodocs`
|
|
140
|
+
- **Documentation** - Added comprehensive AI instruction guide
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### What This Means
|
|
145
|
+
|
|
146
|
+
With `voodocs instruct`, you can now:
|
|
147
|
+
1. Run the command in your project
|
|
148
|
+
2. Get AI-specific instructions
|
|
149
|
+
3. Add them to your `.cursorrules` or Claude project settings
|
|
150
|
+
4. Have your AI assistant automatically write correct symbolic annotations
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### Example Workflow
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Initialize project
|
|
158
|
+
voodocs init
|
|
159
|
+
|
|
160
|
+
# Generate AI instructions
|
|
161
|
+
voodocs instruct --output .cursorrules
|
|
162
|
+
|
|
163
|
+
# Now your AI will automatically write symbolic annotations!
|
|
164
|
+
# When you write code, your AI adds:
|
|
165
|
+
/**@darkarts
|
|
166
|
+
⊳{userId must be a valid UUID}
|
|
167
|
+
⊲{Returns user object or null}
|
|
168
|
+
⊨{Does ¬ modify database}
|
|
169
|
+
⚡{O(1)}
|
|
170
|
+
*/
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Upgrade Notes
|
|
176
|
+
|
|
177
|
+
No breaking changes. Simply upgrade:
|
|
178
|
+
```bash
|
|
179
|
+
npm install -g @voodocs/cli@1.0.3
|
|
180
|
+
```
|
|
181
|
+
|
|
1
182
|
## v1.0.2 (2024-12-21)
|
|
2
183
|
|
|
3
184
|
### 🔧 Critical Bug Fixes
|
package/lib/cli/__init__.py
CHANGED
|
@@ -16,7 +16,7 @@ This module provides the command-line interface for VooDocs.
|
|
|
16
16
|
import click
|
|
17
17
|
from typing import Optional
|
|
18
18
|
|
|
19
|
-
__version__ = "1.0.
|
|
19
|
+
__version__ = "1.0.4"
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@click.group()
|
|
@@ -35,6 +35,7 @@ def cli(ctx):
|
|
|
35
35
|
|
|
36
36
|
# Import subcommands
|
|
37
37
|
from .init import init
|
|
38
|
+
from .instruct import instruct
|
|
38
39
|
from .validate import validate
|
|
39
40
|
from .generate import generate
|
|
40
41
|
from .benchmark import benchmark
|
|
@@ -42,6 +43,7 @@ from .fix import fix
|
|
|
42
43
|
|
|
43
44
|
# Register commands
|
|
44
45
|
cli.add_command(init)
|
|
46
|
+
cli.add_command(instruct)
|
|
45
47
|
cli.add_command(validate)
|
|
46
48
|
cli.add_command(generate)
|
|
47
49
|
cli.add_command(benchmark)
|
package/lib/cli/generate.py
CHANGED
|
@@ -78,11 +78,19 @@ def generate(
|
|
|
78
78
|
if source_path.is_file():
|
|
79
79
|
files_to_process = [source_path]
|
|
80
80
|
elif source_path.is_dir():
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
# Support multiple file extensions
|
|
82
|
+
extensions = ['*.py', '*.ts', '*.js', '*.jsx', '*.tsx', '*.sol']
|
|
83
|
+
files_to_process = []
|
|
84
|
+
|
|
85
|
+
if recursive:
|
|
86
|
+
for ext in extensions:
|
|
87
|
+
files_to_process.extend([f for f in source_path.glob(f"**/{ext}") if f.is_file()])
|
|
88
|
+
else:
|
|
89
|
+
for ext in extensions:
|
|
90
|
+
files_to_process.extend([f for f in source_path.glob(ext) if f.is_file()])
|
|
83
91
|
|
|
84
92
|
if not files_to_process:
|
|
85
|
-
click.secho("No
|
|
93
|
+
click.secho("No files found to process. Supported extensions: .py, .ts, .js, .jsx, .tsx, .sol", fg='yellow')
|
|
86
94
|
sys.exit(1)
|
|
87
95
|
|
|
88
96
|
click.echo(f"Found {len(files_to_process)} files to process")
|
|
@@ -214,20 +222,58 @@ def _generate_doc_for_file(file_path: Path, format: str, include_private: bool)
|
|
|
214
222
|
|
|
215
223
|
|
|
216
224
|
def _extract_annotation(content: str) -> str:
|
|
217
|
-
"""Extract @darkarts annotation from file content."""
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
225
|
+
"""Extract @darkarts or @voodocs annotation from file content."""
|
|
226
|
+
import re
|
|
227
|
+
|
|
228
|
+
# Try Python docstring format first ("""@darkarts or """@voodocs)
|
|
229
|
+
python_pattern = r'"""@(?:darkarts|voodocs)\s*(.*?)"""'
|
|
230
|
+
match = re.search(python_pattern, content, re.DOTALL)
|
|
231
|
+
if match:
|
|
232
|
+
return match.group(0)
|
|
233
|
+
|
|
234
|
+
# Try TypeScript/JavaScript block comment format (/**@darkarts or /**@voodocs)
|
|
235
|
+
js_pattern = r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\*/'
|
|
236
|
+
match = re.search(js_pattern, content, re.DOTALL)
|
|
237
|
+
if match:
|
|
238
|
+
return match.group(0)
|
|
239
|
+
|
|
222
240
|
return ""
|
|
223
241
|
|
|
224
242
|
|
|
225
243
|
def _extract_section(annotation: str, symbol: str) -> str:
|
|
226
|
-
"""Extract a specific section from annotation."""
|
|
244
|
+
"""Extract a specific section from annotation (supports both symbolic and natural language)."""
|
|
245
|
+
import re
|
|
246
|
+
|
|
247
|
+
# Map symbols to natural language keys
|
|
248
|
+
symbol_to_key = {
|
|
249
|
+
'⊢': 'module_purpose',
|
|
250
|
+
'∂': 'dependencies',
|
|
251
|
+
'⚠': 'assumptions',
|
|
252
|
+
'⊨': 'invariants',
|
|
253
|
+
'🔒': 'security',
|
|
254
|
+
'⚡': 'complexity'
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
# Try symbolic format first
|
|
227
258
|
lines = annotation.split('\n')
|
|
228
259
|
for line in lines:
|
|
229
260
|
if line.strip().startswith(symbol):
|
|
230
261
|
return line.strip()[len(symbol):].strip('{}')
|
|
262
|
+
|
|
263
|
+
# Try natural language format
|
|
264
|
+
key = symbol_to_key.get(symbol)
|
|
265
|
+
if key:
|
|
266
|
+
# Match key: value or key: [list]
|
|
267
|
+
pattern = rf'{key}\s*:\s*(.+?)(?=\n[a-z_]+\s*:|\*/|$)'
|
|
268
|
+
match = re.search(pattern, annotation, re.DOTALL | re.IGNORECASE)
|
|
269
|
+
if match:
|
|
270
|
+
value = match.group(1).strip()
|
|
271
|
+
# Clean up list formatting and remove trailing comment markers
|
|
272
|
+
value = value.strip('[]').strip()
|
|
273
|
+
# Remove YAML list markers and join lines
|
|
274
|
+
lines = [line.strip().lstrip('-').strip() for line in value.split('\n') if line.strip()]
|
|
275
|
+
return ', '.join(lines)
|
|
276
|
+
|
|
231
277
|
return ""
|
|
232
278
|
|
|
233
279
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢{cli:instruct}
|
|
3
|
+
∂{click,pathlib,darkarts.instruction_generator,darkarts.ai_detector}
|
|
4
|
+
⚠{write-access:cwd}
|
|
5
|
+
⊨{idempotent:instruction-generation}
|
|
6
|
+
🔒{read-write:filesystem}
|
|
7
|
+
⚡{O(1):file-creation}
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
VooDocs Instruct Command
|
|
12
|
+
|
|
13
|
+
Generate AI-specific instructions for writing @darkarts annotations.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
# Add parent directory to path for imports
|
|
22
|
+
parent_dir = Path(__file__).parent.parent
|
|
23
|
+
sys.path.insert(0, str(parent_dir))
|
|
24
|
+
|
|
25
|
+
from darkarts.instruction_generator import InstructionGenerator
|
|
26
|
+
from darkarts.ai_detector import AIEnvironment, detect_ai_environment
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@click.command()
|
|
30
|
+
@click.option(
|
|
31
|
+
'--ai',
|
|
32
|
+
type=click.Choice([e.value for e in AIEnvironment], case_sensitive=False),
|
|
33
|
+
default=None,
|
|
34
|
+
help='Specify the AI environment (e.g., cursor, claude, gemini). Auto-detects if not provided.'
|
|
35
|
+
)
|
|
36
|
+
@click.option(
|
|
37
|
+
'--output',
|
|
38
|
+
type=click.Path(dir_okay=False, writable=True),
|
|
39
|
+
default=None,
|
|
40
|
+
help='Output file path. Prints to console if not provided.'
|
|
41
|
+
)
|
|
42
|
+
@click.option(
|
|
43
|
+
'--list-templates',
|
|
44
|
+
is_flag=True,
|
|
45
|
+
help='List all available AI instruction templates.'
|
|
46
|
+
)
|
|
47
|
+
def instruct(ai, output, list_templates):
|
|
48
|
+
"""
|
|
49
|
+
Generate AI instructions for writing symbolic @darkarts annotations.
|
|
50
|
+
|
|
51
|
+
Detects the AI environment (Cursor, Claude, etc.) and generates tailored
|
|
52
|
+
instructions to guide the AI in writing correct symbolic annotations.
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
voodocs instruct # Auto-detect AI and print instructions
|
|
56
|
+
voodocs instruct --ai cursor # Generate instructions for Cursor
|
|
57
|
+
voodocs instruct --output .cursorrules # Save to .cursorrules file
|
|
58
|
+
voodocs instruct --list-templates # List available templates
|
|
59
|
+
"""
|
|
60
|
+
generator = InstructionGenerator()
|
|
61
|
+
|
|
62
|
+
if list_templates:
|
|
63
|
+
templates = generator.list_available_templates()
|
|
64
|
+
if not templates:
|
|
65
|
+
click.echo(click.style('No instruction templates found.', fg='yellow'))
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
click.echo(click.style('Available AI instruction templates:', fg='green', bold=True))
|
|
69
|
+
for template in templates:
|
|
70
|
+
click.echo(f'- {template}')
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
# Determine AI environment
|
|
74
|
+
if ai:
|
|
75
|
+
try:
|
|
76
|
+
environment = AIEnvironment(ai.lower())
|
|
77
|
+
except ValueError:
|
|
78
|
+
click.echo(click.style(f'Error: Invalid AI environment "{ai}"', fg='red'))
|
|
79
|
+
click.echo(f'Available options: {[e.value for e in AIEnvironment]}')
|
|
80
|
+
return
|
|
81
|
+
else:
|
|
82
|
+
environment = detect_ai_environment()
|
|
83
|
+
click.echo(click.style(f'Auto-detected AI environment: {environment.value}', fg='cyan'))
|
|
84
|
+
|
|
85
|
+
# Generate instructions
|
|
86
|
+
try:
|
|
87
|
+
instructions = generator.generate(environment)
|
|
88
|
+
except FileNotFoundError:
|
|
89
|
+
click.echo(click.style(f'Error: No instruction template found for {environment.value}', fg='red'))
|
|
90
|
+
click.echo(f'Defaulting to generic instructions...')
|
|
91
|
+
environment = AIEnvironment.DEFAULT
|
|
92
|
+
instructions = generator.generate(environment)
|
|
93
|
+
|
|
94
|
+
# Output instructions
|
|
95
|
+
if output:
|
|
96
|
+
output_path = Path(output)
|
|
97
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
98
|
+
output_path.write_text(instructions, encoding='utf-8')
|
|
99
|
+
click.echo(click.style(f'✓ Instructions saved to {output_path}', fg='green'))
|
|
100
|
+
else:
|
|
101
|
+
click.echo('\n' + '-'*20 + ' AI Instructions ' + '-'*20 + '\n')
|
|
102
|
+
click.echo(instructions)
|
|
103
|
+
click.echo('\n' + '-'*58 + '\n')
|
|
104
|
+
|
|
105
|
+
if environment == AIEnvironment.CURSOR and not output:
|
|
106
|
+
click.echo(click.style('Tip: Save these instructions to a .cursorrules file in your project root.', fg='yellow'))
|
|
107
|
+
elif environment == AIEnvironment.CLAUDE and not output:
|
|
108
|
+
click.echo(click.style('Tip: Add these instructions to your Claude project settings.', fg='yellow'))
|
package/package.json
CHANGED