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
gitinstall/watchdog.py ADDED
@@ -0,0 +1,180 @@
1
+ """
2
+ watchdog.py - 安装看门狗系统
3
+ ===============================
4
+
5
+ 灵感来源:ICE-cluade-SCompany 的 Watchdog 线程
6
+
7
+ 监控安装步骤执行,处理以下情况:
8
+ 1. 步骤超时:pip install 卡死 → 自动 kill + 切换策略
9
+ 2. 资源溢出:检测磁盘/内存不足 → 及时中止
10
+ 3. 挂起检测:进程无输出超过 N 秒 → 判定挂起
11
+
12
+ 零外部依赖,纯 Python 标准库。
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import os
18
+ import shutil
19
+ import signal
20
+ import subprocess
21
+ import threading
22
+ import time
23
+ from dataclasses import dataclass
24
+ from typing import Optional, Callable
25
+
26
+
27
+ # ── 默认超时配置(秒)──
28
+ DEFAULT_STEP_TIMEOUT = 600 # 单步最大 10 分钟
29
+ DEFAULT_IDLE_TIMEOUT = 120 # 无输出最大 2 分钟
30
+ GIT_CLONE_TIMEOUT = 300 # git clone 最大 5 分钟
31
+ PIP_INSTALL_TIMEOUT = 900 # pip install 最大 15 分钟
32
+ NPM_INSTALL_TIMEOUT = 600 # npm install 最大 10 分钟
33
+ DISK_MIN_MB = 500 # 最少剩余 500 MB
34
+
35
+
36
+ @dataclass
37
+ class WatchdogAlert:
38
+ """看门狗告警"""
39
+ alert_type: str # timeout, idle, disk_low, memory_high, killed
40
+ step_index: int
41
+ command: str
42
+ message: str
43
+ elapsed_sec: float = 0.0
44
+ threshold_sec: float = 0.0
45
+ action_taken: str = "" # killed, skipped, retried, warned
46
+
47
+
48
+ @dataclass
49
+ class WatchdogConfig:
50
+ """看门狗配置"""
51
+ step_timeout: int = DEFAULT_STEP_TIMEOUT
52
+ idle_timeout: int = DEFAULT_IDLE_TIMEOUT
53
+ disk_min_mb: int = DISK_MIN_MB
54
+ enabled: bool = True
55
+ on_alert: Optional[Callable] = None # 告警回调
56
+
57
+
58
+ class StepWatchdog:
59
+ """单步执行看门狗"""
60
+
61
+ def __init__(self, config: WatchdogConfig = None):
62
+ self.config = config or WatchdogConfig()
63
+ self.alerts: list[WatchdogAlert] = []
64
+ self._timer: Optional[threading.Timer] = None
65
+ self._process: Optional[subprocess.Popen] = None
66
+ self._killed = False
67
+
68
+ def get_timeout_for_command(self, command: str) -> int:
69
+ """根据命令类型智能选择超时时间"""
70
+ cmd_lower = command.lower()
71
+ if "git clone" in cmd_lower or "git pull" in cmd_lower:
72
+ return GIT_CLONE_TIMEOUT
73
+ if "pip install" in cmd_lower or "pip3 install" in cmd_lower:
74
+ return PIP_INSTALL_TIMEOUT
75
+ if "npm install" in cmd_lower or "npm ci" in cmd_lower:
76
+ return NPM_INSTALL_TIMEOUT
77
+ if "cargo build" in cmd_lower:
78
+ return PIP_INSTALL_TIMEOUT # Rust 编译也可能很慢
79
+ if "make" in cmd_lower or "cmake" in cmd_lower:
80
+ return PIP_INSTALL_TIMEOUT
81
+ if "docker" in cmd_lower:
82
+ return PIP_INSTALL_TIMEOUT
83
+ if "conda install" in cmd_lower:
84
+ return PIP_INSTALL_TIMEOUT
85
+ return self.config.step_timeout
86
+
87
+ def check_disk_space(self, path: str = None) -> Optional[WatchdogAlert]:
88
+ """检查磁盘空间"""
89
+ try:
90
+ target = path or os.path.expanduser("~")
91
+ usage = shutil.disk_usage(target)
92
+ free_mb = usage.free / (1024 * 1024)
93
+ if free_mb < self.config.disk_min_mb:
94
+ alert = WatchdogAlert(
95
+ alert_type="disk_low",
96
+ step_index=-1, command="",
97
+ message=f"磁盘空间不足:仅剩 {free_mb:.0f} MB(阈值 {self.config.disk_min_mb} MB)",
98
+ action_taken="warned",
99
+ )
100
+ self.alerts.append(alert)
101
+ return alert
102
+ except OSError:
103
+ pass
104
+ return None
105
+
106
+ def start_timer(self, process: subprocess.Popen, step_index: int,
107
+ command: str, timeout: int = None):
108
+ """启动超时定时器"""
109
+ if not self.config.enabled:
110
+ return
111
+
112
+ self._process = process
113
+ self._killed = False
114
+ timeout = timeout or self.get_timeout_for_command(command)
115
+
116
+ def _on_timeout():
117
+ if process.poll() is None: # 还在运行
118
+ self._killed = True
119
+ alert = WatchdogAlert(
120
+ alert_type="timeout",
121
+ step_index=step_index,
122
+ command=command,
123
+ message=f"步骤 {step_index + 1} 超时({timeout}s),已终止",
124
+ elapsed_sec=timeout,
125
+ threshold_sec=timeout,
126
+ action_taken="killed",
127
+ )
128
+ self.alerts.append(alert)
129
+ if self.config.on_alert:
130
+ self.config.on_alert(alert)
131
+ # 优雅终止:先 SIGTERM,再 SIGKILL
132
+ try:
133
+ process.terminate()
134
+ try:
135
+ process.wait(timeout=5)
136
+ except subprocess.TimeoutExpired:
137
+ process.kill()
138
+ except OSError:
139
+ pass
140
+
141
+ self._timer = threading.Timer(timeout, _on_timeout)
142
+ self._timer.daemon = True
143
+ self._timer.start()
144
+
145
+ def cancel_timer(self):
146
+ """取消超时定时器"""
147
+ if self._timer:
148
+ self._timer.cancel()
149
+ self._timer = None
150
+
151
+ @property
152
+ def was_killed(self) -> bool:
153
+ """进程是否被看门狗终止"""
154
+ return self._killed
155
+
156
+ def format_alerts(self) -> str:
157
+ """格式化告警列表"""
158
+ if not self.alerts:
159
+ return " 🐕 看门狗:无告警"
160
+
161
+ lines = [f" 🐕 看门狗告警(共 {len(self.alerts)} 条):"]
162
+ icons = {"timeout": "⏰", "idle": "💤", "disk_low": "💾",
163
+ "memory_high": "🧠", "killed": "☠️"}
164
+ for a in self.alerts:
165
+ icon = icons.get(a.alert_type, "⚠️")
166
+ lines.append(f" {icon} [{a.alert_type}] {a.message}")
167
+ if a.action_taken:
168
+ lines.append(f" 操作:{a.action_taken}")
169
+ return "\n".join(lines)
170
+
171
+
172
+ # ─────────────────────────────────────────────
173
+ # 便捷函数
174
+ # ─────────────────────────────────────────────
175
+
176
+ def create_watchdog(enabled: bool = True,
177
+ on_alert: Callable = None) -> StepWatchdog:
178
+ """创建看门狗实例"""
179
+ config = WatchdogConfig(enabled=enabled, on_alert=on_alert)
180
+ return StepWatchdog(config)