File size: 3,149 Bytes
399b80c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/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()