Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """Upload a skill to the OpenSpace cloud platform. | |
| Usage: | |
| openspace-upload-skill --skill-dir ./my-skill --visibility public --origin imported | |
| openspace-upload-skill --skill-dir ./my-skill --visibility private --origin fixed --parent-ids "parent_id" | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| import sys | |
| from pathlib import Path | |
| from openspace.cloud.auth import get_api_base, get_auth_headers_or_exit | |
| from openspace.cloud.client import OpenSpaceClient, CloudError | |
| def main() -> None: | |
| parser = argparse.ArgumentParser( | |
| prog="openspace-upload-skill", | |
| description="Upload a skill to OpenSpace's cloud community", | |
| ) | |
| parser.add_argument("--skill-dir", required=True, help="Path to skill directory (must contain SKILL.md)") | |
| parser.add_argument("--visibility", required=True, choices=["public", "private"]) | |
| parser.add_argument("--origin", default="imported", choices=["imported", "captured", "derived", "fixed"]) | |
| parser.add_argument("--parent-ids", default="", help="Comma-separated parent skill IDs") | |
| parser.add_argument("--tags", default="", help="Comma-separated tags") | |
| parser.add_argument("--created-by", default="", help="Creator display name") | |
| parser.add_argument("--change-summary", default="", help="Change summary text") | |
| parser.add_argument("--api-base", default=None, help="Override API base URL") | |
| parser.add_argument("--dry-run", action="store_true", help="List files without uploading") | |
| args = parser.parse_args() | |
| skill_dir = Path(args.skill_dir).resolve() | |
| if not skill_dir.is_dir(): | |
| print(f"ERROR: Not a directory: {skill_dir}", file=sys.stderr) | |
| sys.exit(1) | |
| api_base = get_api_base(args.api_base) | |
| if args.dry_run: | |
| files = OpenSpaceClient._collect_files(skill_dir) | |
| print(f"Dry run — would upload {len(files)} file(s):", file=sys.stderr) | |
| for f in files: | |
| print(f" {f.relative_to(skill_dir)}", file=sys.stderr) | |
| sys.exit(0) | |
| headers = get_auth_headers_or_exit() | |
| parent_ids = [p.strip() for p in args.parent_ids.split(",") if p.strip()] | |
| tags = [t.strip() for t in args.tags.split(",") if t.strip()] | |
| print(f"\n{'='*60}", file=sys.stderr) | |
| print(f"Upload Skill: {skill_dir.name}", file=sys.stderr) | |
| print(f" Visibility: {args.visibility}", file=sys.stderr) | |
| print(f" Origin: {args.origin}", file=sys.stderr) | |
| print(f" API Base: {api_base}", file=sys.stderr) | |
| print(f"{'='*60}\n", file=sys.stderr) | |
| try: | |
| client = OpenSpaceClient(headers, api_base) | |
| result = client.upload_skill( | |
| skill_dir, | |
| visibility=args.visibility, | |
| origin=args.origin, | |
| parent_skill_ids=parent_ids, | |
| tags=tags, | |
| created_by=args.created_by, | |
| change_summary=args.change_summary, | |
| ) | |
| except CloudError as e: | |
| print(f"ERROR: {e}", file=sys.stderr) | |
| sys.exit(1) | |
| print(f"\nUpload complete!", file=sys.stderr) | |
| print(json.dumps(result, indent=2, ensure_ascii=False)) | |
| if __name__ == "__main__": | |
| main() | |