openclacky 0.9.11 → 0.9.13

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.
data/scripts/install.sh CHANGED
@@ -99,19 +99,39 @@ detect_shell() {
99
99
  }
100
100
 
101
101
  # Network-aware installer source selection
102
- SLOW_THRESHOLD_MS=2500
103
- NETWORK_REGION="global"
102
+ SLOW_THRESHOLD_MS=5000
103
+ NETWORK_REGION="global" # "china" | "global" | "unknown"
104
104
  USE_CN_MIRRORS=false
105
- DEFAULT_RUBYGEMS_URL="https://rubygems.org"
105
+
106
+ # --- Upstream (global) defaults ---
106
107
  GITHUB_RAW_BASE_URL="https://raw.githubusercontent.com"
107
108
  HOMEBREW_INSTALL_SCRIPT_URL="${GITHUB_RAW_BASE_URL}/Homebrew/install/HEAD/install.sh"
108
109
  OPENCLACKY_INSTALL_SCRIPT_URL="${GITHUB_RAW_BASE_URL}/clacky-ai/openclacky/main/scripts/install.sh"
109
- TUNA_MIRROR_BASE_URL="https://mirrors.tuna.tsinghua.edu.cn"
110
- CN_CDN_BASE_URL="https://oss.1024code.com"
110
+ DEFAULT_RUBYGEMS_URL="https://rubygems.org"
111
+ DEFAULT_NPM_REGISTRY="https://registry.npmjs.org"
111
112
  DEFAULT_MISE_INSTALL_URL="https://mise.run"
113
+
114
+ CN_CDN_BASE_URL="https://oss.1024code.com" # reverse proxy for raw.githubusercontent.com
115
+
116
+ # --- CN source URLs ---
117
+ CN_HOMEBREW_INSTALL_SCRIPT_URL="${CN_CDN_BASE_URL}/Homebrew/install/HEAD/install.sh"
112
118
  CN_MISE_INSTALL_URL="${CN_CDN_BASE_URL}/mise.sh"
113
119
  CN_RUBY_PRECOMPILED_URL="${CN_CDN_BASE_URL}/ruby/ruby-{version}.{platform}.tar.gz"
120
+ CN_RUBYGEMS_URL="https://mirrors.aliyun.com/rubygems/"
121
+ CN_NPM_REGISTRY="https://registry.npmmirror.com"
122
+ CN_NODE_MIRROR_URL="https://cdn.npmmirror.com/binaries/node/"
123
+
124
+ # --- Homebrew CN mirrors (Aliyun) ---
125
+ CN_HOMEBREW_BREW_GIT_REMOTE="https://mirrors.aliyun.com/homebrew/brew.git"
126
+ CN_HOMEBREW_CORE_GIT_REMOTE="https://mirrors.aliyun.com/homebrew/homebrew-core.git"
127
+ CN_HOMEBREW_BOTTLE_DOMAIN="https://mirrors.aliyun.com/homebrew/homebrew-bottles"
128
+ CN_HOMEBREW_API_DOMAIN="https://mirrors.aliyun.com/homebrew-bottles/api"
129
+
130
+ # --- Active values (overridden by detect_network_region) ---
114
131
  MISE_INSTALL_URL="$DEFAULT_MISE_INSTALL_URL"
132
+ RUBYGEMS_INSTALL_URL="$DEFAULT_RUBYGEMS_URL"
133
+ NPM_REGISTRY_URL="$DEFAULT_NPM_REGISTRY"
134
+ NODE_MIRROR_URL="" # empty = mise default (nodejs.org)
115
135
  RUBY_VERSION_SPEC="ruby@3"
116
136
 
117
137
  # Probe a single URL; echoes the round-trip time in milliseconds, or "timeout".
@@ -174,62 +194,126 @@ _print_probe_result() {
174
194
  fi
175
195
  }
176
196
 
