gitinstall 1.1.0__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 (59) hide show
  1. gitinstall/__init__.py +61 -0
  2. gitinstall/_sdk.py +541 -0
  3. gitinstall/academic.py +831 -0
  4. gitinstall/admin.html +327 -0
  5. gitinstall/auto_update.py +384 -0
  6. gitinstall/autopilot.py +349 -0
  7. gitinstall/badge.py +476 -0
  8. gitinstall/checkpoint.py +330 -0
  9. gitinstall/cicd.py +499 -0
  10. gitinstall/clawhub.html +718 -0
  11. gitinstall/config_schema.py +353 -0
  12. gitinstall/db.py +984 -0
  13. gitinstall/db_backend.py +445 -0
  14. gitinstall/dep_chain.py +337 -0
  15. gitinstall/dependency_audit.py +1153 -0
  16. gitinstall/detector.py +542 -0
  17. gitinstall/doctor.py +493 -0
  18. gitinstall/education.py +869 -0
  19. gitinstall/enterprise.py +802 -0
  20. gitinstall/error_fixer.py +953 -0
  21. gitinstall/event_bus.py +251 -0
  22. gitinstall/executor.py +577 -0
  23. gitinstall/feature_flags.py +138 -0
  24. gitinstall/fetcher.py +921 -0
  25. gitinstall/huggingface.py +922 -0
  26. gitinstall/hw_detect.py +988 -0
  27. gitinstall/i18n.py +664 -0
  28. gitinstall/installer_registry.py +362 -0
  29. gitinstall/knowledge_base.py +379 -0
  30. gitinstall/license_check.py +605 -0
  31. gitinstall/llm.py +569 -0
  32. gitinstall/log.py +236 -0
  33. gitinstall/main.py +1408 -0
  34. gitinstall/mcp_agent.py +841 -0
  35. gitinstall/mcp_server.py +386 -0
  36. gitinstall/monorepo.py +810 -0
  37. gitinstall/multi_source.py +425 -0
  38. gitinstall/onboard.py +276 -0
  39. gitinstall/planner.py +222 -0
  40. gitinstall/planner_helpers.py +323 -0
  41. gitinstall/planner_known_projects.py +1010 -0
  42. gitinstall/planner_templates.py +996 -0
  43. gitinstall/remote_gpu.py +633 -0
  44. gitinstall/resilience.py +608 -0
  45. gitinstall/run_tests.py +572 -0
  46. gitinstall/skills.py +476 -0
  47. gitinstall/tool_schemas.py +324 -0
  48. gitinstall/trending.py +279 -0
  49. gitinstall/uninstaller.py +415 -0
  50. gitinstall/validate_top100.py +607 -0
  51. gitinstall/watchdog.py +180 -0
  52. gitinstall/web.py +1277 -0
  53. gitinstall/web_ui.html +2277 -0
  54. gitinstall-1.1.0.dist-info/METADATA +275 -0
  55. gitinstall-1.1.0.dist-info/RECORD +59 -0
  56. gitinstall-1.1.0.dist-info/WHEEL +5 -0
  57. gitinstall-1.1.0.dist-info/entry_points.txt +3 -0
  58. gitinstall-1.1.0.dist-info/licenses/LICENSE +21 -0
  59. gitinstall-1.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,323 @@
