Files
skill-seekers-reference/src/skill_seekers/cli/upload_skill.py
yusyus 0265de5816 style: Format all Python files with ruff
- Formatted 103 files to comply with ruff format requirements
- No code logic changes, only formatting/whitespace
- Fixes CI formatting check failures
2026-02-08 14:42:27 +03:00

252 lines
7.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Automatic Skill Uploader
Uploads a skill package to LLM platforms (Claude, Gemini, OpenAI, etc.)
Usage:
# Claude (default)
export ANTHROPIC_API_KEY=sk-ant-...
skill-seekers upload output/react.zip
# Gemini
export GOOGLE_API_KEY=AIzaSy...
skill-seekers upload output/react-gemini.tar.gz --target gemini
# OpenAI
export OPENAI_API_KEY=sk-proj-...
skill-seekers upload output/react-openai.zip --target openai
"""
import argparse
import os
import sys
from pathlib import Path
# Import utilities
try:
from utils import print_upload_instructions
except ImportError:
sys.path.insert(0, str(Path(__file__).parent))
from utils import print_upload_instructions
def upload_skill_api(package_path, target="claude", api_key=None, **kwargs):
"""
Upload skill package to LLM platform
Args:
package_path: Path to skill package file
target: Target platform ('claude', 'gemini', 'openai', 'chroma', 'weaviate')
api_key: Optional API key (otherwise read from environment)
**kwargs: Platform-specific upload options
Returns:
tuple: (success, message)
"""
try:
from skill_seekers.cli.adaptors import get_adaptor
except ImportError:
return False, "Adaptor system not available. Reinstall skill-seekers."
# Get platform-specific adaptor
try:
adaptor = get_adaptor(target)
except ValueError as e:
return False, str(e)
# Get API key
if not api_key:
api_key = os.environ.get(adaptor.get_env_var_name(), "").strip()
# API key validation only for platforms that require it
if target in ["claude", "gemini", "openai"]:
if not api_key:
return False, f"{adaptor.get_env_var_name()} not set. Export your API key first."
# Validate API key format
if not adaptor.validate_api_key(api_key):
return False, f"Invalid API key format for {adaptor.PLATFORM_NAME}"
package_path = Path(package_path)
# Basic file validation
if not package_path.exists():
return False, f"File not found: {package_path}"
skill_name = package_path.stem
print(f"📤 Uploading skill: {skill_name}")
print(f" Target: {adaptor.PLATFORM_NAME}")
print(f" Source: {package_path}")
print(f" Size: {package_path.stat().st_size:,} bytes")
print()
# Upload using adaptor
print(f"⏳ Uploading to {adaptor.PLATFORM_NAME}...")
try:
result = adaptor.upload(package_path, api_key, **kwargs)
if result["success"]:
print()
print(f"{result['message']}")
print()
if result.get("url"):
print("Your skill is now available at:")
print(f" {result['url']}")
if result.get("skill_id"):
print(f" Skill ID: {result['skill_id']}")
if result.get("collection"):
print(f" Collection: {result['collection']}")
if result.get("class_name"):
print(f" Class: {result['class_name']}")
if result.get("count"):
print(f" Documents uploaded: {result['count']}")
print()
return True, "Upload successful"
else:
return False, result["message"]
except Exception as e:
return False, f"Unexpected error: {str(e)}"
def main():
parser = argparse.ArgumentParser(
description="Upload a skill package to LLM platforms and vector databases",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Setup:
Claude:
export ANTHROPIC_API_KEY=sk-ant-...
Gemini:
export GOOGLE_API_KEY=AIzaSy...
OpenAI:
export OPENAI_API_KEY=sk-proj-...
ChromaDB (local):
# No API key needed for local instance
chroma run # Start server
Weaviate (local):
# No API key needed for local instance
docker run -p 8080:8080 semitechnologies/weaviate:latest
Examples:
# Upload to Claude (default)
skill-seekers upload output/react.zip
# Upload to Gemini
skill-seekers upload output/react-gemini.tar.gz --target gemini
# Upload to OpenAI
skill-seekers upload output/react-openai.zip --target openai
# Upload to ChromaDB (local)
skill-seekers upload output/react-chroma.json --target chroma
# Upload to ChromaDB with OpenAI embeddings
skill-seekers upload output/react-chroma.json --target chroma --embedding-function openai
# Upload to Weaviate (local)
skill-seekers upload output/react-weaviate.json --target weaviate
# Upload to Weaviate Cloud
skill-seekers upload output/react-weaviate.json --target weaviate --use-cloud --cluster-url https://xxx.weaviate.network --api-key YOUR_KEY
""",
)
parser.add_argument("package_file", help="Path to skill package file (e.g., output/react.zip)")
parser.add_argument(
"--target",
choices=["claude", "gemini", "openai", "chroma", "weaviate"],
default="claude",
help="Target platform (default: claude)",
)
parser.add_argument("--api-key", help="Platform API key (or set environment variable)")
# ChromaDB upload options
parser.add_argument(
"--chroma-url",
help="ChromaDB URL (default: http://localhost:8000 for HTTP, or use --persist-directory for local)",
)
parser.add_argument(
"--persist-directory",
help="Local directory for persistent ChromaDB storage (default: ./chroma_db)",
)
parser.add_argument(
"--embedding-function",
choices=["openai", "sentence-transformers", "none"],
help="Embedding function for ChromaDB/Weaviate (default: platform default)",
)
parser.add_argument(
"--openai-api-key", help="OpenAI API key for embeddings (or set OPENAI_API_KEY env var)"
)
# Weaviate upload options
parser.add_argument(
"--weaviate-url",
default="http://localhost:8080",
help="Weaviate URL (default: http://localhost:8080)",
)
parser.add_argument(
"--use-cloud",
action="store_true",
help="Use Weaviate Cloud (requires --api-key and --cluster-url)",
)
parser.add_argument(
"--cluster-url", help="Weaviate Cloud cluster URL (e.g., https://xxx.weaviate.network)"
)
args = parser.parse_args()
# Build kwargs for vector DB upload
upload_kwargs = {}
if args.target == "chroma":
if args.chroma_url:
upload_kwargs["chroma_url"] = args.chroma_url
if args.persist_directory:
upload_kwargs["persist_directory"] = args.persist_directory
if args.embedding_function:
upload_kwargs["embedding_function"] = args.embedding_function
if args.openai_api_key:
upload_kwargs["openai_api_key"] = args.openai_api_key
elif args.target == "weaviate":
upload_kwargs["weaviate_url"] = args.weaviate_url
upload_kwargs["use_cloud"] = args.use_cloud
if args.cluster_url:
upload_kwargs["cluster_url"] = args.cluster_url
if args.embedding_function:
upload_kwargs["embedding_function"] = args.embedding_function
if args.openai_api_key:
upload_kwargs["openai_api_key"] = args.openai_api_key
# Upload skill
success, message = upload_skill_api(
args.package_file, args.target, args.api_key, **upload_kwargs
)
if success:
sys.exit(0)
else:
print(f"\n❌ Upload failed: {message}")
print()
print("📝 Manual upload instructions:")
print_upload_instructions(args.package_file)
sys.exit(1)
if __name__ == "__main__":
main()