197
+ # Probe a URL up to MAX_RETRIES times; returns the first successful ms or "timeout".
198
+ _probe_url_with_retry() {
199
+ local url="$1"
200
+ local max_retries="${2:-2}"
201
+ local attempt result
202
+
203
+ for attempt in $(seq 1 "$max_retries"); do
204
+ result=$(_probe_url "$url")
205
+ if [ "$result" != "timeout" ] && ! _is_slow_or_unreachable "$result"; then
206
+ echo "$result"
207
+ return 0
208
+ fi
209
+ # keep last result for reporting
210
+ done
211
+ echo "$result"
212
+ }
213
+
177
214
  detect_network_region() {
178
215
  print_step "Network pre-flight check..."
216
+ echo ""
179
217
 
180
- local tuna_result cdn_result mise_result rubygems_result github_result
181
- local tuna_good=false
182
- local cdn_good=false
183
- local upstream_good=false
218
+ # -----------------------------------------------------------------------
219
+ # Step 1: Region detection — google.com vs baidu.com
220
+ # google reachable → global
221
+ # google unreachable + baidu reachable → china
222
+ # both unreachable → unknown (best-effort, fall through)
223
+ # -----------------------------------------------------------------------
224
+ print_info "Step 1: Detecting network region..."
225
+ local google_result baidu_result
226
+ google_result=$(_probe_url "https://www.google.com")
227
+ baidu_result=$(_probe_url "https://www.baidu.com")
228
+
229
+ _print_probe_result "google.com" "$google_result"
230
+ _print_probe_result "baidu.com" "$baidu_result"
231
+
232
+ local google_ok=false baidu_ok=false
233
+ ! _is_slow_or_unreachable "$google_result" && google_ok=true
234
+ ! _is_slow_or_unreachable "$baidu_result" && baidu_ok=true
235
+
236
+ if [ "$google_ok" = true ]; then
237
+ NETWORK_REGION="global"
238
+ print_success "Region: global (Google reachable)"
239
+ elif [ "$baidu_ok" = true ]; then
240
+ NETWORK_REGION="china"
241
+ print_success "Region: china (Baidu reachable, Google not)"
242
+ else
243
+ NETWORK_REGION="unknown"
244
+ print_warning "Region: unknown (both Google and Baidu unreachable)"
245
+ fi
246
+ echo ""
184
247
 
185
- tuna_result=$(_probe_url "$TUNA_MIRROR_BASE_URL")
186
- cdn_result=$(_probe_url "$CN_MISE_INSTALL_URL")
187
- mise_result=$(_probe_url "$DEFAULT_MISE_INSTALL_URL")
188
- rubygems_result=$(_probe_url "$DEFAULT_RUBYGEMS_URL")
189
- github_result=$(_probe_url "$GITHUB_RAW_BASE_URL")
248
+ # -----------------------------------------------------------------------
249
+ # Step 2: Probe region-specific sources (retry 2× to avoid false alarms)
250
+ # -----------------------------------------------------------------------
251
+ print_info "Step 2: Probing installation sources (up to 2 retries each)..."
190
252
 
191
- _print_probe_result "Tsinghua mirror" "$tuna_result"
192
- _print_probe_result "Clacky CDN" "$cdn_result"
193
- _print_probe_result "mise installer" "$mise_result"
194
- _print_probe_result "RubyGems" "$rubygems_result"
195
- _print_probe_result "GitHub raw content" "$github_result"
253
+ if [ "$NETWORK_REGION" = "china" ]; then
254
+ # CN sources: CDN (oss.1024code.com) + Aliyun + npmmirror
255
+ local cdn_result mirror_result
256
+ cdn_result=$(_probe_url_with_retry "$CN_MISE_INSTALL_URL")
257
+ mirror_result=$(_probe_url_with_retry "$CN_RUBYGEMS_URL")
196
258
 
197
- if ! _is_slow_or_unreachable "$tuna_result"; then
198
- tuna_good=true
199
- fi
259
+ _print_probe_result "Chinese CDN (mise/Ruby)" "$cdn_result"
260
+ _print_probe_result "CN mirror (gem/brew)" "$mirror_result"
200
261
 
201
- if ! _is_slow_or_unreachable "$cdn_result"; then
202
- cdn_good=true
203
- fi
262
+ local cdn_ok=false mirror_ok=false
263
+ ! _is_slow_or_unreachable "$cdn_result" && cdn_ok=true
264
+ ! _is_slow_or_unreachable "$mirror_result" && mirror_ok=true
204
265
 
205
- # "global" here means strategy fallback, not guaranteed global reachability.
206
- # Treat upstream as healthy if at least one core endpoint is reachable and fast enough.
207
- if ! _is_slow_or_unreachable "$mise_result" || \
208
- ! _is_slow_or_unreachable "$rubygems_result" || \
209
- ! _is_slow_or_unreachable "$github_result"; then
210
- upstream_good=true
211
- fi
266
+ # Step 3: warn on source failures, but do not abort
267
+ if [ "$cdn_ok" = false ]; then
268
+ print_warning "Chinese CDN is slow/unreachable. mise and Ruby precompiled binaries may fail."
269
+ fi
270
+ if [ "$mirror_ok" = false ]; then
271
+ print_warning "Aliyun mirror is slow/unreachable. gem/brew installs may be slow."
272
+ fi
273
+ if [ "$cdn_ok" = false ] && [ "$mirror_ok" = false ]; then
274
+ print_warning "All CN mirrors unreachable — falling back to global sources. Expect slow downloads."
275
+ fi
276
+
277
+ # Step 4: apply CN sources
278
+ if [ "$cdn_ok" = true ] || [ "$mirror_ok" = true ]; then
279
+ USE_CN_MIRRORS=true
280
+ MISE_INSTALL_URL="$CN_MISE_INSTALL_URL"
281
+ RUBYGEMS_INSTALL_URL="$CN_RUBYGEMS_URL"
282
+ NPM_REGISTRY_URL="$CN_NPM_REGISTRY"
283
+ NODE_MIRROR_URL="$CN_NODE_MIRROR_URL"
284
+ RUBY_VERSION_SPEC="ruby@3.4.8"
285
+ print_info "CN mirrors applied: CDN (mise/Ruby) + Aliyun (gem/brew) + npmmirror (npm/Node)"
286
+ else
287
+ USE_CN_MIRRORS=false
288
+ print_info "Falling back to global sources despite CN region detection."
289
+ fi
212
290
 
213
- if [ "$tuna_good" = true ] && [ "$cdn_good" = true ]; then
214
- NETWORK_REGION="china"
215
- USE_CN_MIRRORS=true
216
- MISE_INSTALL_URL="$CN_MISE_INSTALL_URL"
217
- RUBY_VERSION_SPEC="ruby@3.4.8"
218
- print_info "Using optimized installation sources for this network environment."
219
291
  else
220
- NETWORK_REGION="global"
292
+ # Global sources: GitHub / RubyGems / npmjs / mise.run
293
+ local github_result rubygems_result npm_result mise_result
294
+ github_result=$(_probe_url_with_retry "$GITHUB_RAW_BASE_URL")
295
+ rubygems_result=$(_probe_url_with_retry "$DEFAULT_RUBYGEMS_URL")
296
+ npm_result=$(_probe_url_with_retry "$DEFAULT_NPM_REGISTRY")
297
+ mise_result=$(_probe_url_with_retry "$DEFAULT_MISE_INSTALL_URL")
298
+
299
+ _print_probe_result "GitHub raw" "$github_result"
300
+ _print_probe_result "RubyGems" "$rubygems_result"
301
+ _print_probe_result "npmjs.com" "$npm_result"
302
+ _print_probe_result "mise.run" "$mise_result"
303
+
304
+ # Step 3: warn on individual source failures
305
+ _is_slow_or_unreachable "$github_result" && print_warning "GitHub is slow/unreachable. Homebrew and install script updates may fail."
306
+ _is_slow_or_unreachable "$rubygems_result" && print_warning "RubyGems is slow/unreachable. gem install may fail."
307
+ _is_slow_or_unreachable "$npm_result" && print_warning "npmjs.com is slow/unreachable. npm install may fail."
308
+ _is_slow_or_unreachable "$mise_result" && print_warning "mise.run is slow/unreachable. mise installation may fail."
309
+
221
310
  USE_CN_MIRRORS=false
222
311
  MISE_INSTALL_URL="$DEFAULT_MISE_INSTALL_URL"
312
+ RUBYGEMS_INSTALL_URL="$DEFAULT_RUBYGEMS_URL"
313
+ NPM_REGISTRY_URL="$DEFAULT_NPM_REGISTRY"
314
+ NODE_MIRROR_URL=""
223
315
  RUBY_VERSION_SPEC="ruby@3"
224
- print_info "Detected global network. Using default upstream sources."
225
- fi
226
-
227
- if [ "$tuna_good" = false ] || [ "$cdn_good" = false ]; then
228
- print_warning "Domestic mirrors are unavailable or too slow. Falling back to default upstream sources."
229
- fi
230
-
231
- if [ "$upstream_good" = false ]; then
232
- print_warning "Default upstream sources are also unreachable or too slow. Installation may fail; check your network, proxy, or VPN settings."
316
+ print_info "Using global upstream sources."
233
317
  fi
234
318
 
235
319
  echo ""
@@ -261,6 +345,122 @@ check_ruby() {
261
345
  fi
262
346
  }
263
347
 
348
+ # Configure CN mirrors permanently in config files so all subsequent tool
349
+ # invocations (gem, npm, mise) automatically use the right source.
350
+ # Called once after detect_network_region, only when USE_CN_MIRRORS=true.
351
+ restore_mirrors() {
352
+ print_step "Restoring original mirror settings..."
353
+
354
+ # --- gem: restore ~/.gemrc ---
355
+ local gemrc="$HOME/.gemrc"
356
+ local gemrc_bak="$HOME/.gemrc_clackybak"
357
+ if [ -f "$gemrc_bak" ]; then
358
+ mv "$gemrc_bak" "$gemrc"
359
+ print_success "~/.gemrc restored from backup"
360
+ elif [ -f "$gemrc" ]; then
361
+ rm "$gemrc"
362
+ print_success "~/.gemrc removed (gem will use default rubygems.org)"
363
+ else
364
+ print_info "~/.gemrc — nothing to restore"
365
+ fi
366
+
367
+ # --- npm: restore ~/.npmrc ---
368
+ local npmrc="$HOME/.npmrc"
369
+ local npmrc_bak="$HOME/.npmrc_clackybak"
370
+ if [ -f "$npmrc_bak" ]; then
371
+ mv "$npmrc_bak" "$npmrc"
372
+ print_success "~/.npmrc restored from backup"
373
+ elif [ -f "$npmrc" ]; then
374
+ rm "$npmrc"
375
+ print_success "~/.npmrc removed (npm will use default registry)"
376
+ else
377
+ print_info "~/.npmrc — nothing to restore"
378
+ fi
379
+
380
+ # --- mise: unset node.mirror_url ---
381
+ local mise_bin=""
382
+ if command_exists mise; then
383
+ mise_bin="mise"
384
+ elif [ -x "$HOME/.local/bin/mise" ]; then
385
+ mise_bin="$HOME/.local/bin/mise"
386
+ fi
387
+ if [ -n "$mise_bin" ]; then
388
+ "$mise_bin" settings unset node.mirror_url 2>/dev/null && \
389
+ print_success "mise node.mirror_url unset"
390
+ else
391
+ print_info "mise not found — node.mirror_url skipped"
392
+ fi
393
+
394
+ # --- Homebrew CN mirrors: remove from shell rc file ---
395
+ if [ -n "$SHELL_RC" ] && [ -f "$SHELL_RC" ] && grep -q "HOMEBREW_BOTTLE_DOMAIN" "$SHELL_RC" 2>/dev/null; then
396
+ # Remove the comment line and the three export lines added by the installer
397
+ sed -i.bak '/# Homebrew CN mirrors (added by openclacky installer)/d' "$SHELL_RC"
398
+ sed -i.bak '/HOMEBREW_BREW_GIT_REMOTE/d' "$SHELL_RC"
399
+ sed -i.bak '/HOMEBREW_CORE_GIT_REMOTE/d' "$SHELL_RC"
400
+ sed -i.bak '/HOMEBREW_BOTTLE_DOMAIN/d' "$SHELL_RC"
401
+ rm -f "${SHELL_RC}.bak"
402
+ unset HOMEBREW_BREW_GIT_REMOTE HOMEBREW_CORE_GIT_REMOTE HOMEBREW_BOTTLE_DOMAIN
403
+ print_success "Homebrew CN mirrors removed from $SHELL_RC"
404
+ else
405
+ print_info "Homebrew CN mirrors — nothing to restore"
406
+ fi
407
+
408
+ echo ""
409
+ print_success "Done. All mirror settings restored to original."
410
+ echo ""
411
+ }
412
+
413
+ configure_cn_mirrors() {
414
+ [ "$USE_CN_MIRRORS" = true ] || return 0
415
+
416
+ print_step "Configuring CN mirrors (permanent)..."
417
+
418
+ # --- gem: write ~/.gemrc ---
419
+ local gemrc="$HOME/.gemrc"
420
+ if [ -f "$gemrc" ] && grep -q "${CN_RUBYGEMS_URL}" "$gemrc" 2>/dev/null; then
421
+ # Already configured by us — leave it alone
422
+ print_success "gem source already set → ${CN_RUBYGEMS_URL} (~/.gemrc)"
423
+ else
424
+ # Existing file with different content — back it up then generate a clean one
425
+ if [ -f "$gemrc" ]; then
426
+ mv "$gemrc" "$HOME/.gemrc_clackybak"
427
+ print_info "Backed up existing ~/.gemrc → ~/.gemrc_clackybak"
428
+ fi
429
+ cat > "$gemrc" <<GEMRC
430
+ :sources:
431
+ - ${CN_RUBYGEMS_URL}
432
+ GEMRC
433
+ print_success "gem source → ${CN_RUBYGEMS_URL} (~/.gemrc)"
434
+ fi
435
+
436
+ # --- npm: write ~/.npmrc ---
437
+ local npmrc="$HOME/.npmrc"
438
+ local npmrc_bak="$HOME/.npmrc_clackybak"
439
+ if [ -f "$npmrc" ] && grep -q "${NPM_REGISTRY_URL}" "$npmrc" 2>/dev/null; then
440
+ # Already configured by us — leave it alone
441
+ print_success "npm registry already set → ${NPM_REGISTRY_URL} (~/.npmrc)"
442
+ else
443
+ # Back up existing file (once), then write clean config
444
+ if [ -f "$npmrc" ] && [ ! -f "$npmrc_bak" ]; then
445
+ cp "$npmrc" "$npmrc_bak"
446
+ print_info "Backed up existing ~/.npmrc → ~/.npmrc_clackybak"
447
+ fi
448
+ if command_exists npm; then
449
+ npm config set registry "$NPM_REGISTRY_URL" 2>/dev/null && \
450
+ print_success "npm registry → ${NPM_REGISTRY_URL} (~/.npmrc)"
451
+ else
452
+ echo "registry=${NPM_REGISTRY_URL}" >> "$npmrc"
453
+ print_success "npm registry → ${NPM_REGISTRY_URL} (~/.npmrc, pre-set)"
454
+ fi
455
+ fi
456
+
457
+ # --- mise Node mirror ---
458
+ # Applied inside install_mise_runtime() after mise binary is available.
459
+ # NODE_MIRROR_URL is already set; nothing to do here.
460
+
461
+ echo ""
462
+ }
463
+
264
464
  # Install via RubyGems
265
465
  install_via_gem() {
266
466
  print_step "Installing via RubyGems..."
@@ -320,9 +520,20 @@ install_mise_runtime() {
320
520
  else
321
521
  print_success "mise already installed"
322
522
  fi
523
+
524
+ # Apply CN Node mirror permanently — covers any future `mise install node` too.
525
+ if [ "$USE_CN_MIRRORS" = true ] && [ -n "$NODE_MIRROR_URL" ]; then
526
+ ~/.local/bin/mise settings node.mirror_url="$NODE_MIRROR_URL" 2>/dev/null || true
527
+ print_info "mise Node mirror → ${NODE_MIRROR_URL}"
528
+ fi
323
529
  }
324
530
 
325
531
  install_ruby_via_mise() {
532
+ if check_ruby; then
533
+ print_success "Ruby already installed and compatible — skipping Ruby installation"
534
+ return 0
535
+ fi
536
+
326
537
  print_info "Installing Ruby 3 via mise..."
327
538
 
328
539
  if [ "$USE_CN_MIRRORS" = true ]; then
@@ -334,7 +545,6 @@ install_ruby_via_mise() {
334
545
  fi
335
546
 
336
547
  if ~/.local/bin/mise use -g "$RUBY_VERSION_SPEC"; then
337
- # Reload mise in the current bash process
338
548
  eval "$(~/.local/bin/mise activate bash)"
339
549
  print_success "Ruby 3 installed successfully"
340
550
  else
@@ -348,33 +558,58 @@ install_macos_dependencies() {
348
558
  print_step "Installing macOS dependencies and Ruby..."
349
559
  echo ""
350
560
 
561
+ # Configure Homebrew CN mirrors before installing (CN mode only)
351
562
  if [ "$USE_CN_MIRRORS" = true ]; then
352
- print_info "Detected mainland/restricted network on macOS"
353
- print_info "Skipping Homebrew and build dependencies because Ruby will be installed from precompiled binaries"
354
- else
355
- # Install Homebrew (it will automatically install Xcode Command Line Tools if needed)
356
- print_info "Checking Homebrew installation..."
357
- if ! command_exists brew; then
358
- print_info "Installing Homebrew..."
359
- /bin/bash -c "$(curl -fsSL "$HOMEBREW_INSTALL_SCRIPT_URL")"
360
-
361
- # Add Homebrew to PATH
362
- echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc
363
- export PATH="/opt/homebrew/bin:$PATH"
364
-
365
- print_success "Homebrew installed successfully"
563
+ print_info "Configuring Homebrew CN mirrors..."
564
+ export HOMEBREW_INSTALL_FROM_API=1
565
+ export HOMEBREW_API_DOMAIN="$CN_HOMEBREW_API_DOMAIN"
566
+ export HOMEBREW_BREW_GIT_REMOTE="$CN_HOMEBREW_BREW_GIT_REMOTE"
567
+ export HOMEBREW_CORE_GIT_REMOTE="$CN_HOMEBREW_CORE_GIT_REMOTE"
568
+ export HOMEBREW_BOTTLE_DOMAIN="$CN_HOMEBREW_BOTTLE_DOMAIN"
569
+
570
+ # Persist to shell rc file
571
+ if ! grep -q "HOMEBREW_BOTTLE_DOMAIN" "$SHELL_RC" 2>/dev/null; then
572
+ {
573
+ echo ""
574
+ echo "# Homebrew CN mirrors (added by openclacky installer)"
575
+ echo "export HOMEBREW_INSTALL_FROM_API=1"
576
+ echo "export HOMEBREW_API_DOMAIN=\"${CN_HOMEBREW_API_DOMAIN}\""
577
+ echo "export HOMEBREW_BREW_GIT_REMOTE=\"${CN_HOMEBREW_BREW_GIT_REMOTE}\""
578
+ echo "export HOMEBREW_CORE_GIT_REMOTE=\"${CN_HOMEBREW_CORE_GIT_REMOTE}\""
579
+ echo "export HOMEBREW_BOTTLE_DOMAIN=\"${CN_HOMEBREW_BOTTLE_DOMAIN}\""
580
+ } >> "$SHELL_RC"
581
+ print_success "Homebrew CN mirrors written to $SHELL_RC"
366
582
  else
367
- print_success "Homebrew already installed"
583
+ print_success "Homebrew CN mirrors already configured in $SHELL_RC"
368
584
  fi
585
+ fi
369
586
 
370
- # Install build dependencies for the default upstream Ruby toolchain path
371
- print_info "Installing build dependencies..."
372
- if brew install openssl@3 libyaml gmp rust; then
373
- print_success "Build dependencies installed"
374
- else
375
- print_error "Failed to install build dependencies"
376
- return 1
587
+ # Install Homebrew (it will automatically install Xcode Command Line Tools if needed)
588
+ print_info "Checking Homebrew installation..."
589
+ if ! command_exists brew; then
590
+ print_info "Installing Homebrew..."
591
+ local brew_install_url="$HOMEBREW_INSTALL_SCRIPT_URL"
592
+ if [ "$USE_CN_MIRRORS" = true ]; then
593
+ brew_install_url="$CN_HOMEBREW_INSTALL_SCRIPT_URL"
377
594
  fi
595
+ /bin/bash -c "$(curl -fsSL "$brew_install_url")"
596
+
597
+ # Add Homebrew to PATH
598
+ echo 'export PATH="/opt/homebrew/bin:$PATH"' >> "$SHELL_RC"
599
+ export PATH="/opt/homebrew/bin:$PATH"
600
+
601
+ print_success "Homebrew installed successfully"
602
+ else
603
+ print_success "Homebrew already installed"
604
+ fi
605
+
606
+ # Install build dependencies
607
+ print_info "Installing build dependencies..."
608
+ if brew install openssl@3 libyaml gmp; then
609
+ print_success "Build dependencies installed"
610
+ else
611
+ print_error "Failed to install build dependencies"
612
+ return 1
378
613
  fi
379
614
 
380
615
  # Install mise for Ruby version management
@@ -404,9 +639,9 @@ install_ubuntu_dependencies() {
404
639
  echo ""
405
640
 
406
641
  if [ "$USE_CN_MIRRORS" = true ]; then
407
- print_info "Configuring apt mirror (Tsinghua)..."
642
+ print_info "Configuring apt mirror (Aliyun)..."
408
643
  local codename="${VERSION_CODENAME:-jammy}"
409
- local mirror_base="${TUNA_MIRROR_BASE_URL}/ubuntu/"
644
+ local mirror_base="https://mirrors.aliyun.com/ubuntu/"
410
645
  local common_components="main restricted universe multiverse"
411
646
  sudo tee /etc/apt/sources.list > /dev/null <<EOF
412
647
  deb ${mirror_base} ${codename} ${common_components}
@@ -430,7 +665,7 @@ EOF
430
665
 
431
666
  # Install build dependencies
432
667
  print_info "Installing build dependencies..."
433
- if sudo apt install -y build-essential rustc libssl-dev libyaml-dev zlib1g-dev libgmp-dev git; then
668
+ if sudo apt install -y build-essential libssl-dev libyaml-dev zlib1g-dev libgmp-dev git; then
434
669
  print_success "Build dependencies installed"
435
670
  else
436
671
  print_error "Failed to install build dependencies"
@@ -464,101 +699,6 @@ EOF
464
699
  }
465
700
 
466
701
  # Suggest Ruby installation
467
- suggest_ruby_installation() {
468
- print_step "Ruby Installation Options"
469
- echo ""
470
-
471
- if [ "$OS" = "macOS" ]; then
472
- print_info "Automatic Installation (Recommended)"
473
- echo " This script can automatically install Ruby and dependencies for you."
474
- echo " Uses mise - a fast, polyglot tool version manager."
475
- echo ""
476
- read -p "Would you like to install Ruby and dependencies automatically? [Y/n] " REPLY
477
- echo ""
478
- REPLY="${REPLY:-Y}"
479
- if [[ $REPLY =~ ^[Yy]$ ]]; then
480
- install_macos_dependencies
481
- return $?
482
- fi
483
- echo ""
484
- print_info "Manual Installation with mise:"
485
- echo " # Install Homebrew (it will install Xcode Command Line Tools automatically)"
486
- echo " /bin/bash -c \"\$(curl -fsSL ${HOMEBREW_INSTALL_SCRIPT_URL})\""
487
- echo ""
488
- echo " # Install dependencies"
489
- echo " brew install openssl@3 libyaml gmp rust"
490
- echo ""
491
- echo " # Install mise"
492
- echo " curl https://mise.run | sh"
493
- echo " echo 'eval \"\$(~/.local/bin/mise activate bash)\"' >> ~/.zshrc"
494
- echo ""
495
- echo " # Install Ruby 3"
496
- echo " mise use -g ruby@3"
497
-
498
- elif [ "$OS" = "Linux" ]; then
499
- if [ "$DISTRO" = "ubuntu" ] || [ "$DISTRO" = "debian" ]; then
500
- print_info "Automatic Installation (Recommended)"
501
- echo " This script can automatically install Ruby and dependencies for you."
502
- echo " Uses mise - a fast, polyglot tool version manager."
503
- echo ""
504
- read -p "Would you like to install Ruby and dependencies automatically? [Y/n] " REPLY
505
- echo ""
506
- REPLY="${REPLY:-Y}"
507
- if [[ $REPLY =~ ^[Yy]$ ]]; then
508
- install_ubuntu_dependencies
509
- return $?
510
- fi
511
- echo ""
512
- print_info "Manual Installation with mise (Ubuntu/Debian):"
513
- echo " # Update and install dependencies"
514
- echo " sudo apt update"
515
- echo " sudo apt install -y build-essential rustc libssl-dev libyaml-dev zlib1g-dev libgmp-dev git"
516
- echo ""
517
- echo " # Install mise"
518
- echo " curl https://mise.run | sh"
519
- echo " echo 'eval \"\$(~/.local/bin/mise activate bash)\"' >> ~/.bashrc"
520
- echo ""
521
- echo " # Install Ruby 3"
522
- echo " mise use -g ruby@3"
523
- else
524
- print_info "Manual Installation with mise (Other Linux):"
525
- echo " # Install build dependencies (adjust for your distribution)"
526
- echo " # Fedora/RHEL:"
527
- echo " sudo dnf install -y gcc make openssl-devel libyaml-devel zlib-devel gmp-devel git rust"
528
- echo ""
529
- echo " # Install mise"
530
- echo " curl https://mise.run | sh"
531
- echo " echo 'eval \"\$(~/.local/bin/mise activate bash)\"' >> ~/.bashrc"
532
- echo ""
533
- echo " # Install Ruby 3"
534
- echo " mise use -g ruby@3"
535
- fi
536
-
537
- elif [ "$OS" = "Windows" ]; then
538
- print_info "Windows Subsystem for Linux (WSL) Installation (Recommended)"
539
- echo " ${DISPLAY_NAME} requires a Unix-like environment. We recommend using WSL."
540
- echo ""
541
- echo " 1. Open PowerShell or Windows Command Prompt in administrator mode"
542
- echo " 2. Install WSL with Ubuntu 24.04:"
543
- echo ""
544
- echo " wsl --install --distribution Ubuntu-24.04"
545
- echo ""
546
- echo " 3. Restart your computer if prompted"
547
- echo " 4. Launch Ubuntu from the Start menu"
548
- echo " 5. Run this installation script again inside Ubuntu:"
549
- echo ""
550
- echo " curl -fsSL ${OPENCLACKY_INSTALL_SCRIPT_URL} | bash"
551
- echo ""
552
- print_info "Learn more about WSL: https://learn.microsoft.com/en-us/windows/wsl/install"
553
- fi
554
-
555
- echo ""
556
- print_info "After installing Ruby, run this script again or use:"
557
- echo " gem install openclacky"
558
- echo ""
559
- print_info "Learn more about mise: https://mise.jdx.dev"
560
- }
561
-
562
702
  # Parse command-line arguments.
563
703
  #
564
704
  # Supported flags:
@@ -579,6 +719,9 @@ parse_args() {
579
719
  --command=*)
580
720
  BRAND_COMMAND="${arg#--command=}"
581
721
  ;;
722
+ --restore-mirrors)
723
+ RESTORE_MIRRORS=true
724
+ ;;
582
725
  esac
583
726
  done
584
727
  # Global display name: brand name if provided, otherwise fall back to OpenClacky
@@ -636,6 +779,12 @@ WRAPPER
636
779
  main() {
637
780
  parse_args "$@"
638
781
 
782
+ # --restore-mirrors: undo CN mirror config and exit
783
+ if [ "${RESTORE_MIRRORS:-false}" = true ]; then
784
+ restore_mirrors
785
+ exit 0
786
+ fi
787
+
639
788
  echo ""
640
789
  echo "${DISPLAY_NAME} Installation"
641
790
  echo ""
@@ -643,43 +792,38 @@ main() {
643
792
  detect_os
644
793
  detect_shell
645
794
  detect_network_region
795
+ configure_cn_mirrors
646
796
 
647
- # Strategy 1: Check Ruby and install via gem
648
- if check_ruby; then
649
- if install_via_gem; then
650
- setup_brand
651
- show_post_install_info
652
- exit 0
797
+ # Install dependencies and Ruby (always run, handles already-installed gracefully)
798
+ if [ "$OS" = "macOS" ]; then
799
+ if ! install_macos_dependencies; then
800
+ print_error "Failed to install dependencies"
801
+ exit 1
653
802
  fi
654
- fi
655
-
656
- # Strategy 2: Install Ruby on macOS/Ubuntu or suggest options
657
- if [ "$OS" = "macOS" ] || [ "$OS" = "Linux" ]; then
658
- print_warning "Ruby not found or version too old"
659
- echo ""
660
- if suggest_ruby_installation; then
661
- # Try installing via gem after Ruby installation
662
- if install_via_gem; then
663
- setup_brand
664
- show_post_install_info
665
- exit 0
666
- else
667
- print_error "Failed to install ${DISPLAY_NAME}"
803
+ elif [ "$OS" = "Linux" ]; then
804
+ if [ "$DISTRO" = "ubuntu" ] || [ "$DISTRO" = "debian" ]; then
805
+ if ! install_ubuntu_dependencies; then
806
+ print_error "Failed to install dependencies"
668
807
  exit 1
669
808
  fi
670
809
  else
671
- # User declined or installation failed
672
- print_info "Ruby installation was not completed"
810
+ print_error "Unsupported Linux distribution: $DISTRO"
673
811
  print_info "Please install Ruby manually and run: gem install openclacky"
674
- print_info "For more information, visit: https://github.com/clacky-ai/openclacky"
675
812
  exit 1
676
813
  fi
677
814
  else
678
- print_error "Could not install ${DISPLAY_NAME} automatically"
679
- echo ""
680
- suggest_ruby_installation
681
- echo ""
682
- print_info "For more information, visit: https://github.com/clacky-ai/openclacky"
815
+ print_error "Unsupported OS: $OS"
816
+ print_info "Please install Ruby manually and run: gem install openclacky"
817
+ exit 1
818
+ fi
819
+
820
+ # Install via gem
821
+ if install_via_gem; then
822
+ setup_brand
823
+ show_post_install_info
824
+ exit 0
825
+ else
826
+ print_error "Failed to install ${DISPLAY_NAME}"
683
827
  exit 1
684
828
  fi
685
829
  }
@@ -689,7 +833,6 @@ main() {
689
833
  install_chrome_devtools_mcp() {
690
834
  print_step "Installing chrome-devtools-mcp..."
691
835
 
692
- # 尝试找到 npm;如果没有,通过 mise 安装 Node.js
693
836
  if ! command_exists npm; then
694
837
  local mise_bin=""
695
838
  if command_exists mise; then
@@ -704,6 +847,8 @@ install_chrome_devtools_mcp() {
704
847
  "$mise_bin" use -g node@22 > /dev/null 2>&1 || true
705
848
  eval "$("$mise_bin" activate bash 2>/dev/null)" 2>/dev/null || true
706
849
  fi
850
+ else
851
+ print_success "Node.js already installed — $(node --version 2>/dev/null)"
707
852
  fi
708
853
 
709
854
  if ! command_exists npm; then