@ranger1/dx 0.1.98 → 0.1.100

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.
@@ -1,430 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- MAX_ROUNDS=3
5
- while [[ $# -gt 0 ]]; do
6
- case "$1" in
7
- --max-rounds)
8
- MAX_ROUNDS="${2:-3}"
9
- shift 2
10
- ;;
11
- *)
12
- shift
13
- ;;
14
- esac
15
- done
16
-
17
- if ! [[ "$MAX_ROUNDS" =~ ^[0-9]+$ ]] || [[ "$MAX_ROUNDS" -lt 1 ]]; then
18
- echo "[doctor] --max-rounds 必须是正整数" >&2
19
- exit 2
20
- fi
21
-
22
- CACHE_ROOT="${PWD}/.cache/doctor"
23
- mkdir -p "$CACHE_ROOT"
24
- CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
25
-
26
- LAST_CHECK_DIR=""
27
- DX_FORCE_OK=0
28
- DX_FORCE_MSG=""
29
-
30
- run_silent() {
31
- "$@" >/dev/null 2>&1
32
- }
33
-
34
- detect_pkg_manager() {
35
- if command -v brew >/dev/null 2>&1; then echo "brew"; return; fi
36
- if command -v apt-get >/dev/null 2>&1; then echo "apt"; return; fi
37
- if command -v dnf >/dev/null 2>&1; then echo "dnf"; return; fi
38
- if command -v yum >/dev/null 2>&1; then echo "yum"; return; fi
39
- if command -v pacman >/dev/null 2>&1; then echo "pacman"; return; fi
40
- echo "none"
41
- }
42
-
43
- install_python3() {
44
- local pm
45
- pm="$(detect_pkg_manager)"
46
- case "$pm" in
47
- brew)
48
- brew install python
49
- ;;
50
- apt)
51
- sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip
52
- ;;
53
- dnf)
54
- sudo dnf install -y python3 python3-pip
55
- ;;
56
- yum)
57
- sudo yum install -y python3 python3-pip
58
- ;;
59
- pacman)
60
- sudo pacman -Sy --noconfirm python
61
- ;;
62
- *)
63
- echo "未检测到可用包管理器,无法安装 python3" >&2
64
- return 1
65
- ;;
66
- esac
67
- }
68
-
69
- ensure_python_alias() {
70
- local py3 target_dir target py_major
71
- py3="$(command -v python3 || true)"
72
- if [[ -z "$py3" ]]; then
73
- echo "python3 不存在,无法创建 python 别名" >&2
74
- return 1
75
- fi
76
-
77
- if command -v python >/dev/null 2>&1; then
78
- py_major="$(python -c 'import sys; print(sys.version_info[0])' 2>/dev/null || true)"
79
- if [[ "$py_major" == "3" ]]; then
80
- return 0
81
- fi
82
- fi
83
-
84
- # 避免污染系统/工具链目录,统一落到用户态目录。
85
- target_dir="$HOME/.local/bin"
86
- mkdir -p "$target_dir"
87
- target="$target_dir/python"
88
- ln -sf "$py3" "$target"
89
-
90
- if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
91
- export PATH="$HOME/.local/bin:$PATH"
92
- fi
93
-
94
- py_major="$(python -c 'import sys; print(sys.version_info[0])' 2>/dev/null || true)"
95
- [[ "$py_major" == "3" ]]
96
- }
97
-
98
- install_rg() {
99
- local pm
100
- pm="$(detect_pkg_manager)"
101
- case "$pm" in
102
- brew)
103
- brew install ripgrep
104
- ;;
105
- apt)
106
- sudo apt-get update && sudo apt-get install -y ripgrep
107
- ;;
108
- dnf)
109
- sudo dnf install -y ripgrep
110
- ;;
111
- yum)
112
- sudo yum install -y ripgrep
113
- ;;
114
- pacman)
115
- sudo pacman -Sy --noconfirm ripgrep
116
- ;;
117
- *)
118
- echo "未检测到可用包管理器,无法安装 rg" >&2
119
- return 1
120
- ;;
121
- esac
122
- }
123
-
124
- install_pnpm() {
125
- if command -v pnpm >/dev/null 2>&1; then
126
- return 0
127
- fi
128
-
129
- if command -v npm >/dev/null 2>&1; then
130
- npm install -g pnpm@latest
131
- elif command -v brew >/dev/null 2>&1; then
132
- brew install pnpm
133
- else
134
- echo "缺少 npm/brew,无法安装 pnpm" >&2
135
- return 1
136
- fi
137
- }
138
-
139
- persist_user_local_bin_path() {
140
- local line='export PATH="$HOME/.local/bin:$PATH"'
141
- local rc
142
- for rc in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.profile"; do
143
- if [[ -f "$rc" ]]; then
144
- if ! grep -F "$line" "$rc" >/dev/null 2>&1; then
145
- printf '\n%s\n' "$line" >>"$rc"
146
- fi
147
- fi
148
- done
149
- }
150
-
151
- expose_dx_globally() {
152
- local source_dx="$1"
153
- local target_dir target_path
154
-
155
- if [[ ! -x "$source_dx" ]]; then
156
- echo "dx 源可执行文件不存在:$source_dx" >&2
157
- return 1
158
- fi
159
-
160
- target_dir=""
161
- if [[ -w "/usr/local/bin" ]]; then
162
- target_dir="/usr/local/bin"
163
- elif [[ -w "/opt/homebrew/bin" ]]; then
164
- target_dir="/opt/homebrew/bin"
165
- else
166
- target_dir="$HOME/.local/bin"
167
- mkdir -p "$target_dir"
168
- if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
169
- export PATH="$HOME/.local/bin:$PATH"
170
- fi
171
- persist_user_local_bin_path
172
- fi
173
-
174
- target_path="$target_dir/dx"
175
- ln -sf "$source_dx" "$target_path"
176
- command -v dx >/dev/null 2>&1
177
- }
178
-
179
- ensure_agent_browser() {
180
- # 优先使用用户态 pnpm,减少全局权限问题。
181
- if command -v pnpm >/dev/null 2>&1; then
182
- pnpm add -g agent-browser@latest
183
- elif command -v npm >/dev/null 2>&1; then
184
- npm install -g agent-browser@latest
185
- elif command -v brew >/dev/null 2>&1; then
186
- brew install agent-browser
187
- else
188
- echo "缺少 npm/pnpm/brew,无法安装 agent-browser" >&2
189
- return 1
190
- fi
191
-
192
- if ! command -v agent-browser >/dev/null 2>&1; then
193
- local pnpm_bin npm_prefix
194
- pnpm_bin="$(pnpm bin -g 2>/dev/null || true)"
195
- npm_prefix="$(npm prefix -g 2>/dev/null || true)"
196
- echo "agent-browser 安装后仍不可用,请检查 PATH(pnpm: ${pnpm_bin:-N/A},npm: ${npm_prefix:-N/A}/bin)" >&2
197
- return 1
198
- fi
199
-
200
- if ! run_silent agent-browser install; then
201
- run_silent agent-browser install --with-deps || {
202
- echo "agent-browser Chromium 安装失败" >&2
203
- return 1
204
- }
205
- fi
206
- }
207
-
208
- force_dx() {
209
- local pnpm_bin dx_installed dx_cmd
210
- if ! install_pnpm; then
211
- DX_FORCE_OK=0
212
- DX_FORCE_MSG="pnpm 不可用,无法执行 dx 强制初始化"
213
- return 1
214
- fi
215
-
216
- if pnpm add -g @ranger1/dx@latest >/dev/null 2>&1; then
217
- pnpm_bin="$(pnpm bin -g 2>/dev/null || true)"
218
- dx_installed=""
219
- if [[ -n "$pnpm_bin" && -x "$pnpm_bin/dx" ]]; then
220
- dx_installed="$pnpm_bin/dx"
221
- elif command -v dx >/dev/null 2>&1; then
222
- dx_installed="$(command -v dx)"
223
- fi
224
-
225
- if [[ -z "$dx_installed" ]]; then
226
- DX_FORCE_OK=0
227
- DX_FORCE_MSG="dx 安装后未找到可执行文件(pnpm bin: ${pnpm_bin:-N/A})"
228
- return 1
229
- fi
230
-
231
- if ! expose_dx_globally "$dx_installed"; then
232
- DX_FORCE_OK=0
233
- DX_FORCE_MSG="dx 已安装但未能暴露为全局命令(pnpm bin: ${pnpm_bin:-N/A})"
234
- return 1
235
- fi
236
-
237
- dx_cmd="$(command -v dx || true)"
238
- if [[ -n "$dx_cmd" ]] && dx initial >/dev/null 2>&1; then
239
- DX_FORCE_OK=1
240
- DX_FORCE_MSG="已安装并暴露全局 dx(${dx_cmd}),并执行 dx initial"
241
- return 0
242
- fi
243
-
244
- DX_FORCE_OK=0
245
- DX_FORCE_MSG="dx 已暴露为全局命令但 dx initial 执行失败(dx: ${dx_cmd:-N/A})"
246
- return 1
247
- fi
248
-
249
- DX_FORCE_OK=0
250
- DX_FORCE_MSG="强制命令执行失败:pnpm add -g @ranger1/dx@latest"
251
- return 1
252
- }
253
-
254
- write_check_file() {
255
- local key="$1" ok="$2" ver="$3" msg="$4" file="$5"
256
- printf '%s|%s|%s|%s\n' "$key" "$ok" "$ver" "$msg" >"$file"
257
- }
258
-
259
- read_field() {
260
- local key="$1" field="$2"
261
- local f="$LAST_CHECK_DIR/${key}.res"
262
- if [[ ! -f "$f" ]]; then
263
- echo ""
264
- return 0
265
- fi
266
- awk -F'|' -v idx="$field" '{print $idx}' "$f"
267
- }
268
-
269
- check_ok() {
270
- local key="$1"
271
- [[ "$(read_field "$key" 2)" == "1" ]]
272
- }
273
-
274
- run_parallel_checks() {
275
- local round="$1"
276
- local dir="$CACHE_ROOT/round-${round}"
277
- mkdir -p "$dir"
278
-
279
- (
280
- if command -v python3 >/dev/null 2>&1; then
281
- write_check_file "python3" "1" "$(python3 --version 2>&1 | head -n1)" "ok" "$dir/python3.res"
282
- else
283
- write_check_file "python3" "0" "" "python3 未安装" "$dir/python3.res"
284
- fi
285
- ) &
286
-
287
- (
288
- if command -v python >/dev/null 2>&1; then
289
- local py_ver py_major
290
- py_ver="$(python --version 2>&1 | head -n1)"
291
- py_major="$(python -c 'import sys; print(sys.version_info[0])' 2>/dev/null || true)"
292
- if [[ "$py_major" == "3" ]]; then
293
- write_check_file "python_alias" "1" "$py_ver" "ok" "$dir/python_alias.res"
294
- else
295
- write_check_file "python_alias" "0" "$py_ver" "python 存在但不是 Python 3" "$dir/python_alias.res"
296
- fi
297
- else
298
- write_check_file "python_alias" "0" "" "python 别名不可用" "$dir/python_alias.res"
299
- fi
300
- ) &
301
-
302
- (
303
- if command -v pnpm >/dev/null 2>&1; then
304
- write_check_file "pnpm" "1" "pnpm $(pnpm --version 2>/dev/null | head -n1)" "ok" "$dir/pnpm.res"
305
- else
306
- write_check_file "pnpm" "0" "" "pnpm 未安装" "$dir/pnpm.res"
307
- fi
308
- ) &
309
-
310
- (
311
- if command -v dx >/dev/null 2>&1; then
312
- local v
313
- v="$(dx --version 2>/dev/null | head -n1 || true)"
314
- if [[ -z "$v" ]]; then
315
- v="$(dx -v 2>/dev/null | head -n1 || true)"
316
- fi
317
- write_check_file "dx" "1" "${v:-dx (版本未知)}" "ok" "$dir/dx.res"
318
- else
319
- write_check_file "dx" "0" "" "dx 未安装" "$dir/dx.res"
320
- fi
321
- ) &
322
-
323
- (
324
- if command -v agent-browser >/dev/null 2>&1; then
325
- write_check_file "agent_browser" "1" "$(agent-browser --version 2>/dev/null | head -n1)" "ok" "$dir/agent_browser.res"
326
- else
327
- write_check_file "agent_browser" "0" "" "agent-browser 未安装" "$dir/agent_browser.res"
328
- fi
329
- ) &
330
-
331
- (
332
- if command -v rg >/dev/null 2>&1; then
333
- write_check_file "rg" "1" "$(rg --version 2>/dev/null | head -n1)" "ok" "$dir/rg.res"
334
- else
335
- write_check_file "rg" "0" "" "rg 未安装" "$dir/rg.res"
336
- fi
337
- ) &
338
-
339
- wait
340
- LAST_CHECK_DIR="$dir"
341
- }
342
-
343
- all_good() {
344
- local keys="python3 python_alias pnpm dx agent_browser rg"
345
- local k
346
- for k in $keys; do
347
- if ! check_ok "$k"; then
348
- return 1
349
- fi
350
- done
351
- [[ "$DX_FORCE_OK" == "1" ]]
352
- }
353
-
354
- print_report() {
355
- local round="$1"
356
- echo
357
- echo "===== Doctor 报告(第 ${round} 轮)====="
358
- printf '%-14s | %-4s | %-40s | %s\n' "检查项" "状态" "版本" "说明"
359
- printf '%-14s-+-%-4s-+-%-40s-+-%s\n' "--------------" "----" "----------------------------------------" "------------------------------"
360
-
361
- local keys="python3 python_alias pnpm dx agent_browser rg"
362
- local k ok txt ver msg
363
- for k in $keys; do
364
- ok="$(read_field "$k" 2)"
365
- txt="FAIL"
366
- [[ "$ok" == "1" ]] && txt="PASS"
367
- ver="$(read_field "$k" 3)"
368
- msg="$(read_field "$k" 4)"
369
- printf '%-14s | %-4s | %-40s | %s\n' "$k" "$txt" "$ver" "$msg"
370
- done
371
-
372
- if [[ "$DX_FORCE_OK" == "1" ]]; then
373
- printf '%-14s | %-4s | %-40s | %s\n' "dx_force" "PASS" "@ranger1/dx@latest" "$DX_FORCE_MSG"
374
- else
375
- printf '%-14s | %-4s | %-40s | %s\n' "dx_force" "FAIL" "@ranger1/dx@latest" "$DX_FORCE_MSG"
376
- fi
377
-
378
- if command -v node >/dev/null 2>&1; then
379
- echo "node: $(node -v 2>/dev/null | head -n1)"
380
- fi
381
- if command -v npm >/dev/null 2>&1; then
382
- echo "npm: $(npm -v 2>/dev/null | head -n1)"
383
- fi
384
- }
385
-
386
- for round in $(seq 1 "$MAX_ROUNDS"); do
387
- echo "[doctor] 第 ${round}/${MAX_ROUNDS} 轮:并行检测"
388
- run_parallel_checks "$round"
389
-
390
- echo "[doctor] 第 ${round}/${MAX_ROUNDS} 轮:修复阶段"
391
-
392
- if ! check_ok "python3"; then
393
- echo "[doctor] 安装 python3"
394
- install_python3 || true
395
- fi
396
-
397
- if ! check_ok "python_alias"; then
398
- echo "[doctor] 建立 python -> python3 调用能力"
399
- ensure_python_alias || true
400
- fi
401
-
402
- if ! check_ok "rg"; then
403
- echo "[doctor] 安装 rg"
404
- install_rg || true
405
- fi
406
-
407
- if ! check_ok "agent_browser"; then
408
- echo "[doctor] 安装/升级 agent-browser 并安装 Chromium"
409
- ensure_agent_browser || true
410
- else
411
- echo "[doctor] agent-browser 已存在,执行升级与 Chromium 安装"
412
- ensure_agent_browser || true
413
- fi
414
-
415
- echo "[doctor] 强制执行 dx 安装与初始化"
416
- force_dx || true
417
-
418
- echo "[doctor] 第 ${round}/${MAX_ROUNDS} 轮:复检"
419
- run_parallel_checks "${round}-post"
420
- print_report "$round"
421
-
422
- if all_good; then
423
- echo "[doctor] 全部检查通过"
424
- exit 0
425
- fi
426
-
427
- done
428
-
429
- echo "[doctor] 达到最大轮次 ${MAX_ROUNDS},仍有未通过项"
430
- exit 1