@voodocs/cli 0.4.1 → 0.4.2
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 +10 -0
- package/lib/darkarts/cli_darkarts.py +385 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [0.4.2] - 2024-12-20
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
- **npm package**: Added missing `cli_darkarts.py` to package files list
|
|
5
|
+
- Fixes "ModuleNotFoundError: No module named 'darkarts.cli_darkarts'" error
|
|
6
|
+
- DarkArts CLI commands now work correctly after npm install
|
|
7
|
+
- No code changes, only packaging fix
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
1
11
|
## [0.4.1] - 2024-12-20
|
|
2
12
|
|
|
3
13
|
### Fixed
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢cli:darkarts.commands
|
|
3
|
+
∂{argparse,pathlib,annotations}
|
|
4
|
+
⚠{files-exist,valid-paths}
|
|
5
|
+
⊨{∀cmd→exit∈{0,1},user-friendly-errors}
|
|
6
|
+
🔒{read-write-files}
|
|
7
|
+
⚡{O(n)|n=files}
|
|
8
|
+
|
|
9
|
+
DarkArts CLI Commands
|
|
10
|
+
|
|
11
|
+
Provides CLI commands for DarkArts symbolic documentation.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import List, Optional
|
|
17
|
+
|
|
18
|
+
from darkarts.annotations import (
|
|
19
|
+
parse_darkarts,
|
|
20
|
+
DarkArtsParser,
|
|
21
|
+
DarkArtsTranslator,
|
|
22
|
+
convert_voodocs_to_darkarts,
|
|
23
|
+
)
|
|
24
|
+
from darkarts.annotations.parser import AnnotationParser
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def cmd_darkarts_translate(args):
|
|
28
|
+
"""
|
|
29
|
+
Translate DarkArts annotations to natural language or vice versa.
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
voodocs darkarts translate <files> [--to-symbols]
|
|
33
|
+
"""
|
|
34
|
+
print("🔮 DarkArts Translation")
|
|
35
|
+
print("=" * 60)
|
|
36
|
+
print()
|
|
37
|
+
|
|
38
|
+
translator = DarkArtsTranslator()
|
|
39
|
+
to_symbols = args.to_symbols if hasattr(args, 'to_symbols') else False
|
|
40
|
+
|
|
41
|
+
for file_path in args.files:
|
|
42
|
+
path = Path(file_path)
|
|
43
|
+
|
|
44
|
+
if not path.exists():
|
|
45
|
+
print(f"❌ File not found: {file_path}")
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
print(f"📄 {path.name}")
|
|
49
|
+
print("-" * 60)
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
if to_symbols:
|
|
53
|
+
# Natural language → Symbols (VooDocs → DarkArts)
|
|
54
|
+
parser = AnnotationParser()
|
|
55
|
+
annotations = parser.parse_file(str(path))
|
|
56
|
+
|
|
57
|
+
if annotations.module:
|
|
58
|
+
# Convert module annotation
|
|
59
|
+
voodocs_dict = {
|
|
60
|
+
'module_purpose': annotations.module.module_purpose,
|
|
61
|
+
'dependencies': annotations.module.dependencies,
|
|
62
|
+
'assumptions': annotations.module.assumptions,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
darkarts = convert_voodocs_to_darkarts(voodocs_dict)
|
|
66
|
+
print(darkarts)
|
|
67
|
+
else:
|
|
68
|
+
print("⚠️ No @voodocs annotations found")
|
|
69
|
+
else:
|
|
70
|
+
# Symbols → Natural language (DarkArts → Human)
|
|
71
|
+
darkarts_annotations = parse_darkarts(path.read_text())
|
|
72
|
+
|
|
73
|
+
if darkarts_annotations:
|
|
74
|
+
for i, ann in enumerate(darkarts_annotations, 1):
|
|
75
|
+
if len(darkarts_annotations) > 1:
|
|
76
|
+
print(f"\n## Annotation {i}\n")
|
|
77
|
+
natural = translator.symbols_to_natural(ann)
|
|
78
|
+
print(natural)
|
|
79
|
+
else:
|
|
80
|
+
print("⚠️ No @darkarts annotations found")
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"❌ Error: {e}")
|
|
84
|
+
|
|
85
|
+
print()
|
|
86
|
+
|
|
87
|
+
return 0
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def cmd_darkarts_convert(args):
|
|
91
|
+
"""
|
|
92
|
+
Convert files between VooDocs and DarkArts formats.
|
|
93
|
+
|
|
94
|
+
Usage:
|
|
95
|
+
voodocs darkarts convert <files> [--in-place]
|
|
96
|
+
"""
|
|
97
|
+
print("🔄 DarkArts Conversion")
|
|
98
|
+
print("=" * 60)
|
|
99
|
+
print()
|
|
100
|
+
|
|
101
|
+
translator = DarkArtsTranslator()
|
|
102
|
+
in_place = args.in_place if hasattr(args, 'in_place') else False
|
|
103
|
+
|
|
104
|
+
for file_path in args.files:
|
|
105
|
+
path = Path(file_path)
|
|
106
|
+
|
|
107
|
+
if not path.exists():
|
|
108
|
+
print(f"❌ File not found: {file_path}")
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
print(f"📄 {path.name}")
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
content = path.read_text()
|
|
115
|
+
|
|
116
|
+
# Parse VooDocs annotations
|
|
117
|
+
parser = AnnotationParser()
|
|
118
|
+
annotations = parser.parse_file(str(path))
|
|
119
|
+
|
|
120
|
+
if not annotations.module:
|
|
121
|
+
print(" ⚠️ No @voodocs annotations found")
|
|
122
|
+
continue
|
|
123
|
+
|
|
124
|
+
# Convert to DarkArts
|
|
125
|
+
voodocs_dict = {
|
|
126
|
+
'module_purpose': annotations.module.module_purpose,
|
|
127
|
+
'dependencies': annotations.module.dependencies,
|
|
128
|
+
'assumptions': annotations.module.assumptions,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
darkarts = convert_voodocs_to_darkarts(voodocs_dict)
|
|
132
|
+
|
|
133
|
+
if in_place:
|
|
134
|
+
# Replace @voodocs with @darkarts in file
|
|
135
|
+
# This is a simple replacement - in production would be more sophisticated
|
|
136
|
+
new_content = content.replace(
|
|
137
|
+
'"""@voodocs',
|
|
138
|
+
darkarts.replace('"""@darkarts\n', '').replace('\n"""', '')
|
|
139
|
+
)
|
|
140
|
+
path.write_text(new_content)
|
|
141
|
+
print(" ✅ Converted in place")
|
|
142
|
+
else:
|
|
143
|
+
# Print to console
|
|
144
|
+
print(darkarts)
|
|
145
|
+
|
|
146
|
+
except Exception as e:
|
|
147
|
+
print(f" ❌ Error: {e}")
|
|
148
|
+
|
|
149
|
+
print()
|
|
150
|
+
|
|
151
|
+
return 0
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def cmd_darkarts_stats(args):
|
|
155
|
+
"""
|
|
156
|
+
Show statistics about DarkArts annotations.
|
|
157
|
+
|
|
158
|
+
Usage:
|
|
159
|
+
voodocs darkarts stats <paths>
|
|
160
|
+
"""
|
|
161
|
+
print("📊 DarkArts Statistics")
|
|
162
|
+
print("=" * 60)
|
|
163
|
+
print()
|
|
164
|
+
|
|
165
|
+
total_files = 0
|
|
166
|
+
files_with_darkarts = 0
|
|
167
|
+
total_annotations = 0
|
|
168
|
+
total_symbols = 0
|
|
169
|
+
symbol_counts = {}
|
|
170
|
+
|
|
171
|
+
paths = args.paths if hasattr(args, 'paths') else ['.']
|
|
172
|
+
|
|
173
|
+
for path_str in paths:
|
|
174
|
+
path = Path(path_str)
|
|
175
|
+
|
|
176
|
+
if path.is_file():
|
|
177
|
+
files = [path]
|
|
178
|
+
elif path.is_dir():
|
|
179
|
+
files = list(path.rglob('*.py'))
|
|
180
|
+
else:
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
for file_path in files:
|
|
184
|
+
total_files += 1
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
content = file_path.read_text()
|
|
188
|
+
annotations = parse_darkarts(content)
|
|
189
|
+
|
|
190
|
+
if annotations:
|
|
191
|
+
files_with_darkarts += 1
|
|
192
|
+
total_annotations += len(annotations)
|
|
193
|
+
|
|
194
|
+
# Count symbols
|
|
195
|
+
for ann in annotations:
|
|
196
|
+
for char in ann.raw_text:
|
|
197
|
+
if char in ['⊢', '∂', '⚠', '⊨', '🔒', '⚡', '∀', '∃', '∧', '∨', '¬', '⇒', '∈']:
|
|
198
|
+
symbol_counts[char] = symbol_counts.get(char, 0) + 1
|
|
199
|
+
total_symbols += 1
|
|
200
|
+
|
|
201
|
+
except Exception:
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
# Print statistics
|
|
205
|
+
print(f"Total files scanned: {total_files}")
|
|
206
|
+
print(f"Files with @darkarts: {files_with_darkarts}")
|
|
207
|
+
print(f"Total annotations: {total_annotations}")
|
|
208
|
+
print(f"Total symbols used: {total_symbols}")
|
|
209
|
+
|
|
210
|
+
if symbol_counts:
|
|
211
|
+
print("\nMost used symbols:")
|
|
212
|
+
sorted_symbols = sorted(symbol_counts.items(), key=lambda x: x[1], reverse=True)
|
|
213
|
+
for symbol, count in sorted_symbols[:10]:
|
|
214
|
+
print(f" {symbol} : {count}")
|
|
215
|
+
|
|
216
|
+
if total_files > 0:
|
|
217
|
+
coverage = (files_with_darkarts / total_files) * 100
|
|
218
|
+
print(f"\nCoverage: {coverage:.1f}%")
|
|
219
|
+
|
|
220
|
+
print()
|
|
221
|
+
return 0
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def cmd_darkarts_validate(args):
|
|
225
|
+
"""
|
|
226
|
+
Validate DarkArts annotations.
|
|
227
|
+
|
|
228
|
+
Usage:
|
|
229
|
+
voodocs darkarts validate <files>
|
|
230
|
+
"""
|
|
231
|
+
print("✅ DarkArts Validation")
|
|
232
|
+
print("=" * 60)
|
|
233
|
+
print()
|
|
234
|
+
|
|
235
|
+
all_valid = True
|
|
236
|
+
|
|
237
|
+
for file_path in args.files:
|
|
238
|
+
path = Path(file_path)
|
|
239
|
+
|
|
240
|
+
if not path.exists():
|
|
241
|
+
print(f"❌ File not found: {file_path}")
|
|
242
|
+
all_valid = False
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
print(f"📄 {path.name}")
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
content = path.read_text()
|
|
249
|
+
annotations = parse_darkarts(content)
|
|
250
|
+
|
|
251
|
+
if not annotations:
|
|
252
|
+
print(" ⚠️ No @darkarts annotations found")
|
|
253
|
+
continue
|
|
254
|
+
|
|
255
|
+
for i, ann in enumerate(annotations, 1):
|
|
256
|
+
# Basic validation
|
|
257
|
+
issues = []
|
|
258
|
+
|
|
259
|
+
if not ann.module:
|
|
260
|
+
issues.append("Missing module declaration (⊢)")
|
|
261
|
+
|
|
262
|
+
if not ann.dependencies:
|
|
263
|
+
issues.append("Missing dependencies (∂)")
|
|
264
|
+
|
|
265
|
+
if not ann.invariants:
|
|
266
|
+
issues.append("Missing invariants (⊨)")
|
|
267
|
+
|
|
268
|
+
if issues:
|
|
269
|
+
print(f" ⚠️ Annotation {i}:")
|
|
270
|
+
for issue in issues:
|
|
271
|
+
print(f" - {issue}")
|
|
272
|
+
all_valid = False
|
|
273
|
+
else:
|
|
274
|
+
print(f" ✅ Annotation {i}: Valid")
|
|
275
|
+
|
|
276
|
+
except Exception as e:
|
|
277
|
+
print(f" ❌ Error: {e}")
|
|
278
|
+
all_valid = False
|
|
279
|
+
|
|
280
|
+
print()
|
|
281
|
+
|
|
282
|
+
return 0 if all_valid else 1
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def add_darkarts_subcommands(subparsers):
|
|
286
|
+
"""
|
|
287
|
+
Add DarkArts subcommands to VooDocs CLI.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
subparsers: Argparse subparsers object
|
|
291
|
+
"""
|
|
292
|
+
# darkarts command group
|
|
293
|
+
darkarts_parser = subparsers.add_parser(
|
|
294
|
+
"darkarts",
|
|
295
|
+
help="DarkArts symbolic documentation tools"
|
|
296
|
+
)
|
|
297
|
+
darkarts_subparsers = darkarts_parser.add_subparsers(
|
|
298
|
+
dest="darkarts_action",
|
|
299
|
+
help="DarkArts actions"
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
# darkarts translate
|
|
303
|
+
translate_parser = darkarts_subparsers.add_parser(
|
|
304
|
+
"translate",
|
|
305
|
+
help="Translate between symbols and natural language"
|
|
306
|
+
)
|
|
307
|
+
translate_parser.add_argument(
|
|
308
|
+
"files",
|
|
309
|
+
nargs="+",
|
|
310
|
+
help="Files to translate"
|
|
311
|
+
)
|
|
312
|
+
translate_parser.add_argument(
|
|
313
|
+
"--to-symbols",
|
|
314
|
+
action="store_true",
|
|
315
|
+
help="Translate from natural language to symbols (default: symbols to natural)"
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
# darkarts convert
|
|
319
|
+
convert_parser = darkarts_subparsers.add_parser(
|
|
320
|
+
"convert",
|
|
321
|
+
help="Convert VooDocs annotations to DarkArts"
|
|
322
|
+
)
|
|
323
|
+
convert_parser.add_argument(
|
|
324
|
+
"files",
|
|
325
|
+
nargs="+",
|
|
326
|
+
help="Files to convert"
|
|
327
|
+
)
|
|
328
|
+
convert_parser.add_argument(
|
|
329
|
+
"--in-place",
|
|
330
|
+
action="store_true",
|
|
331
|
+
help="Modify files in place (default: print to console)"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
# darkarts stats
|
|
335
|
+
stats_parser = darkarts_subparsers.add_parser(
|
|
336
|
+
"stats",
|
|
337
|
+
help="Show DarkArts usage statistics"
|
|
338
|
+
)
|
|
339
|
+
stats_parser.add_argument(
|
|
340
|
+
"paths",
|
|
341
|
+
nargs="*",
|
|
342
|
+
default=["."],
|
|
343
|
+
help="Paths to analyze (default: current directory)"
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# darkarts validate
|
|
347
|
+
validate_parser = darkarts_subparsers.add_parser(
|
|
348
|
+
"validate",
|
|
349
|
+
help="Validate DarkArts annotations"
|
|
350
|
+
)
|
|
351
|
+
validate_parser.add_argument(
|
|
352
|
+
"files",
|
|
353
|
+
nargs="+",
|
|
354
|
+
help="Files to validate"
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return darkarts_parser
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def dispatch_darkarts_command(args):
|
|
361
|
+
"""
|
|
362
|
+
Dispatch DarkArts subcommands.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
args: Parsed command-line arguments
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Exit code (0 for success, 1 for error)
|
|
369
|
+
"""
|
|
370
|
+
if not hasattr(args, 'darkarts_action') or not args.darkarts_action:
|
|
371
|
+
print("Error: No DarkArts action specified")
|
|
372
|
+
print("Use 'voodocs darkarts --help' for usage")
|
|
373
|
+
return 1
|
|
374
|
+
|
|
375
|
+
if args.darkarts_action == "translate":
|
|
376
|
+
return cmd_darkarts_translate(args)
|
|
377
|
+
elif args.darkarts_action == "convert":
|
|
378
|
+
return cmd_darkarts_convert(args)
|
|
379
|
+
elif args.darkarts_action == "stats":
|
|
380
|
+
return cmd_darkarts_stats(args)
|
|
381
|
+
elif args.darkarts_action == "validate":
|
|
382
|
+
return cmd_darkarts_validate(args)
|
|
383
|
+
else:
|
|
384
|
+
print(f"Error: Unknown DarkArts action: {args.darkarts_action}")
|
|
385
|
+
return 1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voodocs/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "AI-Native Documentation System - Generate docs, tests, and API specs from @voodocs annotations using the DarkArts language",
|
|
5
5
|
"main": "cli.py",
|
|
6
6
|
"bin": {
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"devDependencies": {},
|
|
46
46
|
"files": [
|
|
47
47
|
"cli.py",
|
|
48
|
+
"lib/darkarts/cli_darkarts.py",
|
|
48
49
|
"lib/darkarts/annotations/",
|
|
49
50
|
"lib/darkarts/context/",
|
|
50
51
|
"lib/darkarts/core/",
|