multi-lang-build 0.2.8__py3-none-any.whl → 0.2.10__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.
Files changed (38) hide show
  1. multi_lang_build/__init__.py +4 -4
  2. multi_lang_build/cli.py +3 -2
  3. multi_lang_build/compiler/__init__.py +1 -1
  4. multi_lang_build/compiler/go_compiler.py +388 -0
  5. multi_lang_build/compiler/go_support/__init__.py +19 -0
  6. multi_lang_build/compiler/go_support/binary.py +117 -0
  7. multi_lang_build/compiler/go_support/builder.py +228 -0
  8. multi_lang_build/compiler/go_support/cleaner.py +40 -0
  9. multi_lang_build/compiler/go_support/env.py +41 -0
  10. multi_lang_build/compiler/go_support/mirror.py +111 -0
  11. multi_lang_build/compiler/go_support/module.py +77 -0
  12. multi_lang_build/compiler/go_support/tester.py +199 -0
  13. multi_lang_build/compiler/pnpm.py +61 -209
  14. multi_lang_build/compiler/pnpm_support/__init__.py +6 -0
  15. multi_lang_build/compiler/pnpm_support/executor.py +148 -0
  16. multi_lang_build/compiler/pnpm_support/project.py +53 -0
  17. multi_lang_build/compiler/python.py +65 -222
  18. multi_lang_build/compiler/python_support/__init__.py +13 -0
  19. multi_lang_build/compiler/python_support/cleaner.py +56 -0
  20. multi_lang_build/compiler/python_support/cli.py +46 -0
  21. multi_lang_build/compiler/python_support/detector.py +64 -0
  22. multi_lang_build/compiler/python_support/installer.py +162 -0
  23. multi_lang_build/compiler/python_support/venv.py +63 -0
  24. multi_lang_build/ide_register.py +97 -0
  25. multi_lang_build/mirror/config.py +19 -0
  26. multi_lang_build/register/support/__init__.py +13 -0
  27. multi_lang_build/register/support/claude.py +94 -0
  28. multi_lang_build/register/support/codebuddy.py +100 -0
  29. multi_lang_build/register/support/opencode.py +62 -0
  30. multi_lang_build/register/support/trae.py +72 -0
  31. {multi_lang_build-0.2.8.dist-info → multi_lang_build-0.2.10.dist-info}/METADATA +1 -1
  32. multi_lang_build-0.2.10.dist-info/RECORD +40 -0
  33. multi_lang_build/compiler/go.py +0 -564
  34. multi_lang_build/register.py +0 -412
  35. multi_lang_build-0.2.8.dist-info/RECORD +0 -18
  36. {multi_lang_build-0.2.8.dist-info → multi_lang_build-0.2.10.dist-info}/WHEEL +0 -0
  37. {multi_lang_build-0.2.8.dist-info → multi_lang_build-0.2.10.dist-info}/entry_points.txt +0 -0
  38. {multi_lang_build-0.2.8.dist-info → multi_lang_build-0.2.10.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,162 @@
1
+ """Python dependency installation."""
2
+
3
+ import os
4
+ import subprocess
5
+ import sys
6
+ import time
7
+ from pathlib import Path
8
+
9
+ from multi_lang_build.compiler.base import BuildResult
10
+
11
+
12
+ class DependencyInstaller:
13
+ """Install Python dependencies for various build systems."""
14
+
15
+ @staticmethod
16
+ def install_poetry(
17
+ python_executable: str,
18
+ source_dir: Path,
19
+ environment: dict[str, str],
20
+ dev: bool = False,
21
+ stream_output: bool = True,
22
+ ) -> BuildResult:
23
+ """Install dependencies using Poetry."""
24
+ cmd = [python_executable, "-m", "poetry", "install"]
25
+ if dev:
26
+ cmd.append("--with=dev")
27
+
28
+ return DependencyInstaller._run_pip(
29
+ cmd, source_dir, source_dir, environment, stream_output
30
+ )
31
+
32
+ @staticmethod
33
+ def install_pip(
34
+ python_executable: str,
35
+ source_dir: Path,
36
+ environment: dict[str, str],
37
+ dev: bool = False,
38
+ stream_output: bool = True,
39
+ ) -> BuildResult:
40
+ """Install dependencies using pip."""
41
+ cmd = [python_executable, "-m", "pip", "install", "-r", str(source_dir / "requirements.txt")]
42
+
43
+ if dev:
44
+ cmd.append("-r")
45
+ cmd.append(str(source_dir / "requirements-dev.txt"))
46
+
47
+ return DependencyInstaller._run_pip(
48
+ cmd, source_dir, source_dir, environment, stream_output
49
+ )
50
+
51
+ @staticmethod
52
+ def _run_pip(
53
+ command: list[str],
54
+ source_dir: Path,
55
+ output_dir: Path,
56
+ environment: dict[str, str],
57
+ stream_output: bool,
58
+ ) -> BuildResult:
59
+ """Execute pip command."""
60
+ import time
61
+
62
+ start_time = time.perf_counter()
63
+
64
+ try:
65
+ if stream_output:
66
+ return DependencyInstaller._stream_pip(
67
+ command, source_dir, environment, start_time
68
+ )
69
+ else:
70
+ return DependencyInstaller._capture_pip(
71
+ command, source_dir, environment, start_time
72
+ )
73
+ except Exception as e:
74
+ duration = time.perf_counter() - start_time
75
+ return BuildResult(
76
+ success=False,
77
+ return_code=-2,
78
+ stdout="",
79
+ stderr=f"Install error: {str(e)}",
80
+ output_path=None,
81
+ duration_seconds=duration,
82
+ )
83
+
84
+ @staticmethod
85
+ def _stream_pip(
86
+ command: list[str],
87
+ source_dir: Path,
88
+ environment: dict[str, str],
89
+ start_time: float,
90
+ ) -> BuildResult:
91
+ """Execute pip with streaming output."""
92
+ import os
93
+ import subprocess as sp
94
+ import sys
95
+
96
+ stdout_buffer = []
97
+ stderr_buffer = []
98
+
99
+ process = sp.Popen(
100
+ command,
101
+ cwd=source_dir,
102
+ stdout=sp.PIPE,
103
+ stderr=sp.PIPE,
104
+ text=True,
105
+ env={**os.environ, **environment},
106
+ )
107
+
108
+ # Read stdout
109
+ if process.stdout:
110
+ for line in process.stdout:
111
+ line = line.rstrip('\n\r')
112
+ stdout_buffer.append(line)
113
+ print(line)
114
+ sys.stdout.flush()
115
+
116
+ # Read stderr
117
+ if process.stderr:
118
+ for line in process.stderr:
119
+ line = line.rstrip('\n\r')
120
+ stderr_buffer.append(line)
121
+ print(line, file=sys.stderr)
122
+ sys.stderr.flush()
123
+
124
+ return_code = process.wait()
125
+ duration = time.perf_counter() - start_time
126
+
127
+ return BuildResult(
128
+ success=return_code == 0,
129
+ return_code=return_code,
130
+ stdout='\n'.join(stdout_buffer),
131
+ stderr='\n'.join(stderr_buffer),
132
+ output_path=source_dir,
133
+ duration_seconds=duration,
134
+ )
135
+
136
+ @staticmethod
137
+ def _capture_pip(
138
+ command: list[str],
139
+ source_dir: Path,
140
+ environment: dict[str, str],
141
+ start_time: float,
142
+ ) -> BuildResult:
143
+ """Execute pip with captured output."""
144
+ result = subprocess.run(
145
+ command,
146
+ cwd=source_dir,
147
+ capture_output=True,
148
+ text=True,
149
+ timeout=3600,
150
+ env={**os.environ, **environment},
151
+ )
152
+
153
+ duration = time.perf_counter() - start_time
154
+
155
+ return BuildResult(
156
+ success=result.returncode == 0,
157
+ return_code=result.returncode,
158
+ stdout=result.stdout,
159
+ stderr=result.stderr,
160
+ output_path=source_dir,
161
+ duration_seconds=duration,
162
+ )
@@ -0,0 +1,63 @@
1
+ """Python virtual environment management."""
2
+
3
+ import time
4
+ import venv
5
+ from pathlib import Path
6
+
7
+ from multi_lang_build.compiler.base import BuildResult
8
+
9
+
10
+ class VenvManager:
11
+ """Manage Python virtual environments."""
12
+
13
+ @staticmethod
14
+ def create(
15
+ directory: Path,
16
+ python_path: str | None = None,
17
+ mirror_enabled: bool = True,
18
+ ) -> BuildResult:
19
+ """Create a virtual environment.
20
+
21
+ Args:
22
+ directory: Directory to create the venv in
23
+ python_path: Python interpreter to use
24
+ mirror_enabled: Whether to configure pip mirror
25
+
26
+ Returns:
27
+ BuildResult containing success status and output information.
28
+ """
29
+ start_time = time.perf_counter()
30
+
31
+ try:
32
+ env_builder = venv.EnvBuilder(with_pip=True, clear=True)
33
+ env_builder.create(directory)
34
+
35
+ # Configure pip mirror if enabled
36
+ if mirror_enabled:
37
+ pip_config_dir = directory / "pip.conf"
38
+ pip_config_dir.write_text(
39
+ "[global]\n"
40
+ "index-url = https://pypi.tuna.tsinghua.edu.cn/simple\n"
41
+ "trusted-host = pypi.tuna.tsinghua.edu.cn\n"
42
+ )
43
+
44
+ duration = time.perf_counter() - start_time
45
+
46
+ return BuildResult(
47
+ success=True,
48
+ return_code=0,
49
+ stdout=f"Virtual environment created at {directory}",
50
+ stderr="",
51
+ output_path=directory,
52
+ duration_seconds=duration,
53
+ )
54
+ except Exception as e:
55
+ duration = time.perf_counter() - start_time
56
+ return BuildResult(
57
+ success=False,
58
+ return_code=-1,
59
+ stdout="",
60
+ stderr=f"Failed to create virtual environment: {str(e)}",
61
+ output_path=None,
62
+ duration_seconds=duration,
63
+ )
@@ -0,0 +1,97 @@
1
+ """Register multi-lang-build as a skill for various IDEs."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import subprocess
6
+ import sys
7
+ from typing import Literal
8
+
9
+ from multi_lang_build.register.support import (
10
+ register_claude_code,
11
+ register_opencode,
12
+ register_trae,
13
+ register_codebuddy,
14
+ )
15
+
16
+
17
+ def get_cli_path() -> str:
18
+ """Get the path to the multi-lang-build CLI."""
19
+ result = subprocess.run(
20
+ ["which", "multi-lang-build"],
21
+ capture_output=True,
22
+ text=True,
23
+ )
24
+ if result.returncode == 0:
25
+ return result.stdout.strip()
26
+ return f"{sys.executable} -m multi_lang_build"
27
+
28
+
29
+ def register_skill(
30
+ ide: Literal["claude", "opencode", "trae", "codebuddy", "all"] = "claude",
31
+ global_level: bool = False
32
+ ) -> bool:
33
+ """Register multi-lang-build as a skill for the specified IDE.
34
+
35
+ Args:
36
+ ide: The IDE to register with. Options: "claude", "opencode", "trae", "codebuddy", "all"
37
+ Default is "claude".
38
+ global_level: If True, register to global config. If False (default), register to project-level.
39
+
40
+ Returns:
41
+ True if registration succeeded, False otherwise.
42
+ """
43
+ print(f"📝 Registering multi-lang-build for {ide}...\n")
44
+
45
+ if ide == "all":
46
+ results = [
47
+ ("Claude Code", register_claude_code(project_level=not global_level)),
48
+ ("OpenCode", register_opencode(project_level=not global_level)),
49
+ ("Trae", register_trae(project_level=not global_level)),
50
+ ("CodeBuddy", register_codebuddy(project_level=not global_level)),
51
+ ]
52
+
53
+ print("\n" + "=" * 50)
54
+ print("Registration Summary:")
55
+ for name, success in results:
56
+ status = "✅" if success else "❌"
57
+ print(f" {status} {name}")
58
+
59
+ return all(success for _, success in results)
60
+
61
+ elif ide == "claude":
62
+ return register_claude_code(project_level=not global_level)
63
+ elif ide == "opencode":
64
+ return register_opencode(project_level=not global_level)
65
+ elif ide == "trae":
66
+ return register_trae(project_level=not global_level)
67
+ elif ide == "codebuddy":
68
+ return register_codebuddy(project_level=not global_level)
69
+ else:
70
+ print(f"❌ Unknown IDE: {ide}")
71
+ print("Supported IDEs: claude, opencode, trae, codebuddy, all")
72
+ return False
73
+
74
+
75
+ if __name__ == "__main__":
76
+ import argparse
77
+
78
+ parser = argparse.ArgumentParser(
79
+ description="Register multi-lang-build as an IDE skill"
80
+ )
81
+ parser.add_argument(
82
+ "ide",
83
+ nargs="?",
84
+ default="claude",
85
+ choices=["claude", "opencode", "trae", "codebuddy", "all"],
86
+ help="IDE to register with (default: claude)",
87
+ )
88
+ parser.add_argument(
89
+ "--global",
90
+ dest="global_level",
91
+ action="store_true",
92
+ help="Register to global config instead of project-level",
93
+ )
94
+
95
+ args = parser.parse_args()
96
+ success = register_skill(args.ide, global_level=args.global_level)
97
+ sys.exit(0 if success else 1)
@@ -249,3 +249,22 @@ def validate_mirror_config(mirror_config: MirrorConfig) -> bool:
249
249
  return False
250
250
 
251
251
  return True
252
+
253
+
254
+ # Go mirrors in failover order (goproxy.io → goproxy.cn → goproxy.vip.cn)
255
+ GO_MIRROR_FALLBACK_ORDER = ["go_qiniu", "go", "go_vip"]
256
+
257
+
258
+ def get_go_mirror_with_fallback(failover: bool = True) -> list[str]:
259
+ """Get Go mirror list for failover.
260
+
261
+ Args:
262
+ failover: If True, return all mirrors in fallback order.
263
+ If False, return only the default mirror.
264
+
265
+ Returns:
266
+ List of mirror keys to try.
267
+ """
268
+ if failover:
269
+ return GO_MIRROR_FALLBACK_ORDER
270
+ return ["go"]
@@ -0,0 +1,13 @@
1
+ """IDE registration support modules."""
2
+
3
+ from multi_lang_build.register.support.claude import register_claude_code
4
+ from multi_lang_build.register.support.opencode import register_opencode
5
+ from multi_lang_build.register.support.trae import register_trae
6
+ from multi_lang_build.register.support.codebuddy import register_codebuddy
7
+
8
+ __all__ = [
9
+ "register_claude_code",
10
+ "register_opencode",
11
+ "register_trae",
12
+ "register_codebuddy",
13
+ ]
@@ -0,0 +1,94 @@
1
+ """Register with Claude Code."""
2
+
3
+ from pathlib import Path
4
+ import subprocess
5
+
6
+
7
+ def register_claude_code(project_level: bool = True) -> bool:
8
+ """Register as Claude Code skill.
9
+
10
+ Args:
11
+ project_level: If True (default), register to project-level .claude/multi-lang-build.md.
12
+ If False, register to global ~/.claude/CLAUDE.md.
13
+ """
14
+ try:
15
+ # Determine registration path
16
+ if project_level:
17
+ # Project-level: .claude/multi-lang-build.md in current directory
18
+ config_dir = Path.cwd() / ".claude"
19
+ config_dir.mkdir(exist_ok=True)
20
+ skill_file = config_dir / "multi-lang-build.md"
21
+ level_name = "project-level"
22
+ else:
23
+ # Global-level: ~/.claude/CLAUDE.md (only check CLI for global)
24
+ result = subprocess.run(
25
+ ["which", "claude"],
26
+ capture_output=True,
27
+ text=True,
28
+ )
29
+
30
+ if result.returncode != 0:
31
+ print("❌ Claude Code CLI not found. Please install it first:")
32
+ print(" npm install -g @anthropic-ai/claude-code")
33
+ return False
34
+
35
+ claude_dir = Path.home() / ".claude"
36
+ claude_dir.mkdir(exist_ok=True)
37
+ skill_file = claude_dir / "CLAUDE.md"
38
+ level_name = "global"
39
+
40
+ skill_content = """## Multi-Lang Build Tool
41
+
42
+ You can use the `multi-lang-build` tool to compile projects:
43
+
44
+ ### Available Commands:
45
+ - `multi-lang-build pnpm <source> --output <dir>` - Build pnpm projects
46
+ - `multi-lang-build go <source> --output <bin>` - Build Go projects
47
+ - `multi-lang-build python <source> --output <dir>` - Build Python projects
48
+ - `multi-lang-build mirror list|set|show` - Configure domestic mirrors
49
+
50
+ ### Examples:
51
+ ```bash
52
+ # Build Go project
53
+ multi-lang-build go ./src --output ./bin/app --mirror
54
+
55
+ # Build with specific target (multi-entry support)
56
+ multi-lang-build go ./src --output ./bin/server --target cmd/server/main.go
57
+
58
+ # Build Python project
59
+ multi-lang-build python ./src --output ./dist --mirror
60
+
61
+ # Build pnpm project
62
+ multi-lang-build pnpm ./src --output ./dist --mirror
63
+
64
+ # Configure mirror
65
+ multi-lang-build mirror set pip pip_aliyun
66
+ multi-lang-build mirror set go
67
+ ```
68
+
69
+ When working with Go projects, check if there are multiple main packages and use the `--target` flag to specify which one to build.
70
+ """
71
+
72
+ if project_level:
73
+ # Project-level: create dedicated file
74
+ with open(skill_file, "w") as f:
75
+ f.write(skill_content)
76
+ print(f"✅ Registered with Claude Code ({level_name}, created {skill_file})")
77
+ else:
78
+ # Global-level: append to existing CLAUDE.md if not already present
79
+ existing_content = ""
80
+ if skill_file.exists():
81
+ existing_content = skill_file.read_text()
82
+
83
+ if "## Multi-Lang Build Tool" not in existing_content:
84
+ with open(skill_file, "a") as f:
85
+ f.write(skill_content)
86
+ print(f"✅ Registered with Claude Code ({level_name}, added to {skill_file})")
87
+ else:
88
+ print(f"ℹ️ Already registered with Claude Code ({level_name}, {skill_file})")
89
+
90
+ return True
91
+
92
+ except Exception as e:
93
+ print(f"❌ Failed to register with Claude Code: {e}")
94
+ return False
@@ -0,0 +1,100 @@
1
+ """Register with CodeBuddy."""
2
+
3
+ from pathlib import Path
4
+
5
+
6
+ def register_codebuddy(project_level: bool = True) -> bool:
7
+ """Register as CodeBuddy skill.
8
+
9
+ Args:
10
+ project_level: If True (default), register to project-level .codebuddy/skills.yaml.
11
+ If False, register to global ~/.codebuddy/skills.yaml.
12
+ """
13
+ try:
14
+ # Determine registration path
15
+ if project_level:
16
+ # Project-level: .codebuddy/skills.yaml in current directory
17
+ base_dir = Path.cwd()
18
+ config_dir = base_dir / ".codebuddy"
19
+ config_dir.mkdir(exist_ok=True)
20
+ skills_file = config_dir / "skills.yaml"
21
+ level_name = "project-level"
22
+ else:
23
+ # Global-level: ~/.codebuddy/skills.yaml
24
+ config_dir = Path.home() / ".codebuddy"
25
+ config_dir.mkdir(exist_ok=True)
26
+ skills_file = config_dir / "skills.yaml"
27
+ level_name = "global"
28
+
29
+ skill_config = """# Multi-Lang Build Skill
30
+ skills:
31
+ multi-lang-build:
32
+ name: "Multi-Lang Build"
33
+ description: "Multi-language automated build tool with mirror acceleration"
34
+ version: "0.2.0"
35
+
36
+ commands:
37
+ build-go:
38
+ description: "Build Go project"
39
+ command: "multi-lang-build go {source} --output {output}"
40
+ args:
41
+ - name: source
42
+ description: "Source directory"
43
+ required: true
44
+ - name: output
45
+ description: "Output path"
46
+ required: true
47
+ - name: target
48
+ description: "Build target (file or directory)"
49
+ required: false
50
+ - name: mirror
51
+ description: "Enable mirror acceleration"
52
+ type: flag
53
+
54
+ build-python:
55
+ description: "Build Python project"
56
+ command: "multi-lang-build python {source} --output {output}"
57
+ args:
58
+ - name: source
59
+ description: "Source directory"
60
+ required: true
61
+ - name: output
62
+ description: "Output directory"
63
+ required: true
64
+ - name: mirror
65
+ description: "Enable mirror acceleration"
66
+ type: flag
67
+
68
+ build-pnpm:
69
+ description: "Build pnpm project"
70
+ command: "multi-lang-build pnpm {source} --output {output}"
71
+ args:
72
+ - name: source
73
+ description: "Source directory"
74
+ required: true
75
+ - name: output
76
+ description: "Output directory"
77
+ required: true
78
+ - name: mirror
79
+ description: "Enable mirror acceleration"
80
+ type: flag
81
+ """
82
+
83
+ # Append or create
84
+ if skills_file.exists():
85
+ content = skills_file.read_text()
86
+ if "multi-lang-build" not in content:
87
+ with open(skills_file, "a") as f:
88
+ f.write("\n" + skill_config)
89
+ print(f"✅ Registered with CodeBuddy ({level_name}, updated {skills_file})")
90
+ else:
91
+ print(f"ℹ️ Already registered with CodeBuddy ({level_name}, {skills_file})")
92
+ else:
93
+ skills_file.write_text(skill_config)
94
+ print(f"✅ Registered with CodeBuddy ({level_name}, created {skills_file})")
95
+
96
+ return True
97
+
98
+ except Exception as e:
99
+ print(f"❌ Failed to register with CodeBuddy: {e}")
100
+ return False
@@ -0,0 +1,62 @@
1
+ """Register with OpenCode."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+
7
+ def register_opencode(project_level: bool = True) -> bool:
8
+ """Register as OpenCode skill.
9
+
10
+ Args:
11
+ project_level: If True (default), register to project-level .opencode/skills.json.
12
+ If False, register to global ~/.config/opencode/skills.json.
13
+ """
14
+ try:
15
+ # Determine registration path
16
+ if project_level:
17
+ # Project-level: .opencode/skills.json in current directory
18
+ base_dir = Path.cwd()
19
+ config_dir = base_dir / ".opencode"
20
+ config_dir.mkdir(exist_ok=True)
21
+ skills_file = config_dir / "skills.json"
22
+ level_name = "project-level"
23
+ else:
24
+ # Global-level: ~/.config/opencode/skills.json
25
+ config_dir = Path.home() / ".config" / "opencode"
26
+ config_dir.mkdir(parents=True, exist_ok=True)
27
+ skills_file = config_dir / "skills.json"
28
+ level_name = "global"
29
+
30
+ # Create or update skills.json
31
+ skills: dict = {}
32
+
33
+ if skills_file.exists():
34
+ with open(skills_file) as f:
35
+ skills = json.load(f)
36
+
37
+ # Add multi-lang-build skill
38
+ skills["multi-lang-build"] = {
39
+ "name": "multi-lang-build",
40
+ "description": "Multi-language automated build tool with mirror acceleration",
41
+ "commands": {
42
+ "build-go": "multi-lang-build go <source> --output <output> [--mirror] [--target <target>]",
43
+ "build-python": "multi-lang-build python <source> --output <output> [--mirror]",
44
+ "build-pnpm": "multi-lang-build pnpm <source> --output <output> [--mirror]",
45
+ },
46
+ "examples": [
47
+ "multi-lang-build go ./src --output ./bin/app --mirror",
48
+ "multi-lang-build go ./src --output ./bin/server --target cmd/server/main.go",
49
+ "multi-lang-build python ./src --output ./dist --mirror",
50
+ "multi-lang-build pnpm ./src --output ./dist --mirror",
51
+ ]
52
+ }
53
+
54
+ with open(skills_file, "w") as f:
55
+ json.dump(skills, f, indent=2)
56
+
57
+ print(f"✅ Registered with OpenCode ({level_name}, config: {skills_file})")
58
+ return True
59
+
60
+ except Exception as e:
61
+ print(f"❌ Failed to register with OpenCode: {e}")
62
+ return False
@@ -0,0 +1,72 @@
1
+ """Register with Trae."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+
7
+ def register_trae(project_level: bool = True) -> bool:
8
+ """Register as Trae skill.
9
+
10
+ Args:
11
+ project_level: If True (default), register to project-level .trae/skills.json.
12
+ If False, register to global ~/.trae/skills.json.
13
+ """
14
+ try:
15
+ # Determine registration path
16
+ if project_level:
17
+ # Project-level: .trae/skills.json in current directory
18
+ base_dir = Path.cwd()
19
+ config_dir = base_dir / ".trae"
20
+ config_dir.mkdir(exist_ok=True)
21
+ skills_file = config_dir / "skills.json"
22
+ level_name = "project-level"
23
+ else:
24
+ # Global-level: ~/.trae/skills.json
25
+ config_dir = Path.home() / ".trae"
26
+ config_dir.mkdir(exist_ok=True)
27
+ skills_file = config_dir / "skills.json"
28
+ level_name = "global"
29
+
30
+ # Create or update skills.json
31
+ skills: dict = {}
32
+
33
+ if skills_file.exists():
34
+ with open(skills_file) as f:
35
+ skills = json.load(f)
36
+
37
+ # Add multi-lang-build skill
38
+ skills["multi-lang-build"] = {
39
+ "name": "Multi-Lang Build",
40
+ "description": "Automated build tool for Go, Python, and pnpm projects",
41
+ "category": "build",
42
+ "commands": [
43
+ {
44
+ "name": "build-go",
45
+ "command": "multi-lang-build go {source} --output {output}",
46
+ "description": "Build Go project",
47
+ "args": ["source", "output", "target", "mirror"]
48
+ },
49
+ {
50
+ "name": "build-python",
51
+ "command": "multi-lang-build python {source} --output {output}",
52
+ "description": "Build Python project",
53
+ "args": ["source", "output", "mirror"]
54
+ },
55
+ {
56
+ "name": "build-pnpm",
57
+ "command": "multi-lang-build pnpm {source} --output {output}",
58
+ "description": "Build pnpm project",
59
+ "args": ["source", "output", "mirror"]
60
+ }
61
+ ]
62
+ }
63
+
64
+ with open(skills_file, "w") as f:
65
+ json.dump(skills, f, indent=2)
66
+
67
+ print(f"✅ Registered with Trae ({level_name}, config: {skills_file})")
68
+ return True
69
+
70
+ except Exception as e:
71
+ print(f"❌ Failed to register with Trae: {e}")
72
+ return False