1
+ """
2
+ planner_helpers.py - 平台适配辅助函数
3
+ ======================================
4
+
5
+ 从 planner.py 拆分出来的纯函数,无状态。
6
+ 提供 OS/GPU/工具链检测、命令生成等基础设施。
7
+
8
+ GPU 自适应(自动选择正确的 PyTorch 安装命令):
9
+ - Apple MPS (M1/M2/M3/M4) → pip install torch(原生支持 MPS)
10
+ - NVIDIA CUDA 12+ → --index-url .../cu121
11
+ - NVIDIA CUDA 11 → --index-url .../cu118
12
+ - AMD ROCm → --index-url .../rocm5.6
13
+ - CPU 纯算 → --index-url .../cpu
14
+
15
+ 平台自适应:
16
+ - macOS → brew / python3 -m venv / source .../activate
17
+ - Linux → apt/snap / python3 / source .../activate
18
+ - Windows → winget/choco / python -m venv / .\\venv\\Scripts\\activate
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import re
24
+ import json
25
+ from pathlib import Path
26
+ from typing import Any
27
+
28
+
29
+ # ─────────────────────────────────────────────
30
+ # 平台适配辅助函数(纯函数,无状态)
31
+ # ─────────────────────────────────────────────
32
+
33
+ def _os_type(env: dict) -> str:
34
+ return env.get("os", {}).get("type", "linux")
35
+
36
+
37
+ def _is_apple_silicon(env: dict) -> bool:
38
+ return (
39
+ env.get("os", {}).get("is_apple_silicon", False)
40
+ or env.get("os", {}).get("chip", "").startswith("M")
41
+ or (env.get("os", {}).get("type") == "macos"
42
+ and env.get("os", {}).get("arch") == "arm64")
43
+ )
44
+
45
+
46
+ def _gpu_type(env: dict) -> str:
47
+ t = env.get("gpu", {}).get("type", "cpu_only")
48
+ # 兼容 detector.py 的不同写法
49
+ if t in ("apple_mps", "mps"):
50
+ return "mps"
51
+ if t == "cuda":
52
+ return "cuda"
53
+ if t == "rocm":
54
+ return "rocm"
55
+ return "cpu_only"
56
+
57
+
58
+ def _cuda_major(env: dict) -> int:
59
+ ver = env.get("gpu", {}).get("cuda_version", "0")
60
+ try:
61
+ return int(str(ver).split(".")[0])
62
+ except Exception:
63
+ return 0
64
+
65
+
66
+ def _has_pm(env: dict, pm: str) -> bool:
67
+ return pm in env.get("package_managers", {})
68
+
69
+
70
+ def _has_runtime(env: dict, rt: str) -> bool:
71
+ return rt in env.get("runtimes", {})
72
+
73
+
74
+ def _python_cmd(env: dict) -> str:
75
+ """Linux 上优先用 python3,其他用 python"""
76
+ if _os_type(env) == "linux":
77
+ return "python3"
78
+ return "python"
79
+
80
+
81
+ def _pip_cmd(env: dict) -> str:
82
+ if _os_type(env) == "linux":
83
+ return "pip3"
84
+ return "pip"
85
+
86
+
87
+ def _venv_activate(env: dict, venv_name: str = "venv") -> str:
88
+ """返回平台正确的 venv 激活命令"""
89
+ if _os_type(env) == "windows":
90
+ return f"{venv_name}\\Scripts\\activate"
91
+ return f"source {venv_name}/bin/activate"
92
+
93
+
94
+ def _dep_names(dependency_files: dict[str, str]) -> set[str]:
95
+ return {Path(path).name for path in dependency_files}
96
+
97
+
98
+ def _dep_content(dependency_files: dict[str, str], name: str) -> str:
99
+ for path, content in dependency_files.items():
100
+ if Path(path).name == name and "/" not in path:
101
+ return content
102
+ for path, content in dependency_files.items():
103
+ if Path(path).name == name:
104
+ return content
105
+ return ""
106
+
107
+
108
+ def _is_maturin_project(types: set[str], dependency_files: dict[str, str]) -> bool:
109
+ if not ({"python", "rust"} <= types):
110
+ return False
111
+ pyproject = _dep_content(dependency_files, "pyproject.toml")
112
+ return bool(pyproject and re.search(r"maturin|setuptools-rust", pyproject, re.IGNORECASE))
113
+
114
+
115
+ def _preferred_java_version(readme: str) -> str:
116
+ match = re.search(r"(?:openjdk|jdk|java)[^\d]{0,8}(8|11|17|21)", readme, re.IGNORECASE)
117
+ return match.group(1) if match else "17"
118
+
119
+
120
+ def _has_haskell_cabal_file(dependency_files: dict[str, str]) -> bool:
121
+ return any(Path(path).name.endswith(".cabal") for path in dependency_files)
122
+
123
+
124
+ def _stack_resolver(dependency_files: dict[str, str]) -> str:
125
+ stack_yaml = _dep_content(dependency_files, "stack.yaml")
126
+ match = re.search(r'^\s*resolver\s*:\s*["\']?([^\s"\']+)', stack_yaml, re.MULTILINE)
127
+ return match.group(1) if match else ""
128
+
129
+
130
+ def _stack_lts_major(resolver: str) -> int:
131
+ match = re.match(r'lts-(\d+)(?:\.\d+)?', resolver, re.IGNORECASE)
132
+ return int(match.group(1)) if match else 0
133
+
134
+
135
+ def _zig_minimum_version(dependency_files: dict[str, str]) -> str:
136
+ build_zon = _dep_content(dependency_files, "build.zig.zon")
137
+ match = re.search(r'\.minimum_zig_version\s*=\s*"([^"]+)"', build_zon)
138
+ if match:
139
+ return match.group(1)
140
+ return _dep_content(dependency_files, ".zig-version").strip()
141
+
142
+
143
+ def _zig_fallback_version(dependency_files: dict[str, str]) -> str:
144
+ min_version = _zig_minimum_version(dependency_files)
145
+ if min_version and _version_tuple(min_version) < (0, 15, 0):
146
+ return min_version
147
+ return "0.14.0"
148
+
149
+
150
+ def _version_tuple(version: str) -> tuple[int, ...]:
151
+ numbers = [int(part) for part in re.findall(r"\d+", version)]
152
+ return tuple(numbers[:3]) if numbers else ()
153
+
154
+
155
+ def _zig_uses_legacy_build_api(dependency_files: dict[str, str]) -> bool:
156
+ build_zig = _dep_content(dependency_files, "build.zig")
157
+ min_version = _zig_minimum_version(dependency_files)
158
+ if _version_tuple(min_version) >= (0, 15, 0):
159
+ return False
160
+ legacy_markers = [
161
+ ".root_source_file",
162
+ ".source_file",
163
+ "Build.ExecutableOptions",
164
+ ]
165
+ return any(marker in build_zig for marker in legacy_markers)
166
+
167
+
168
+ def _haskell_system_packages(dependency_files: dict[str, str], env: dict) -> list[str]:
169
+ combined = "\n".join(dependency_files.values()).lower()
170
+ packages: list[str] = ["pkg-config"]
171
+
172
+ if any(token in combined for token in ["pcre-light", "pcre-heavy", "libpcre", "pcre "]):
173
+ packages.append("pcre")
174
+ if any(token in combined for token in ["openssl", "libssl", "http-client-tls", "tls", "hsopenssl"]):
175
+ packages.append("openssl")
176
+ if any(token in combined for token in ["gtk", "pango", "gtk+-", "yi-frontend-pango"]):
177
+ packages.append("gtk+3")
178
+
179
+ deduped = list(dict.fromkeys(packages))
180
+ if _os_type(env) == "macos":
181
+ return deduped
182
+ if _os_type(env) == "linux":
183
+ mapping = {
184
+ "pkg-config": "pkg-config",
185
+ "pcre": "libpcre3-dev",
186
+ "openssl": "libssl-dev",
187
+ "gtk+3": "libgtk-3-dev",
188
+ }
189
+ return [mapping[pkg] for pkg in deduped if pkg in mapping]
190
+ return []
191
+
192
+
193
+ def _haskell_macos_env_prefix(dependency_files: dict[str, str], env: dict) -> str:
194
+ if _os_type(env) != "macos":
195
+ return ""
196
+
197
+ formulas = [pkg for pkg in _haskell_system_packages(dependency_files, env) if pkg in {"pcre", "openssl", "gtk+3"}]
198
+ lines = [
199
+ 'BREW_PREFIX="$(brew --prefix)"',
200
+ 'export PKG_CONFIG_PATH="$BREW_PREFIX/lib/pkgconfig:$BREW_PREFIX/share/pkgconfig:${PKG_CONFIG_PATH:-}"',
201
+ 'export CPATH="$BREW_PREFIX/include:${CPATH:-}"',
202
+ 'export LIBRARY_PATH="$BREW_PREFIX/lib:${LIBRARY_PATH:-}"',
203
+ 'export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1',
204
+ ]
205
+ for formula in formulas:
206
+ lines.append(
207
+ f'if brew --prefix {formula} >/dev/null 2>&1; then FORMULA_PREFIX="$(brew --prefix {formula})"; '
208
+ 'export PKG_CONFIG_PATH="$FORMULA_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"; '
209
+ 'export CPATH="$FORMULA_PREFIX/include:$CPATH"; '
210
+ 'export LIBRARY_PATH="$FORMULA_PREFIX/lib:$LIBRARY_PATH"; fi'
211
+ )
212
+ return "; ".join(lines) + ";"
213
+
214
+
215
+ def _haskell_repo_template(owner: str, repo: str, ghcup_cmd: str, env_prefix: str) -> tuple[str, str, list[str]] | None:
216
+ key = f"{owner}/{repo}".lower()
217
+
218
+ if key == "yi-editor/yi":
219
+ build_cmd = (
220
+ "perl -0pi -e 's/extra-deps:\\n - Hclip-3\\.0\\.0\\.4\\n/"
221
+ "extra-deps:\\n - Hclip-3.0.0.4\\n"
222
+ " - vty-6.5\\@sha256:43a4137de7e55cf438a8334cc525fb0e0b4efe78d2ed8bd31b0716eb34993059,3425\\n"
223
+ " - vty-crossplatform-0.5.0.0\\@sha256:6d057fd8a5582eac3be28c91e99ed3730b729078e107ad19107af46bbb2ea65d,3146\\n"
224
+ " - vty-unix-0.2.0.0\\@sha256:2af3d0bdae3c4b7b7e567ee374efe32c7439fabdf9096465ce011a6c6736e9ae,2932\\n/' stack.yaml"
225
+ f" && {env_prefix}{ghcup_cmd} run --stack latest -- stack build yi --flag yi:-pango"
226
+ )
227
+ launch_cmd = f"{env_prefix}{ghcup_cmd} run --stack latest -- stack exec yi"
228
+ notes = [
229
+ "检测到 yi 的 Apple Silicon/新 resolver 兼容问题:模板会补齐 vty、vty-crossplatform、vty-unix 的 extra-deps。",
230
+ "模板默认关闭 yi 的 pango 前端,优先构建 VTY CLI 版本,避免 GTK/text 版本窗口冲突。",
231
+ ]
232
+ return build_cmd, launch_cmd, notes
233
+
234
+ if key == "chrispenner/rasa":
235
+ build_cmd = (
236
+ "rm -rf .gitinstall-patches/eve-0.1.9.0"
237
+ f" && {env_prefix}{ghcup_cmd} run --ghc recommended --cabal recommended -- cabal get eve-0.1.9.0 --destdir .gitinstall-patches"
238
+ " && perl -0pi -e 's/import Control\\.Monad\\.State/import Control.Monad (join, void)\\nimport Control.Monad.State/'"
239
+ " .gitinstall-patches/eve-0.1.9.0/src/Eve/Internal/Actions.hs .gitinstall-patches/eve-0.1.9.0/src/Eve/Internal/Listeners.hs"
240
+ " && perl -0pi -e 's/\\} deriving \\(Eq\\)/} deriving (Eq, Functor)/g' rasa/src/Rasa/Internal/Range.hs"
241
+ " && perl -0pi -e 's/import Control\\.Monad\\.State/import Control.Monad (void)\\nimport Control.Monad.State/' rasa-ext-cursors/src/Rasa/Ext/Cursors/Internal/Base.hs"
242
+ " && printf '%s\\n' 'packages:' ' ./rasa' ' ./rasa-ext-cmd' ' ./rasa-ext-cursors' ' ./rasa-ext-files'"
243
+ " ' ./rasa-ext-logger' ' ./rasa-ext-views' ' ./rasa-ext-vim' ' ./text-lens' ' ./.gitinstall-patches/eve-0.1.9.0' 'allow-newer: true'"
244
+ " > cabal.project.gitinstall-core"
245
+ f" && {env_prefix}{ghcup_cmd} run --ghc recommended --cabal recommended -- cabal build all --project-file=cabal.project.gitinstall-core"
246
+ )
247
+ launch_cmd = f"{env_prefix}{ghcup_cmd} run --ghc recommended --cabal recommended -- cabal repl rasa --project-file=cabal.project.gitinstall-core"
248
+ notes = [
249
+ "检测到 rasa 的旧生态约束:模板会自动下载并补丁 eve-0.1.9.0,再对 rasa 核心源码打现代 GHC 兼容补丁。",
250
+ "模板默认构建 rasa 的核心包集合,并剥离已知与现代 vty API 不兼容的 slate/example 可执行目标。",
251
+ ]
252
+ return build_cmd, launch_cmd, notes
253
+
254
+ if key == "lettier/gifcurry":
255
+ build_cmd = f"{env_prefix}{ghcup_cmd} run --ghc recommended --cabal recommended -- cabal build all"
256
+ launch_cmd = f"{env_prefix}{ghcup_cmd} run --ghc recommended --cabal recommended -- cabal run gifcurry_cli"
257
+ notes = [
258
+ "检测到 gifcurry 在 Apple Silicon 上优先应走 ghcup run + cabal 路径,避免旧 stack resolver 直接落到不受支持的 GHC 二进制。",
259
+ "若后续仍被旧 GUI 目标和精确版本窗拖垮,交由通用 Haskell fixer 自动切换到 headless/CLI 构建。",
260
+ ]
261
+ return build_cmd, launch_cmd, notes
262
+
263
+ return None
264
+
265
+
266
+ def _torch_install_cmd(env: dict) -> str:
267
+ """返回适配当前 GPU 的 PyTorch 安装命令(这是 AI 项目最容易装错的一步)"""
268
+ pip = _pip_cmd(env)
269
+ gpu = _gpu_type(env)
270
+
271
+ if gpu == "mps":
272
+ # Apple Silicon:PyTorch 原生支持 MPS,直接 pip install
273
+ return f"{pip} install torch torchvision torchaudio"
274
+
275
+ if gpu == "cuda":
276
+ major = _cuda_major(env)
277
+ if major >= 12:
278
+ idx = "https://download.pytorch.org/whl/cu121"
279
+ elif major >= 11:
280
+ idx = "https://download.pytorch.org/whl/cu118"
281
+ else:
282
+ # CUDA 10 及更早版本不受 PyTorch 2.x 支持,降级到 CPU
283
+ idx = "https://download.pytorch.org/whl/cpu"
284
+ return f"{pip} install torch torchvision torchaudio --index-url {idx}"
285
+
286
+ if gpu == "rocm":
287
+ return f"{pip} install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm5.6"
288
+
289
+ # CPU-only(包含 Intel Mac)
290
+ return f"{pip} install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu"
291
+
292
+
293
+ def _node_pm(env: dict) -> tuple[str, str]:
294
+ """返回 (install 命令, dev 启动命令),优先 pnpm > yarn > npm"""
295
+ if _has_pm(env, "pnpm"):
296
+ return "pnpm install", "pnpm dev"
297
+ if _has_pm(env, "yarn"):
298
+ return "yarn", "yarn dev"
299
+ return "npm install", "npm run dev"
300
+
301
+
302
+
303
+ # ─────────────────────────────────────────────
304
+ # 模块级工具函数
305
+ # ─────────────────────────────────────────────
306
+
307
+ def _make_step(cmd: str, desc: str, warn: bool = False) -> dict:
308
+ return {
309
+ "command": cmd,
310
+ "description": desc,
311
+ "_warning": "⚠️ 执行前请确认命令来源可信" if warn else "",
312
+ }
313
+
314
+
315
+ def _get_gpu_name(env: dict) -> str:
316
+ gpu = _gpu_type(env)
317
+ if gpu == "mps":
318
+ return f"Apple {env.get('os', {}).get('chip', 'Silicon')} MPS"
319
+ if gpu == "cuda":
320
+ return f"NVIDIA CUDA {env.get('gpu', {}).get('cuda_version', '')}"
321
+ if gpu == "rocm":
322
+ return "AMD ROCm"
323
+ return "CPU(无 GPU 加速)"