@techwavedev/agi-agent-kit 1.1.3
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 +59 -0
- package/README.md +147 -0
- package/bin/init.js +471 -0
- package/package.json +36 -0
- package/templates/.agent/agents/backend-specialist.md +263 -0
- package/templates/.agent/agents/code-archaeologist.md +106 -0
- package/templates/.agent/agents/database-architect.md +226 -0
- package/templates/.agent/agents/debugger.md +225 -0
- package/templates/.agent/agents/devops-engineer.md +242 -0
- package/templates/.agent/agents/documentation-writer.md +104 -0
- package/templates/.agent/agents/explorer-agent.md +73 -0
- package/templates/.agent/agents/frontend-specialist.md +556 -0
- package/templates/.agent/agents/game-developer.md +162 -0
- package/templates/.agent/agents/mobile-developer.md +377 -0
- package/templates/.agent/agents/orchestrator.md +416 -0
- package/templates/.agent/agents/penetration-tester.md +188 -0
- package/templates/.agent/agents/performance-optimizer.md +187 -0
- package/templates/.agent/agents/product-manager.md +112 -0
- package/templates/.agent/agents/project-planner.md +403 -0
- package/templates/.agent/agents/qa-automation-engineer.md +109 -0
- package/templates/.agent/agents/security-auditor.md +170 -0
- package/templates/.agent/agents/seo-specialist.md +111 -0
- package/templates/.agent/agents/test-engineer.md +158 -0
- package/templates/.agent/rules/GEMINI.md +253 -0
- package/templates/.agent/workflows/brainstorm.md +113 -0
- package/templates/.agent/workflows/create.md +59 -0
- package/templates/.agent/workflows/debug.md +103 -0
- package/templates/.agent/workflows/deploy.md +176 -0
- package/templates/.agent/workflows/enhance.md +63 -0
- package/templates/.agent/workflows/orchestrate.md +237 -0
- package/templates/.agent/workflows/plan.md +89 -0
- package/templates/.agent/workflows/preview.md +81 -0
- package/templates/.agent/workflows/status.md +86 -0
- package/templates/.agent/workflows/test.md +144 -0
- package/templates/.agent/workflows/ui-ux-pro-max.md +296 -0
- package/templates/base/.env.example +54 -0
- package/templates/base/AGENTS.md +463 -0
- package/templates/base/requirements.txt +6 -0
- package/templates/base/skill-creator/LICENSE.txt +202 -0
- package/templates/base/skill-creator/SKILL_skillcreator.md +389 -0
- package/templates/base/skill-creator/references/output-patterns.md +82 -0
- package/templates/base/skill-creator/references/workflows.md +28 -0
- package/templates/base/skill-creator/scripts/init_skill.py +304 -0
- package/templates/base/skill-creator/scripts/package_skill.py +110 -0
- package/templates/base/skill-creator/scripts/quick_validate.py +95 -0
- package/templates/base/skill-creator/scripts/update_catalog.py +371 -0
- package/templates/skills/core/README.md +21 -0
- package/templates/skills/core/documentation/SKILL.md +351 -0
- package/templates/skills/core/documentation/references/best_practices.md +201 -0
- package/templates/skills/core/documentation/scripts/analyze_code.py +307 -0
- package/templates/skills/core/documentation/scripts/detect_changes.py +460 -0
- package/templates/skills/core/documentation/scripts/generate_changelog.py +312 -0
- package/templates/skills/core/documentation/scripts/sync_docs.py +272 -0
- package/templates/skills/core/documentation/scripts/update_skill_docs.py +366 -0
- package/templates/skills/core/pdf-reader/SKILL.md +104 -0
- package/templates/skills/core/pdf-reader/references/pdf_libraries.md +83 -0
- package/templates/skills/core/pdf-reader/scripts/extract_text.py +295 -0
- package/templates/skills/core/qdrant-memory/SKILL.md +435 -0
- package/templates/skills/core/qdrant-memory/references/advanced_patterns.md +375 -0
- package/templates/skills/core/qdrant-memory/references/collection_schemas.md +229 -0
- package/templates/skills/core/qdrant-memory/references/complete_guide.md +724 -0
- package/templates/skills/core/qdrant-memory/references/embedding_models.md +325 -0
- package/templates/skills/core/qdrant-memory/scripts/benchmark_token_savings.py +640 -0
- package/templates/skills/core/qdrant-memory/scripts/embedding_utils.py +323 -0
- package/templates/skills/core/qdrant-memory/scripts/hybrid_search.py +214 -0
- package/templates/skills/core/qdrant-memory/scripts/init_collection.py +193 -0
- package/templates/skills/core/qdrant-memory/scripts/memory_retrieval.py +345 -0
- package/templates/skills/core/qdrant-memory/scripts/semantic_cache.py +282 -0
- package/templates/skills/core/qdrant-memory/scripts/test_skill.py +655 -0
- package/templates/skills/core/webcrawler/SKILL.md +292 -0
- package/templates/skills/core/webcrawler/references/advanced_crawling.md +181 -0
- package/templates/skills/core/webcrawler/scripts/crawl_docs.py +532 -0
- package/templates/skills/core/webcrawler/scripts/extract_page.py +189 -0
- package/templates/skills/core/webcrawler/scripts/filter_docs.py +200 -0
- package/templates/skills/knowledge/api-patterns/SKILL.md +81 -0
- package/templates/skills/knowledge/api-patterns/api-style.md +42 -0
- package/templates/skills/knowledge/api-patterns/auth.md +24 -0
- package/templates/skills/knowledge/api-patterns/documentation.md +26 -0
- package/templates/skills/knowledge/api-patterns/graphql.md +41 -0
- package/templates/skills/knowledge/api-patterns/rate-limiting.md +31 -0
- package/templates/skills/knowledge/api-patterns/response.md +37 -0
- package/templates/skills/knowledge/api-patterns/rest.md +40 -0
- package/templates/skills/knowledge/api-patterns/scripts/api_validator.py +211 -0
- package/templates/skills/knowledge/api-patterns/security-testing.md +122 -0
- package/templates/skills/knowledge/api-patterns/trpc.md +41 -0
- package/templates/skills/knowledge/api-patterns/versioning.md +22 -0
- package/templates/skills/knowledge/app-builder/SKILL.md +75 -0
- package/templates/skills/knowledge/app-builder/agent-coordination.md +71 -0
- package/templates/skills/knowledge/app-builder/feature-building.md +53 -0
- package/templates/skills/knowledge/app-builder/project-detection.md +34 -0
- package/templates/skills/knowledge/app-builder/scaffolding.md +118 -0
- package/templates/skills/knowledge/app-builder/tech-stack.md +40 -0
- package/templates/skills/knowledge/app-builder/templates/SKILL.md +39 -0
- package/templates/skills/knowledge/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/templates/skills/knowledge/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/templates/skills/knowledge/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/templates/skills/knowledge/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/templates/skills/knowledge/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/templates/skills/knowledge/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/templates/skills/knowledge/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/templates/skills/knowledge/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
- package/templates/skills/knowledge/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
- package/templates/skills/knowledge/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
- package/templates/skills/knowledge/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
- package/templates/skills/knowledge/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/templates/skills/knowledge/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
- package/templates/skills/knowledge/architecture/SKILL.md +55 -0
- package/templates/skills/knowledge/architecture/context-discovery.md +43 -0
- package/templates/skills/knowledge/architecture/examples.md +94 -0
- package/templates/skills/knowledge/architecture/pattern-selection.md +68 -0
- package/templates/skills/knowledge/architecture/patterns-reference.md +50 -0
- package/templates/skills/knowledge/architecture/trade-off-analysis.md +77 -0
- package/templates/skills/knowledge/bash-linux/SKILL.md +199 -0
- package/templates/skills/knowledge/behavioral-modes/SKILL.md +242 -0
- package/templates/skills/knowledge/brainstorming/SKILL.md +163 -0
- package/templates/skills/knowledge/brainstorming/dynamic-questioning.md +350 -0
- package/templates/skills/knowledge/clean-code/SKILL.md +201 -0
- package/templates/skills/knowledge/code-review-checklist/SKILL.md +109 -0
- package/templates/skills/knowledge/database-design/SKILL.md +52 -0
- package/templates/skills/knowledge/database-design/database-selection.md +43 -0
- package/templates/skills/knowledge/database-design/indexing.md +39 -0
- package/templates/skills/knowledge/database-design/migrations.md +48 -0
- package/templates/skills/knowledge/database-design/optimization.md +36 -0
- package/templates/skills/knowledge/database-design/orm-selection.md +30 -0
- package/templates/skills/knowledge/database-design/schema-design.md +56 -0
- package/templates/skills/knowledge/database-design/scripts/schema_validator.py +172 -0
- package/templates/skills/knowledge/deployment-procedures/SKILL.md +241 -0
- package/templates/skills/knowledge/doc.md +177 -0
- package/templates/skills/knowledge/documentation-templates/SKILL.md +194 -0
- package/templates/skills/knowledge/frontend-design/SKILL.md +396 -0
- package/templates/skills/knowledge/frontend-design/animation-guide.md +331 -0
- package/templates/skills/knowledge/frontend-design/color-system.md +311 -0
- package/templates/skills/knowledge/frontend-design/decision-trees.md +418 -0
- package/templates/skills/knowledge/frontend-design/motion-graphics.md +306 -0
- package/templates/skills/knowledge/frontend-design/scripts/accessibility_checker.py +183 -0
- package/templates/skills/knowledge/frontend-design/scripts/ux_audit.py +722 -0
- package/templates/skills/knowledge/frontend-design/typography-system.md +345 -0
- package/templates/skills/knowledge/frontend-design/ux-psychology.md +541 -0
- package/templates/skills/knowledge/frontend-design/visual-effects.md +383 -0
- package/templates/skills/knowledge/game-development/2d-games/SKILL.md +119 -0
- package/templates/skills/knowledge/game-development/3d-games/SKILL.md +135 -0
- package/templates/skills/knowledge/game-development/SKILL.md +167 -0
- package/templates/skills/knowledge/game-development/game-art/SKILL.md +185 -0
- package/templates/skills/knowledge/game-development/game-audio/SKILL.md +190 -0
- package/templates/skills/knowledge/game-development/game-design/SKILL.md +129 -0
- package/templates/skills/knowledge/game-development/mobile-games/SKILL.md +108 -0
- package/templates/skills/knowledge/game-development/multiplayer/SKILL.md +132 -0
- package/templates/skills/knowledge/game-development/pc-games/SKILL.md +144 -0
- package/templates/skills/knowledge/game-development/vr-ar/SKILL.md +123 -0
- package/templates/skills/knowledge/game-development/web-games/SKILL.md +150 -0
- package/templates/skills/knowledge/geo-fundamentals/SKILL.md +156 -0
- package/templates/skills/knowledge/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/templates/skills/knowledge/i18n-localization/SKILL.md +154 -0
- package/templates/skills/knowledge/i18n-localization/scripts/i18n_checker.py +241 -0
- package/templates/skills/knowledge/intelligent-routing/SKILL.md +334 -0
- package/templates/skills/knowledge/lint-and-validate/SKILL.md +45 -0
- package/templates/skills/knowledge/lint-and-validate/scripts/lint_runner.py +172 -0
- package/templates/skills/knowledge/lint-and-validate/scripts/type_coverage.py +173 -0
- package/templates/skills/knowledge/mcp-builder/SKILL.md +176 -0
- package/templates/skills/knowledge/mobile-design/SKILL.md +394 -0
- package/templates/skills/knowledge/mobile-design/decision-trees.md +516 -0
- package/templates/skills/knowledge/mobile-design/mobile-backend.md +491 -0
- package/templates/skills/knowledge/mobile-design/mobile-color-system.md +420 -0
- package/templates/skills/knowledge/mobile-design/mobile-debugging.md +122 -0
- package/templates/skills/knowledge/mobile-design/mobile-design-thinking.md +357 -0
- package/templates/skills/knowledge/mobile-design/mobile-navigation.md +458 -0
- package/templates/skills/knowledge/mobile-design/mobile-performance.md +767 -0
- package/templates/skills/knowledge/mobile-design/mobile-testing.md +356 -0
- package/templates/skills/knowledge/mobile-design/mobile-typography.md +433 -0
- package/templates/skills/knowledge/mobile-design/platform-android.md +666 -0
- package/templates/skills/knowledge/mobile-design/platform-ios.md +561 -0
- package/templates/skills/knowledge/mobile-design/scripts/mobile_audit.py +670 -0
- package/templates/skills/knowledge/mobile-design/touch-psychology.md +537 -0
- package/templates/skills/knowledge/nextjs-best-practices/SKILL.md +203 -0
- package/templates/skills/knowledge/nodejs-best-practices/SKILL.md +333 -0
- package/templates/skills/knowledge/parallel-agents/SKILL.md +175 -0
- package/templates/skills/knowledge/performance-profiling/SKILL.md +143 -0
- package/templates/skills/knowledge/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/templates/skills/knowledge/plan-writing/SKILL.md +152 -0
- package/templates/skills/knowledge/powershell-windows/SKILL.md +167 -0
- package/templates/skills/knowledge/python-patterns/SKILL.md +441 -0
- package/templates/skills/knowledge/react-patterns/SKILL.md +198 -0
- package/templates/skills/knowledge/red-team-tactics/SKILL.md +199 -0
- package/templates/skills/knowledge/seo-fundamentals/SKILL.md +129 -0
- package/templates/skills/knowledge/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/templates/skills/knowledge/server-management/SKILL.md +161 -0
- package/templates/skills/knowledge/systematic-debugging/SKILL.md +109 -0
- package/templates/skills/knowledge/tailwind-patterns/SKILL.md +269 -0
- package/templates/skills/knowledge/tdd-workflow/SKILL.md +149 -0
- package/templates/skills/knowledge/testing-patterns/SKILL.md +178 -0
- package/templates/skills/knowledge/testing-patterns/scripts/test_runner.py +219 -0
- package/templates/skills/knowledge/vulnerability-scanner/SKILL.md +276 -0
- package/templates/skills/knowledge/vulnerability-scanner/checklists.md +121 -0
- package/templates/skills/knowledge/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/templates/skills/knowledge/webapp-testing/SKILL.md +187 -0
- package/templates/skills/knowledge/webapp-testing/scripts/playwright_runner.py +173 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Skill Documentation Updater
|
|
4
|
+
|
|
5
|
+
Updates documentation for a specific skill based on its current state.
|
|
6
|
+
Extracts information from scripts, references, and updates SKILL.md.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python update_skill_docs.py --skill <name> [options]
|
|
10
|
+
|
|
11
|
+
Arguments:
|
|
12
|
+
--skill Skill name to update (required)
|
|
13
|
+
--skills-dir Skills directory (default: skills/)
|
|
14
|
+
--changelog Generate changelog entry (optional)
|
|
15
|
+
--analyze-scripts Analyze script docstrings (default: true)
|
|
16
|
+
--update-references Update references list (default: true)
|
|
17
|
+
--dry-run Preview changes without writing (optional)
|
|
18
|
+
|
|
19
|
+
Exit Codes:
|
|
20
|
+
0 - Success
|
|
21
|
+
1 - Invalid arguments
|
|
22
|
+
2 - Skill not found
|
|
23
|
+
3 - Parse error
|
|
24
|
+
4 - Write error
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
import ast
|
|
29
|
+
import re
|
|
30
|
+
import sys
|
|
31
|
+
from datetime import datetime
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
from typing import Dict, List, Optional, Tuple
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def parse_skill_md(skill_path: Path) -> Tuple[Dict, str]:
|
|
37
|
+
"""
|
|
38
|
+
Parse SKILL.md into frontmatter and body.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
(frontmatter_dict, body_string)
|
|
42
|
+
"""
|
|
43
|
+
content = skill_path.read_text()
|
|
44
|
+
|
|
45
|
+
if not content.startswith('---'):
|
|
46
|
+
return {}, content
|
|
47
|
+
|
|
48
|
+
parts = content.split('---', 2)
|
|
49
|
+
if len(parts) < 3:
|
|
50
|
+
return {}, content
|
|
51
|
+
|
|
52
|
+
frontmatter_raw = parts[1].strip()
|
|
53
|
+
body = parts[2]
|
|
54
|
+
|
|
55
|
+
# Parse simple YAML
|
|
56
|
+
frontmatter = {}
|
|
57
|
+
for line in frontmatter_raw.split('\n'):
|
|
58
|
+
if ':' in line:
|
|
59
|
+
key, value = line.split(':', 1)
|
|
60
|
+
frontmatter[key.strip()] = value.strip().strip('"\'')
|
|
61
|
+
|
|
62
|
+
return frontmatter, body
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def extract_script_info(script_path: Path) -> Dict:
|
|
66
|
+
"""
|
|
67
|
+
Extract documentation info from a Python script.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Dict with: name, docstring, functions, usage
|
|
71
|
+
"""
|
|
72
|
+
try:
|
|
73
|
+
content = script_path.read_text()
|
|
74
|
+
tree = ast.parse(content)
|
|
75
|
+
except SyntaxError as e:
|
|
76
|
+
return {
|
|
77
|
+
'name': script_path.name,
|
|
78
|
+
'docstring': f'[Parse error: {e}]',
|
|
79
|
+
'functions': [],
|
|
80
|
+
'usage': None
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
info = {
|
|
84
|
+
'name': script_path.name,
|
|
85
|
+
'docstring': '',
|
|
86
|
+
'functions': [],
|
|
87
|
+
'usage': None
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Get module docstring
|
|
91
|
+
if tree.body and isinstance(tree.body[0], ast.Expr):
|
|
92
|
+
if isinstance(tree.body[0].value, ast.Constant):
|
|
93
|
+
info['docstring'] = tree.body[0].value.value or ''
|
|
94
|
+
|
|
95
|
+
# Extract usage from docstring
|
|
96
|
+
if 'Usage:' in info['docstring']:
|
|
97
|
+
usage_match = re.search(r'Usage:\s*\n(.*?)(?:\n\n|\nArguments:|\nExit)',
|
|
98
|
+
info['docstring'], re.DOTALL)
|
|
99
|
+
if usage_match:
|
|
100
|
+
info['usage'] = usage_match.group(1).strip()
|
|
101
|
+
|
|
102
|
+
# Get main function definitions
|
|
103
|
+
for node in ast.walk(tree):
|
|
104
|
+
if isinstance(node, ast.FunctionDef):
|
|
105
|
+
func_info = {
|
|
106
|
+
'name': node.name,
|
|
107
|
+
'docstring': ast.get_docstring(node) or '',
|
|
108
|
+
'args': [arg.arg for arg in node.args.args if arg.arg != 'self']
|
|
109
|
+
}
|
|
110
|
+
info['functions'].append(func_info)
|
|
111
|
+
|
|
112
|
+
return info
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def get_first_line_description(docstring: str) -> str:
|
|
116
|
+
"""Extract the first meaningful line from a docstring."""
|
|
117
|
+
if not docstring:
|
|
118
|
+
return '*[See script for details]*'
|
|
119
|
+
|
|
120
|
+
# Skip empty lines and get first content line
|
|
121
|
+
lines = [l.strip() for l in docstring.split('\n') if l.strip()]
|
|
122
|
+
if lines:
|
|
123
|
+
first_line = lines[0]
|
|
124
|
+
# Truncate if too long
|
|
125
|
+
if len(first_line) > 100:
|
|
126
|
+
return first_line[:97] + '...'
|
|
127
|
+
return first_line
|
|
128
|
+
|
|
129
|
+
return '*[See script for details]*'
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def scan_skill_scripts(skill_dir: Path) -> List[Dict]:
|
|
133
|
+
"""Scan all Python scripts in a skill's scripts/ directory."""
|
|
134
|
+
scripts_dir = skill_dir / 'scripts'
|
|
135
|
+
if not scripts_dir.exists():
|
|
136
|
+
return []
|
|
137
|
+
|
|
138
|
+
scripts = []
|
|
139
|
+
for script_path in sorted(scripts_dir.glob('*.py')):
|
|
140
|
+
if script_path.name.startswith('__') or script_path.name.startswith('example'):
|
|
141
|
+
continue
|
|
142
|
+
|
|
143
|
+
info = extract_script_info(script_path)
|
|
144
|
+
scripts.append(info)
|
|
145
|
+
|
|
146
|
+
return scripts
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def scan_skill_references(skill_dir: Path) -> List[str]:
|
|
150
|
+
"""Scan all reference files in a skill's references/ directory."""
|
|
151
|
+
refs_dir = skill_dir / 'references'
|
|
152
|
+
if not refs_dir.exists():
|
|
153
|
+
return []
|
|
154
|
+
|
|
155
|
+
refs = []
|
|
156
|
+
for ref_path in sorted(refs_dir.glob('*.md')):
|
|
157
|
+
if ref_path.name.startswith('example'):
|
|
158
|
+
continue
|
|
159
|
+
refs.append(ref_path.name)
|
|
160
|
+
|
|
161
|
+
return refs
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def update_last_updated(body: str) -> str:
|
|
165
|
+
"""Update the 'Last Updated' timestamp in the body."""
|
|
166
|
+
today = datetime.now().strftime('%Y-%m-%d')
|
|
167
|
+
|
|
168
|
+
# Pattern: > **Last Updated:** YYYY-MM-DD
|
|
169
|
+
pattern = r'>\s*\*\*Last Updated:\*\*\s*\d{4}-\d{2}-\d{2}'
|
|
170
|
+
replacement = f'> **Last Updated:** {today}'
|
|
171
|
+
|
|
172
|
+
if re.search(pattern, body):
|
|
173
|
+
return re.sub(pattern, replacement, body)
|
|
174
|
+
|
|
175
|
+
# If not found, try to add it after the first heading
|
|
176
|
+
lines = body.split('\n')
|
|
177
|
+
for i, line in enumerate(lines):
|
|
178
|
+
if line.startswith('# ') and i < len(lines) - 1:
|
|
179
|
+
# Insert after heading and any following empty line
|
|
180
|
+
insert_at = i + 1
|
|
181
|
+
while insert_at < len(lines) and not lines[insert_at].strip():
|
|
182
|
+
insert_at += 1
|
|
183
|
+
|
|
184
|
+
lines.insert(insert_at, '')
|
|
185
|
+
lines.insert(insert_at + 1, replacement)
|
|
186
|
+
lines.insert(insert_at + 2, '')
|
|
187
|
+
break
|
|
188
|
+
|
|
189
|
+
return '\n'.join(lines)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def generate_scripts_section(scripts: List[Dict]) -> str:
|
|
193
|
+
"""Generate a markdown section for scripts."""
|
|
194
|
+
if not scripts:
|
|
195
|
+
return ""
|
|
196
|
+
|
|
197
|
+
lines = [
|
|
198
|
+
"## Scripts",
|
|
199
|
+
""
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
for script in scripts:
|
|
203
|
+
lines.append(f"### `{script['name']}`")
|
|
204
|
+
lines.append("")
|
|
205
|
+
|
|
206
|
+
# First line of docstring as description
|
|
207
|
+
desc = get_first_line_description(script['docstring'])
|
|
208
|
+
if desc and desc != '*[See script for details]*':
|
|
209
|
+
lines.append(desc)
|
|
210
|
+
lines.append("")
|
|
211
|
+
|
|
212
|
+
# Usage example if available
|
|
213
|
+
if script['usage']:
|
|
214
|
+
lines.append("```bash")
|
|
215
|
+
for usage_line in script['usage'].split('\n'):
|
|
216
|
+
lines.append(usage_line)
|
|
217
|
+
lines.append("```")
|
|
218
|
+
lines.append("")
|
|
219
|
+
|
|
220
|
+
return '\n'.join(lines)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def generate_references_section(references: List[str]) -> str:
|
|
224
|
+
"""Generate a markdown section for references."""
|
|
225
|
+
if not references:
|
|
226
|
+
return ""
|
|
227
|
+
|
|
228
|
+
lines = [
|
|
229
|
+
"## References",
|
|
230
|
+
""
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
for ref in references:
|
|
234
|
+
ref_name = ref.replace('.md', '').replace('_', ' ').title()
|
|
235
|
+
lines.append(f"- [`{ref}`](references/{ref}) — {ref_name}")
|
|
236
|
+
|
|
237
|
+
lines.append("")
|
|
238
|
+
return '\n'.join(lines)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def generate_changelog_entry(skill_name: str, scripts: List[Dict], refs: List[str]) -> str:
|
|
242
|
+
"""Generate a changelog entry for the skill update."""
|
|
243
|
+
today = datetime.now().strftime('%Y-%m-%d')
|
|
244
|
+
|
|
245
|
+
lines = [
|
|
246
|
+
f"## [{today}] - {skill_name} Documentation Update",
|
|
247
|
+
"",
|
|
248
|
+
"### Changed",
|
|
249
|
+
f"- Updated documentation for `{skill_name}` skill",
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
if scripts:
|
|
253
|
+
lines.append(f"- Updated scripts documentation ({len(scripts)} scripts)")
|
|
254
|
+
|
|
255
|
+
if refs:
|
|
256
|
+
lines.append(f"- Updated references listing ({len(refs)} references)")
|
|
257
|
+
|
|
258
|
+
lines.extend(["", ""])
|
|
259
|
+
return '\n'.join(lines)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def update_skill_md(skill_dir: Path, scripts: List[Dict], refs: List[str],
|
|
263
|
+
dry_run: bool = False) -> Tuple[bool, str]:
|
|
264
|
+
"""
|
|
265
|
+
Update the SKILL.md file with current script and reference information.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
(success, message)
|
|
269
|
+
"""
|
|
270
|
+
skill_md_path = skill_dir / 'SKILL.md'
|
|
271
|
+
|
|
272
|
+
if not skill_md_path.exists():
|
|
273
|
+
return False, f"SKILL.md not found in {skill_dir}"
|
|
274
|
+
|
|
275
|
+
frontmatter, body = parse_skill_md(skill_md_path)
|
|
276
|
+
|
|
277
|
+
if not frontmatter:
|
|
278
|
+
return False, "Could not parse SKILL.md frontmatter"
|
|
279
|
+
|
|
280
|
+
# Update last updated timestamp
|
|
281
|
+
body = update_last_updated(body)
|
|
282
|
+
|
|
283
|
+
# TODO: More sophisticated body updates could be done here
|
|
284
|
+
# For now, we just update the timestamp and leave content intact
|
|
285
|
+
# A more advanced version could:
|
|
286
|
+
# - Update scripts section with extracted docstrings
|
|
287
|
+
# - Update references section with current files
|
|
288
|
+
# - Add missing sections
|
|
289
|
+
|
|
290
|
+
# Rebuild SKILL.md
|
|
291
|
+
new_content = '---\n'
|
|
292
|
+
for key, value in frontmatter.items():
|
|
293
|
+
if ' ' in value or ':' in value or value.startswith('['):
|
|
294
|
+
new_content += f'{key}: "{value}"\n'
|
|
295
|
+
else:
|
|
296
|
+
new_content += f'{key}: {value}\n'
|
|
297
|
+
new_content += '---\n'
|
|
298
|
+
new_content += body
|
|
299
|
+
|
|
300
|
+
if dry_run:
|
|
301
|
+
return True, "Dry run - no changes written"
|
|
302
|
+
|
|
303
|
+
try:
|
|
304
|
+
skill_md_path.write_text(new_content)
|
|
305
|
+
return True, f"Updated {skill_md_path}"
|
|
306
|
+
except Exception as e:
|
|
307
|
+
return False, f"Write error: {e}"
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def main():
|
|
311
|
+
parser = argparse.ArgumentParser(
|
|
312
|
+
description='Update skill documentation',
|
|
313
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
314
|
+
epilog=__doc__
|
|
315
|
+
)
|
|
316
|
+
parser.add_argument('--skill', required=True, help='Skill name to update')
|
|
317
|
+
parser.add_argument('--skills-dir', default='skills/', help='Skills directory')
|
|
318
|
+
parser.add_argument('--changelog', action='store_true', help='Generate changelog entry')
|
|
319
|
+
parser.add_argument('--analyze-scripts', type=bool, default=True, help='Analyze scripts')
|
|
320
|
+
parser.add_argument('--update-references', type=bool, default=True, help='Update references')
|
|
321
|
+
parser.add_argument('--dry-run', action='store_true', help='Preview without writing')
|
|
322
|
+
args = parser.parse_args()
|
|
323
|
+
|
|
324
|
+
skills_dir = Path(args.skills_dir).resolve()
|
|
325
|
+
skill_dir = skills_dir / args.skill
|
|
326
|
+
|
|
327
|
+
if not skill_dir.exists():
|
|
328
|
+
print(f"❌ Error: Skill not found: {skill_dir}", file=sys.stderr)
|
|
329
|
+
sys.exit(2)
|
|
330
|
+
|
|
331
|
+
print(f"📝 Updating documentation for: {args.skill}")
|
|
332
|
+
|
|
333
|
+
# Scan scripts
|
|
334
|
+
scripts = scan_skill_scripts(skill_dir) if args.analyze_scripts else []
|
|
335
|
+
print(f" Found {len(scripts)} script(s)")
|
|
336
|
+
|
|
337
|
+
# Scan references
|
|
338
|
+
refs = scan_skill_references(skill_dir) if args.update_references else []
|
|
339
|
+
print(f" Found {len(refs)} reference(s)")
|
|
340
|
+
|
|
341
|
+
# Update SKILL.md
|
|
342
|
+
success, message = update_skill_md(skill_dir, scripts, refs, args.dry_run)
|
|
343
|
+
|
|
344
|
+
if success:
|
|
345
|
+
print(f"✅ {message}")
|
|
346
|
+
else:
|
|
347
|
+
print(f"❌ {message}", file=sys.stderr)
|
|
348
|
+
sys.exit(4)
|
|
349
|
+
|
|
350
|
+
# Generate changelog if requested
|
|
351
|
+
if args.changelog and not args.dry_run:
|
|
352
|
+
changelog_entry = generate_changelog_entry(args.skill, scripts, refs)
|
|
353
|
+
print("\n📋 Changelog Entry:")
|
|
354
|
+
print(changelog_entry)
|
|
355
|
+
|
|
356
|
+
print("\n✅ Documentation update complete!")
|
|
357
|
+
|
|
358
|
+
# Remind to update catalog
|
|
359
|
+
print("\n💡 Remember to update the skills catalog:")
|
|
360
|
+
print(" python skill-creator/scripts/update_catalog.py --skills-dir skills/")
|
|
361
|
+
|
|
362
|
+
sys.exit(0)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
if __name__ == '__main__':
|
|
366
|
+
main()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pdf-reader
|
|
3
|
+
description: Extract text from PDF files for manipulation, search, and reference. Use when needing to read PDF content, extract text from documents, search within PDFs, or convert PDF to text for further processing. Supports multiple extraction methods (pdfplumber, PyMuPDF, pdfminer) with automatic fallback.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PDF Reader
|
|
7
|
+
|
|
8
|
+
Extract text from PDF files for text manipulation, search, and reference.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
Extract all text from a PDF:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python scripts/extract_text.py document.pdf
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Save to file:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
python scripts/extract_text.py document.pdf -o .tmp/output.txt
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Extract specific pages:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
python scripts/extract_text.py document.pdf -p 1-10 -o .tmp/pages.txt
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
1. **Extract text** → Run `scripts/extract_text.py`
|
|
33
|
+
2. **Process output** → Text is now searchable, editable, quotable
|
|
34
|
+
3. **Reference content** → Use extracted text for analysis or response
|
|
35
|
+
|
|
36
|
+
## Script Options
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
extract_text.py <pdf_path> [options]
|
|
40
|
+
|
|
41
|
+
Options:
|
|
42
|
+
-o, --output FILE Save to file (default: print to stdout)
|
|
43
|
+
-m, --method METHOD auto|pdfplumber|pymupdf|pdfminer (default: auto)
|
|
44
|
+
-p, --pages RANGE Page range: "1-5" or "1,3,5" (default: all)
|
|
45
|
+
--preserve-layout Keep spatial arrangement of text
|
|
46
|
+
--json Output with metadata (page sizes, method used)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Method Selection
|
|
50
|
+
|
|
51
|
+
| Scenario | Recommended Method |
|
|
52
|
+
| ------------------------ | ------------------- |
|
|
53
|
+
| General use | `auto` (default) |
|
|
54
|
+
| Documents with tables | `pdfplumber` |
|
|
55
|
+
| Large PDFs, speed needed | `pymupdf` |
|
|
56
|
+
| Maximum text accuracy | `pdfminer` |
|
|
57
|
+
| Scanned/image PDFs | `pymupdf` (has OCR) |
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Extract and search
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python scripts/extract_text.py report.pdf | grep -i "revenue"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Extract tables (use pdfplumber)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python scripts/extract_text.py data.pdf -m pdfplumber --json -o .tmp/data.json
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Specific pages with layout
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
python scripts/extract_text.py book.pdf -p 50-55 --preserve-layout -o .tmp/chapter.txt
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Dependencies
|
|
80
|
+
|
|
81
|
+
At least one library required:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install pdfplumber pymupdf pdfminer.six
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
For detailed library comparison, see [references/pdf_libraries.md](references/pdf_libraries.md).
|
|
88
|
+
|
|
89
|
+
## Troubleshooting
|
|
90
|
+
|
|
91
|
+
**Empty output?**
|
|
92
|
+
|
|
93
|
+
- PDF may be scanned/image-based → try `--method pymupdf` (has OCR)
|
|
94
|
+
- Check if PDF is password-protected
|
|
95
|
+
|
|
96
|
+
**Garbled text?**
|
|
97
|
+
|
|
98
|
+
- Try different method: `-m pdfminer`
|
|
99
|
+
- PDF may have non-standard font encoding
|
|
100
|
+
|
|
101
|
+
**Tables not formatted?**
|
|
102
|
+
|
|
103
|
+
- Use `-m pdfplumber --json` for structured output
|
|
104
|
+
- Consider `--preserve-layout` flag
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# PDF Library Reference
|
|
2
|
+
|
|
3
|
+
## Library Comparison
|
|
4
|
+
|
|
5
|
+
| Library | Speed | Tables | OCR | Layout | Install |
|
|
6
|
+
| ------------ | ---------- | -------- | ----------- | ------- | -------------------------- |
|
|
7
|
+
| pdfplumber | Medium | ✅ Best | ❌ | ✅ Good | `pip install pdfplumber` |
|
|
8
|
+
| PyMuPDF | ✅ Fastest | ⚠️ Basic | ✅ Built-in | ✅ Good | `pip install pymupdf` |
|
|
9
|
+
| pdfminer.six | Slow | ❌ | ❌ | ✅ Best | `pip install pdfminer.six` |
|
|
10
|
+
|
|
11
|
+
## When to Use Each
|
|
12
|
+
|
|
13
|
+
### pdfplumber (default)
|
|
14
|
+
|
|
15
|
+
Best for documents with tables, forms, or structured content.
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import pdfplumber
|
|
19
|
+
with pdfplumber.open("doc.pdf") as pdf:
|
|
20
|
+
for page in pdf.pages:
|
|
21
|
+
text = page.extract_text()
|
|
22
|
+
tables = page.extract_tables()
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### PyMuPDF (pymupdf)
|
|
26
|
+
|
|
27
|
+
Best for speed, large documents, or when OCR is needed.
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import fitz
|
|
31
|
+
doc = fitz.open("doc.pdf")
|
|
32
|
+
for page in doc:
|
|
33
|
+
text = page.get_text()
|
|
34
|
+
# OCR if needed (requires Tesseract)
|
|
35
|
+
# text = page.get_text("text", flags=fitz.TEXT_PRESERVE_WHITESPACE)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### pdfminer.six
|
|
39
|
+
|
|
40
|
+
Best for maximum text accuracy and complex layouts.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from pdfminer.high_level import extract_text
|
|
44
|
+
text = extract_text("doc.pdf")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Common Issues
|
|
48
|
+
|
|
49
|
+
### Scanned PDFs (image-based)
|
|
50
|
+
|
|
51
|
+
Use PyMuPDF with OCR:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python scripts/extract_text.py scanned.pdf --method pymupdf
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If text is empty, the PDF likely needs OCR processing.
|
|
58
|
+
|
|
59
|
+
### Tables Not Extracting
|
|
60
|
+
|
|
61
|
+
Use pdfplumber explicitly:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python scripts/extract_text.py table.pdf --method pdfplumber --json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Encoding Issues
|
|
68
|
+
|
|
69
|
+
Try different methods or check if PDF has embedded fonts.
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
Install all libraries for maximum compatibility:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install pdfplumber pymupdf pdfminer.six
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Minimal (one library):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install pdfplumber # Recommended default
|
|
83
|
+
```
|