skill-seekers 2.7.3__py3-none-any.whl
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.
- skill_seekers/__init__.py +22 -0
- skill_seekers/cli/__init__.py +39 -0
- skill_seekers/cli/adaptors/__init__.py +120 -0
- skill_seekers/cli/adaptors/base.py +221 -0
- skill_seekers/cli/adaptors/claude.py +485 -0
- skill_seekers/cli/adaptors/gemini.py +453 -0
- skill_seekers/cli/adaptors/markdown.py +269 -0
- skill_seekers/cli/adaptors/openai.py +503 -0
- skill_seekers/cli/ai_enhancer.py +310 -0
- skill_seekers/cli/api_reference_builder.py +373 -0
- skill_seekers/cli/architectural_pattern_detector.py +525 -0
- skill_seekers/cli/code_analyzer.py +1462 -0
- skill_seekers/cli/codebase_scraper.py +1225 -0
- skill_seekers/cli/config_command.py +563 -0
- skill_seekers/cli/config_enhancer.py +431 -0
- skill_seekers/cli/config_extractor.py +871 -0
- skill_seekers/cli/config_manager.py +452 -0
- skill_seekers/cli/config_validator.py +394 -0
- skill_seekers/cli/conflict_detector.py +528 -0
- skill_seekers/cli/constants.py +72 -0
- skill_seekers/cli/dependency_analyzer.py +757 -0
- skill_seekers/cli/doc_scraper.py +2332 -0
- skill_seekers/cli/enhance_skill.py +488 -0
- skill_seekers/cli/enhance_skill_local.py +1096 -0
- skill_seekers/cli/enhance_status.py +194 -0
- skill_seekers/cli/estimate_pages.py +433 -0
- skill_seekers/cli/generate_router.py +1209 -0
- skill_seekers/cli/github_fetcher.py +534 -0
- skill_seekers/cli/github_scraper.py +1466 -0
- skill_seekers/cli/guide_enhancer.py +723 -0
- skill_seekers/cli/how_to_guide_builder.py +1267 -0
- skill_seekers/cli/install_agent.py +461 -0
- skill_seekers/cli/install_skill.py +178 -0
- skill_seekers/cli/language_detector.py +614 -0
- skill_seekers/cli/llms_txt_detector.py +60 -0
- skill_seekers/cli/llms_txt_downloader.py +104 -0
- skill_seekers/cli/llms_txt_parser.py +150 -0
- skill_seekers/cli/main.py +558 -0
- skill_seekers/cli/markdown_cleaner.py +132 -0
- skill_seekers/cli/merge_sources.py +806 -0
- skill_seekers/cli/package_multi.py +77 -0
- skill_seekers/cli/package_skill.py +241 -0
- skill_seekers/cli/pattern_recognizer.py +1825 -0
- skill_seekers/cli/pdf_extractor_poc.py +1166 -0
- skill_seekers/cli/pdf_scraper.py +617 -0
- skill_seekers/cli/quality_checker.py +519 -0
- skill_seekers/cli/rate_limit_handler.py +438 -0
- skill_seekers/cli/resume_command.py +160 -0
- skill_seekers/cli/run_tests.py +230 -0
- skill_seekers/cli/setup_wizard.py +93 -0
- skill_seekers/cli/split_config.py +390 -0
- skill_seekers/cli/swift_patterns.py +560 -0
- skill_seekers/cli/test_example_extractor.py +1081 -0
- skill_seekers/cli/test_unified_simple.py +179 -0
- skill_seekers/cli/unified_codebase_analyzer.py +572 -0
- skill_seekers/cli/unified_scraper.py +932 -0
- skill_seekers/cli/unified_skill_builder.py +1605 -0
- skill_seekers/cli/upload_skill.py +162 -0
- skill_seekers/cli/utils.py +432 -0
- skill_seekers/mcp/__init__.py +33 -0
- skill_seekers/mcp/agent_detector.py +316 -0
- skill_seekers/mcp/git_repo.py +273 -0
- skill_seekers/mcp/server.py +231 -0
- skill_seekers/mcp/server_fastmcp.py +1249 -0
- skill_seekers/mcp/server_legacy.py +2302 -0
- skill_seekers/mcp/source_manager.py +285 -0
- skill_seekers/mcp/tools/__init__.py +115 -0
- skill_seekers/mcp/tools/config_tools.py +251 -0
- skill_seekers/mcp/tools/packaging_tools.py +826 -0
- skill_seekers/mcp/tools/scraping_tools.py +842 -0
- skill_seekers/mcp/tools/source_tools.py +828 -0
- skill_seekers/mcp/tools/splitting_tools.py +212 -0
- skill_seekers/py.typed +0 -0
- skill_seekers-2.7.3.dist-info/METADATA +2027 -0
- skill_seekers-2.7.3.dist-info/RECORD +79 -0
- skill_seekers-2.7.3.dist-info/WHEEL +5 -0
- skill_seekers-2.7.3.dist-info/entry_points.txt +19 -0
- skill_seekers-2.7.3.dist-info/licenses/LICENSE +21 -0
- skill_seekers-2.7.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
OpenAI ChatGPT Adaptor
|
|
4
|
+
|
|
5
|
+
Implements platform-specific handling for OpenAI ChatGPT Assistants.
|
|
6
|
+
Uses Assistants API with Vector Store for file search.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import zipfile
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from .base import SkillAdaptor, SkillMetadata
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class OpenAIAdaptor(SkillAdaptor):
|
|
18
|
+
"""
|
|
19
|
+
OpenAI ChatGPT platform adaptor.
|
|
20
|
+
|
|
21
|
+
Handles:
|
|
22
|
+
- Assistant instructions format (not YAML frontmatter)
|
|
23
|
+
- ZIP packaging for Assistants API
|
|
24
|
+
- Upload creates Assistant + Vector Store
|
|
25
|
+
- AI enhancement using GPT-4o
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
PLATFORM = "openai"
|
|
29
|
+
PLATFORM_NAME = "OpenAI ChatGPT"
|
|
30
|
+
DEFAULT_API_ENDPOINT = "https://api.openai.com/v1/assistants"
|
|
31
|
+
|
|
32
|
+
def format_skill_md(self, skill_dir: Path, metadata: SkillMetadata) -> str:
|
|
33
|
+
"""
|
|
34
|
+
Format SKILL.md as Assistant instructions.
|
|
35
|
+
|
|
36
|
+
OpenAI Assistants use instructions rather than markdown docs.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
skill_dir: Path to skill directory
|
|
40
|
+
metadata: Skill metadata
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Formatted instructions for OpenAI Assistant
|
|
44
|
+
"""
|
|
45
|
+
# Read existing content (if any)
|
|
46
|
+
existing_content = self._read_existing_content(skill_dir)
|
|
47
|
+
|
|
48
|
+
# If existing content is substantial, adapt it to instructions format
|
|
49
|
+
if existing_content and len(existing_content) > 100:
|
|
50
|
+
content_body = f"""You are an expert assistant for {metadata.name}.
|
|
51
|
+
|
|
52
|
+
{metadata.description}
|
|
53
|
+
|
|
54
|
+
Use the attached knowledge files to provide accurate, detailed answers about {metadata.name}.
|
|
55
|
+
|
|
56
|
+
{existing_content}
|
|
57
|
+
|
|
58
|
+
## How to Assist Users
|
|
59
|
+
|
|
60
|
+
When users ask questions:
|
|
61
|
+
1. Search the knowledge files for relevant information
|
|
62
|
+
2. Provide clear, practical answers with code examples
|
|
63
|
+
3. Reference specific documentation sections when helpful
|
|
64
|
+
4. Be concise but thorough
|
|
65
|
+
|
|
66
|
+
Always prioritize accuracy by consulting the knowledge base before responding."""
|
|
67
|
+
else:
|
|
68
|
+
# Generate default instructions
|
|
69
|
+
content_body = f"""You are an expert assistant for {metadata.name}.
|
|
70
|
+
|
|
71
|
+
{metadata.description}
|
|
72
|
+
|
|
73
|
+
## Your Knowledge Base
|
|
74
|
+
|
|
75
|
+
You have access to comprehensive documentation files about {metadata.name}. Use these files to provide accurate answers to user questions.
|
|
76
|
+
|
|
77
|
+
{self._generate_toc(skill_dir)}
|
|
78
|
+
|
|
79
|
+
## Quick Reference
|
|
80
|
+
|
|
81
|
+
{self._extract_quick_reference(skill_dir)}
|
|
82
|
+
|
|
83
|
+
## How to Assist Users
|
|
84
|
+
|
|
85
|
+
When users ask questions about {metadata.name}:
|
|
86
|
+
|
|
87
|
+
1. **Search the knowledge files** - Use file_search to find relevant information
|
|
88
|
+
2. **Provide code examples** - Include practical, working code snippets
|
|
89
|
+
3. **Reference documentation** - Cite specific sections when helpful
|
|
90
|
+
4. **Be practical** - Focus on real-world usage and best practices
|
|
91
|
+
5. **Stay accurate** - Always verify information against the knowledge base
|
|
92
|
+
|
|
93
|
+
## Response Guidelines
|
|
94
|
+
|
|
95
|
+
- Keep answers clear and concise
|
|
96
|
+
- Use proper code formatting with language tags
|
|
97
|
+
- Provide both simple and detailed explanations as needed
|
|
98
|
+
- Suggest related topics when relevant
|
|
99
|
+
- Admit when information isn't in the knowledge base
|
|
100
|
+
|
|
101
|
+
Always prioritize accuracy by consulting the attached documentation files before responding."""
|
|
102
|
+
|
|
103
|
+
# Return plain text instructions (NO frontmatter)
|
|
104
|
+
return content_body
|
|
105
|
+
|
|
106
|
+
def package(self, skill_dir: Path, output_path: Path) -> Path:
|
|
107
|
+
"""
|
|
108
|
+
Package skill into ZIP file for OpenAI Assistants.
|
|
109
|
+
|
|
110
|
+
Creates OpenAI-compatible structure:
|
|
111
|
+
- assistant_instructions.txt (main instructions)
|
|
112
|
+
- vector_store_files/*.md (reference files for vector store)
|
|
113
|
+
- openai_metadata.json (skill metadata)
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
skill_dir: Path to skill directory
|
|
117
|
+
output_path: Output path/filename for ZIP
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Path to created ZIP file
|
|
121
|
+
"""
|
|
122
|
+
skill_dir = Path(skill_dir)
|
|
123
|
+
|
|
124
|
+
# Determine output filename
|
|
125
|
+
if output_path.is_dir() or str(output_path).endswith("/"):
|
|
126
|
+
output_path = Path(output_path) / f"{skill_dir.name}-openai.zip"
|
|
127
|
+
elif not str(output_path).endswith(".zip") and not str(output_path).endswith("-openai.zip"):
|
|
128
|
+
# Keep .zip extension
|
|
129
|
+
output_str = str(output_path).replace(".zip", "-openai.zip")
|
|
130
|
+
if not output_str.endswith(".zip"):
|
|
131
|
+
output_str += ".zip"
|
|
132
|
+
output_path = Path(output_str)
|
|
133
|
+
|
|
134
|
+
output_path = Path(output_path)
|
|
135
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
136
|
+
|
|
137
|
+
# Create ZIP file
|
|
138
|
+
with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:
|
|
139
|
+
# Add SKILL.md as assistant_instructions.txt
|
|
140
|
+
skill_md = skill_dir / "SKILL.md"
|
|
141
|
+
if skill_md.exists():
|
|
142
|
+
instructions = skill_md.read_text(encoding="utf-8")
|
|
143
|
+
zf.writestr("assistant_instructions.txt", instructions)
|
|
144
|
+
|
|
145
|
+
# Add references directory as vector_store_files/
|
|
146
|
+
refs_dir = skill_dir / "references"
|
|
147
|
+
if refs_dir.exists():
|
|
148
|
+
for ref_file in refs_dir.rglob("*.md"):
|
|
149
|
+
if ref_file.is_file() and not ref_file.name.startswith("."):
|
|
150
|
+
# Place all reference files in vector_store_files/
|
|
151
|
+
arcname = f"vector_store_files/{ref_file.name}"
|
|
152
|
+
zf.write(ref_file, arcname)
|
|
153
|
+
|
|
154
|
+
# Create and add metadata file
|
|
155
|
+
metadata = {
|
|
156
|
+
"platform": "openai",
|
|
157
|
+
"name": skill_dir.name,
|
|
158
|
+
"version": "1.0.0",
|
|
159
|
+
"created_with": "skill-seekers",
|
|
160
|
+
"model": "gpt-4o",
|
|
161
|
+
"tools": ["file_search"],
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
zf.writestr("openai_metadata.json", json.dumps(metadata, indent=2))
|
|
165
|
+
|
|
166
|
+
return output_path
|
|
167
|
+
|
|
168
|
+
def upload(self, package_path: Path, api_key: str, **kwargs) -> dict[str, Any]:
|
|
169
|
+
"""
|
|
170
|
+
Upload skill ZIP to OpenAI Assistants API.
|
|
171
|
+
|
|
172
|
+
Creates:
|
|
173
|
+
1. Vector Store with reference files
|
|
174
|
+
2. Assistant with file_search tool
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
package_path: Path to skill ZIP file
|
|
178
|
+
api_key: OpenAI API key
|
|
179
|
+
**kwargs: Additional arguments (model, etc.)
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Dictionary with upload result
|
|
183
|
+
"""
|
|
184
|
+
# Validate package file FIRST
|
|
185
|
+
package_path = Path(package_path)
|
|
186
|
+
if not package_path.exists():
|
|
187
|
+
return {
|
|
188
|
+
"success": False,
|
|
189
|
+
"skill_id": None,
|
|
190
|
+
"url": None,
|
|
191
|
+
"message": f"File not found: {package_path}",
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if package_path.suffix != ".zip":
|
|
195
|
+
return {
|
|
196
|
+
"success": False,
|
|
197
|
+
"skill_id": None,
|
|
198
|
+
"url": None,
|
|
199
|
+
"message": f"Not a ZIP file: {package_path}",
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
# Check for openai library
|
|
203
|
+
try:
|
|
204
|
+
from openai import OpenAI
|
|
205
|
+
except ImportError:
|
|
206
|
+
return {
|
|
207
|
+
"success": False,
|
|
208
|
+
"skill_id": None,
|
|
209
|
+
"url": None,
|
|
210
|
+
"message": "openai library not installed. Run: pip install openai",
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
# Configure OpenAI client
|
|
214
|
+
try:
|
|
215
|
+
client = OpenAI(api_key=api_key)
|
|
216
|
+
|
|
217
|
+
# Extract package to temp directory
|
|
218
|
+
import tempfile
|
|
219
|
+
|
|
220
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
221
|
+
# Extract ZIP
|
|
222
|
+
with zipfile.ZipFile(package_path, "r") as zf:
|
|
223
|
+
zf.extractall(temp_dir)
|
|
224
|
+
|
|
225
|
+
temp_path = Path(temp_dir)
|
|
226
|
+
|
|
227
|
+
# Read instructions
|
|
228
|
+
instructions_file = temp_path / "assistant_instructions.txt"
|
|
229
|
+
if not instructions_file.exists():
|
|
230
|
+
return {
|
|
231
|
+
"success": False,
|
|
232
|
+
"skill_id": None,
|
|
233
|
+
"url": None,
|
|
234
|
+
"message": "Invalid package: assistant_instructions.txt not found",
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
instructions = instructions_file.read_text(encoding="utf-8")
|
|
238
|
+
|
|
239
|
+
# Read metadata
|
|
240
|
+
metadata_file = temp_path / "openai_metadata.json"
|
|
241
|
+
skill_name = package_path.stem
|
|
242
|
+
model = kwargs.get("model", "gpt-4o")
|
|
243
|
+
|
|
244
|
+
if metadata_file.exists():
|
|
245
|
+
with open(metadata_file) as f:
|
|
246
|
+
metadata = json.load(f)
|
|
247
|
+
skill_name = metadata.get("name", skill_name)
|
|
248
|
+
model = metadata.get("model", model)
|
|
249
|
+
|
|
250
|
+
# Create vector store
|
|
251
|
+
vector_store = client.beta.vector_stores.create(name=f"{skill_name} Documentation")
|
|
252
|
+
|
|
253
|
+
# Upload reference files to vector store
|
|
254
|
+
vector_files_dir = temp_path / "vector_store_files"
|
|
255
|
+
file_ids = []
|
|
256
|
+
|
|
257
|
+
if vector_files_dir.exists():
|
|
258
|
+
for ref_file in vector_files_dir.glob("*.md"):
|
|
259
|
+
# Upload file
|
|
260
|
+
with open(ref_file, "rb") as f:
|
|
261
|
+
uploaded_file = client.files.create(file=f, purpose="assistants")
|
|
262
|
+
file_ids.append(uploaded_file.id)
|
|
263
|
+
|
|
264
|
+
# Attach files to vector store
|
|
265
|
+
if file_ids:
|
|
266
|
+
client.beta.vector_stores.files.create_batch(
|
|
267
|
+
vector_store_id=vector_store.id, file_ids=file_ids
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Create assistant
|
|
271
|
+
assistant = client.beta.assistants.create(
|
|
272
|
+
name=skill_name,
|
|
273
|
+
instructions=instructions,
|
|
274
|
+
model=model,
|
|
275
|
+
tools=[{"type": "file_search"}],
|
|
276
|
+
tool_resources={"file_search": {"vector_store_ids": [vector_store.id]}},
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
"success": True,
|
|
281
|
+
"skill_id": assistant.id,
|
|
282
|
+
"url": f"https://platform.openai.com/assistants/{assistant.id}",
|
|
283
|
+
"message": f"Assistant created with {len(file_ids)} knowledge files",
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
except Exception as e:
|
|
287
|
+
return {
|
|
288
|
+
"success": False,
|
|
289
|
+
"skill_id": None,
|
|
290
|
+
"url": None,
|
|
291
|
+
"message": f"Upload failed: {str(e)}",
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
def validate_api_key(self, api_key: str) -> bool:
|
|
295
|
+
"""
|
|
296
|
+
Validate OpenAI API key format.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
api_key: API key to validate
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
True if key starts with 'sk-'
|
|
303
|
+
"""
|
|
304
|
+
return api_key.strip().startswith("sk-")
|
|
305
|
+
|
|
306
|
+
def get_env_var_name(self) -> str:
|
|
307
|
+
"""
|
|
308
|
+
Get environment variable name for OpenAI API key.
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
'OPENAI_API_KEY'
|
|
312
|
+
"""
|
|
313
|
+
return "OPENAI_API_KEY"
|
|
314
|
+
|
|
315
|
+
def supports_enhancement(self) -> bool:
|
|
316
|
+
"""
|
|
317
|
+
OpenAI supports AI enhancement via GPT-4o.
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
True
|
|
321
|
+
"""
|
|
322
|
+
return True
|
|
323
|
+
|
|
324
|
+
def enhance(self, skill_dir: Path, api_key: str) -> bool:
|
|
325
|
+
"""
|
|
326
|
+
Enhance SKILL.md using GPT-4o API.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
skill_dir: Path to skill directory
|
|
330
|
+
api_key: OpenAI API key
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
True if enhancement succeeded
|
|
334
|
+
"""
|
|
335
|
+
# Check for openai library
|
|
336
|
+
try:
|
|
337
|
+
from openai import OpenAI
|
|
338
|
+
except ImportError:
|
|
339
|
+
print("ā Error: openai package not installed")
|
|
340
|
+
print("Install with: pip install openai")
|
|
341
|
+
return False
|
|
342
|
+
|
|
343
|
+
skill_dir = Path(skill_dir)
|
|
344
|
+
references_dir = skill_dir / "references"
|
|
345
|
+
skill_md_path = skill_dir / "SKILL.md"
|
|
346
|
+
|
|
347
|
+
# Read reference files
|
|
348
|
+
print("š Reading reference documentation...")
|
|
349
|
+
references = self._read_reference_files(references_dir)
|
|
350
|
+
|
|
351
|
+
if not references:
|
|
352
|
+
print("ā No reference files found to analyze")
|
|
353
|
+
return False
|
|
354
|
+
|
|
355
|
+
print(f" ā Read {len(references)} reference files")
|
|
356
|
+
total_size = sum(len(c) for c in references.values())
|
|
357
|
+
print(f" ā Total size: {total_size:,} characters\n")
|
|
358
|
+
|
|
359
|
+
# Read current SKILL.md
|
|
360
|
+
current_skill_md = None
|
|
361
|
+
if skill_md_path.exists():
|
|
362
|
+
current_skill_md = skill_md_path.read_text(encoding="utf-8")
|
|
363
|
+
print(f" ā¹ Found existing SKILL.md ({len(current_skill_md)} chars)")
|
|
364
|
+
else:
|
|
365
|
+
print(" ā¹ No existing SKILL.md, will create new one")
|
|
366
|
+
|
|
367
|
+
# Build enhancement prompt
|
|
368
|
+
prompt = self._build_enhancement_prompt(skill_dir.name, references, current_skill_md)
|
|
369
|
+
|
|
370
|
+
print("\nš¤ Asking GPT-4o to enhance SKILL.md...")
|
|
371
|
+
print(f" Input: {len(prompt):,} characters")
|
|
372
|
+
|
|
373
|
+
try:
|
|
374
|
+
client = OpenAI(api_key=api_key)
|
|
375
|
+
|
|
376
|
+
response = client.chat.completions.create(
|
|
377
|
+
model="gpt-4o",
|
|
378
|
+
messages=[
|
|
379
|
+
{
|
|
380
|
+
"role": "system",
|
|
381
|
+
"content": "You are an expert technical writer creating Assistant instructions for OpenAI ChatGPT.",
|
|
382
|
+
},
|
|
383
|
+
{"role": "user", "content": prompt},
|
|
384
|
+
],
|
|
385
|
+
temperature=0.3,
|
|
386
|
+
max_tokens=4096,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
enhanced_content = response.choices[0].message.content
|
|
390
|
+
print(f" ā Generated enhanced SKILL.md ({len(enhanced_content)} chars)\n")
|
|
391
|
+
|
|
392
|
+
# Backup original
|
|
393
|
+
if skill_md_path.exists():
|
|
394
|
+
backup_path = skill_md_path.with_suffix(".md.backup")
|
|
395
|
+
skill_md_path.rename(backup_path)
|
|
396
|
+
print(f" š¾ Backed up original to: {backup_path.name}")
|
|
397
|
+
|
|
398
|
+
# Save enhanced version
|
|
399
|
+
skill_md_path.write_text(enhanced_content, encoding="utf-8")
|
|
400
|
+
print(" ā
Saved enhanced SKILL.md")
|
|
401
|
+
|
|
402
|
+
return True
|
|
403
|
+
|
|
404
|
+
except Exception as e:
|
|
405
|
+
print(f"ā Error calling OpenAI API: {e}")
|
|
406
|
+
return False
|
|
407
|
+
|
|
408
|
+
def _read_reference_files(
|
|
409
|
+
self, references_dir: Path, max_chars: int = 200000
|
|
410
|
+
) -> dict[str, str]:
|
|
411
|
+
"""
|
|
412
|
+
Read reference markdown files from skill directory.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
references_dir: Path to references directory
|
|
416
|
+
max_chars: Maximum total characters to read
|
|
417
|
+
|
|
418
|
+
Returns:
|
|
419
|
+
Dictionary mapping filename to content
|
|
420
|
+
"""
|
|
421
|
+
if not references_dir.exists():
|
|
422
|
+
return {}
|
|
423
|
+
|
|
424
|
+
references = {}
|
|
425
|
+
total_chars = 0
|
|
426
|
+
|
|
427
|
+
# Read all .md files
|
|
428
|
+
for ref_file in sorted(references_dir.glob("*.md")):
|
|
429
|
+
if total_chars >= max_chars:
|
|
430
|
+
break
|
|
431
|
+
|
|
432
|
+
try:
|
|
433
|
+
content = ref_file.read_text(encoding="utf-8")
|
|
434
|
+
# Limit individual file size
|
|
435
|
+
if len(content) > 30000:
|
|
436
|
+
content = content[:30000] + "\n\n...(truncated)"
|
|
437
|
+
|
|
438
|
+
references[ref_file.name] = content
|
|
439
|
+
total_chars += len(content)
|
|
440
|
+
|
|
441
|
+
except Exception as e:
|
|
442
|
+
print(f" ā ļø Could not read {ref_file.name}: {e}")
|
|
443
|
+
|
|
444
|
+
return references
|
|
445
|
+
|
|
446
|
+
def _build_enhancement_prompt(
|
|
447
|
+
self, skill_name: str, references: dict[str, str], current_skill_md: str = None
|
|
448
|
+
) -> str:
|
|
449
|
+
"""
|
|
450
|
+
Build OpenAI API prompt for enhancement.
|
|
451
|
+
|
|
452
|
+
Args:
|
|
453
|
+
skill_name: Name of the skill
|
|
454
|
+
references: Dictionary of reference content
|
|
455
|
+
current_skill_md: Existing SKILL.md content (optional)
|
|
456
|
+
|
|
457
|
+
Returns:
|
|
458
|
+
Enhancement prompt for GPT-4o
|
|
459
|
+
"""
|
|
460
|
+
prompt = f"""You are creating Assistant instructions for an OpenAI ChatGPT Assistant about: {skill_name}
|
|
461
|
+
|
|
462
|
+
I've scraped documentation and organized it into reference files. Your job is to create EXCELLENT Assistant instructions that will help the Assistant use this documentation effectively.
|
|
463
|
+
|
|
464
|
+
CURRENT INSTRUCTIONS:
|
|
465
|
+
{"```" if current_skill_md else "(none - create from scratch)"}
|
|
466
|
+
{current_skill_md or "No existing instructions"}
|
|
467
|
+
{"```" if current_skill_md else ""}
|
|
468
|
+
|
|
469
|
+
REFERENCE DOCUMENTATION:
|
|
470
|
+
"""
|
|
471
|
+
|
|
472
|
+
for filename, content in references.items():
|
|
473
|
+
prompt += f"\n\n## {filename}\n```markdown\n{content[:30000]}\n```\n"
|
|
474
|
+
|
|
475
|
+
prompt += """
|
|
476
|
+
|
|
477
|
+
YOUR TASK:
|
|
478
|
+
Create enhanced Assistant instructions that include:
|
|
479
|
+
|
|
480
|
+
1. **Clear role definition** - "You are an expert assistant for [topic]"
|
|
481
|
+
2. **Knowledge base description** - What documentation is attached
|
|
482
|
+
3. **Excellent Quick Reference** - Extract 5-10 of the BEST, most practical code examples from the reference docs
|
|
483
|
+
- Choose SHORT, clear examples that demonstrate common tasks
|
|
484
|
+
- Include both simple and intermediate examples
|
|
485
|
+
- Annotate examples with clear descriptions
|
|
486
|
+
- Use proper language tags (cpp, python, javascript, json, etc.)
|
|
487
|
+
4. **Response guidelines** - How the Assistant should help users
|
|
488
|
+
5. **Search strategy** - When to use file_search, how to find information
|
|
489
|
+
6. **DO NOT use YAML frontmatter** - This is plain text instructions for OpenAI
|
|
490
|
+
|
|
491
|
+
IMPORTANT:
|
|
492
|
+
- Extract REAL examples from the reference docs, don't make them up
|
|
493
|
+
- Prioritize SHORT, clear examples (5-20 lines max)
|
|
494
|
+
- Make it actionable and practical for the Assistant
|
|
495
|
+
- Write clear, direct instructions
|
|
496
|
+
- Focus on how the Assistant should behave and respond
|
|
497
|
+
- NO YAML frontmatter (no --- blocks)
|
|
498
|
+
|
|
499
|
+
OUTPUT:
|
|
500
|
+
Return ONLY the complete Assistant instructions as plain text.
|
|
501
|
+
"""
|
|
502
|
+
|
|
503
|
+
return prompt
|