@cocorograph/hub-agent 0.5.26 → 0.5.27

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 (2) hide show
  1. package/package.json +1 -1
  2. package/scripts/install.sh +153 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocorograph/hub-agent",
3
- "version": "0.5.26",
3
+ "version": "0.5.27",
4
4
  "description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの tmux/pty を中継する。",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -21,6 +21,13 @@
21
21
 
22
22
  set -euo pipefail
23
23
 
24
+ # brew の auto-update / hint 出力は初回 install で長時間化する原因の最大要因。
25
+ # 環境変数で抑止して 1 発完走率を上げる。最新 Formula が欲しいときは
26
+ # ユーザーが `brew update` を別途実行する前提。
27
+ export HOMEBREW_NO_AUTO_UPDATE=1
28
+ export HOMEBREW_NO_ENV_HINTS=1
29
+ export HOMEBREW_NO_INSTALL_CLEANUP=1
30
+
24
31
  # Node.js のサポート範囲ポリシー(Active LTS のみ)。
25
32
  # - 既存 node のメジャーが [MIN, MAX] に収まっていれば現状維持
26
33
  # - 範囲外なら NODE_DEFAULT_BREW_FORMULA (最新 Active LTS) にアップ / ダウングレード
@@ -42,6 +49,42 @@ color_err() { printf "\033[1;31m✗ %s\033[0m\n" "$1" >&2; }
42
49
 
43
50
  present() { command -v "$1" >/dev/null 2>&1; }
44
51
 
52
+ # step counter (main() で使う)。色は出すが詳細メッセージは関数内に任せる。
53
+ # STEP_TOTAL は main の冒頭で再設定する想定。
54
+ STEP_TOTAL=10
55
+ STEP_NUM=0
56
+ step_header() {
57
+ STEP_NUM=$((STEP_NUM + 1))
58
+ printf "\033[1;36m\n━━━ [%d/%d] %s ━━━\033[0m\n" "$STEP_NUM" "$STEP_TOTAL" "$1"
59
+ }
60
+
61
+ # 指定コマンドを最大 N 回まで指数 backoff で retry する。
62
+ # transient な network / brew / npm 失敗を耐える用途。
63
+ # 使い方: retry 3 brew install foo
64
+ # retry 3 npm install -g bar
65
+ #
66
+ # 重要: bash の `set -e` 下では `if cmd` パターンは cmd の戻り値で分岐するため、
67
+ # cmd 失敗時に script が exit しない (`set -e` の標準仕様)。
68
+ # retry 全体が失敗した時のみ呼び出し元が exit する。
69
+ retry() {
70
+ local max="$1"; shift
71
+ local i=1
72
+ local delay=2
73
+ while true; do
74
+ if "$@"; then
75
+ return 0
76
+ fi
77
+ if (( i >= max )); then
78
+ color_err "コマンドが ${max} 回連続失敗: $*"
79
+ return 1
80
+ fi
81
+ color_warn "失敗 (${i}/${max}) → ${delay}s 後に再試行: $*"
82
+ sleep "$delay"
83
+ i=$((i + 1))
84
+ delay=$((delay * 2))
85
+ done
86
+ }
87
+
45
88
  # 現在 PATH にある brew が、このユーザーで書き込み可能か判定する。
46
89
  # 「brew はあるが Cellar が他ユーザー所有で書き込み不可」というケースを検知して
47
90
  # user-local Homebrew にフォールバックするための判定関数。
@@ -89,7 +132,9 @@ ensure_brew() {
89
132
  _install_user_local_brew
90
133
  else
91
134
  color_step "Homebrew をシステムインストール"
92
- /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
135
+ # Homebrew 公式 install.sh をダウンロードして実行。
136
+ # curl は GitHub raw のレート制限や transient 502 を retry でカバーする。
137
+ retry 3 bash -c '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'
93
138
  # Apple Silicon の brew はデフォルト PATH に入らないので追加
94
139
  if [[ -d /opt/homebrew/bin ]]; then
95
140
  export PATH="/opt/homebrew/bin:$PATH"
@@ -107,7 +152,9 @@ _install_user_local_brew() {
107
152
  else
108
153
  color_step "Homebrew をユーザーローカルインストール (\$HOME/homebrew)"
109
154
  mkdir -p "$HOME/homebrew"
110
- curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C "$HOME/homebrew"
155
+ # GitHub tarball ダウンロード + tar 展開を 1 つの bash -c に包んで retry にかける。
156
+ # pipe 途中の curl 失敗を retry のスコープに収めるため。
157
+ retry 3 bash -c 'curl -fsSL https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C "$HOME/homebrew"'
111
158
  fi
112
159
  # PATH を user-local 優先で並べる(既存 /usr/local/bin/brew より先)
113
160
  export PATH="$HOME/homebrew/bin:$PATH"
@@ -398,14 +445,15 @@ ensure_pkg() {
398
445
  if present "$cmd"; then color_ok "$cmd already installed"; return 0; fi
399
446
  color_step "$cmd をインストール"
400
447
  if [[ "$(uname)" == "Darwin" ]]; then
401
- brew install "$brew_pkg"
448
+ # brew install は transient (network / hash mismatch / pour 失敗) を retry で吸収
449
+ retry 3 brew install "$brew_pkg"
402
450
  elif present apt-get; then
403
- sudo apt-get update -y
404
- sudo apt-get install -y "$apt_pkg"
451
+ retry 3 sudo apt-get update -y
452
+ retry 3 sudo apt-get install -y "$apt_pkg"
405
453
  elif present dnf; then
406
- sudo dnf install -y "$apt_pkg"
454
+ retry 3 sudo dnf install -y "$apt_pkg"
407
455
  elif present pacman; then
408
- sudo pacman -S --noconfirm "$apt_pkg"
456
+ retry 3 sudo pacman -S --noconfirm "$apt_pkg"
409
457
  else
410
458
  color_err "対応するパッケージマネージャ (brew/apt/dnf/pacman) が見つかりません。$cmd を手動で install してください"
411
459
  exit 1
@@ -417,7 +465,7 @@ ensure_pkg() {
417
465
  _install_node_lts_brew() {
418
466
  local formula="$NODE_DEFAULT_BREW_FORMULA"
419
467
  color_step "$formula (Active LTS) を install"
420
- brew install "$formula"
468
+ retry 3 brew install "$formula"
421
469
  # 既存無印 node が link されていれば外す(v26 current 等を退かす)
422
470
  if brew list node >/dev/null 2>&1; then
423
471
  color_step "既存 'node' formula を unlink ($formula を優先するため)"
@@ -465,15 +513,19 @@ ensure_node_version() {
465
513
  }
466
514
 
467
515
  ensure_global_install() {
516
+ # @latest 明示 + --force で npm cache stale 起因の「同 version 判定 skip」を回避。
517
+ # 過去事例: 0.5.24 が既に入っているマシンで `npm i -g xxx` が 0.5.26 に更新
518
+ # しない事象があった (npm の "no changes needed" 誤発火)。--force でこの判定を
519
+ # 飛ばし、@latest で確実に最新版を解決する。
468
520
  if present hub-agent; then
469
521
  local cur
470
522
  cur=$(hub-agent --version 2>/dev/null || echo "unknown")
471
523
  color_step "hub-agent (現在 $cur) を最新版にアップデート"
472
- npm install -g "$PACKAGE_NAME"
473
524
  else
474
525
  color_step "$PACKAGE_NAME を install"
475
- npm install -g "$PACKAGE_NAME"
476
526
  fi
527
+ retry 3 npm install -g "${PACKAGE_NAME}@latest" --force
528
+ hash -r 2>/dev/null || true
477
529
  color_ok "hub-agent $(hub-agent --version)"
478
530
  }
479
531
 
@@ -485,11 +537,14 @@ ensure_claude_code() {
485
537
  local cur
486
538
  cur=$(claude --version 2>/dev/null || echo "unknown")
487
539
  color_step "Claude Code (現在 $cur) を最新版にアップデート"
488
- npm install -g "$CLAUDE_CODE_PACKAGE" || color_warn "Claude Code upgrade に失敗 (既存版で継続)"
540
+ # claude Anthropic 配信。失敗しても既存版で継続 (warning のみ)
541
+ retry 2 npm install -g "${CLAUDE_CODE_PACKAGE}@latest" --force \
542
+ || color_warn "Claude Code upgrade に失敗 (既存版で継続)"
489
543
  else
490
544
  color_step "$CLAUDE_CODE_PACKAGE を install"
491
- npm install -g "$CLAUDE_CODE_PACKAGE"
545
+ retry 3 npm install -g "${CLAUDE_CODE_PACKAGE}@latest" --force
492
546
  fi
547
+ hash -r 2>/dev/null || true
493
548
  if present claude; then
494
549
  color_ok "claude $(claude --version 2>/dev/null || echo 'installed')"
495
550
  else
@@ -503,20 +558,88 @@ do_enroll() {
503
558
  color_warn " 手動で実行: hub-agent enroll <token> --hub-url ${HUB_AGENT_URL:-https://api.hub.cocorograph.com}"
504
559
  return 0
505
560
  fi
561
+ local hub_url="${HUB_AGENT_URL:-https://api.hub.cocorograph.com}"
562
+ # enroll は token が短命の可能性があるため retry は 1 回のみ。
563
+ # (transient network なら retry が効くが、token 期限切れだと回数を増やしても無駄)
506
564
  if [[ -f "$HOME/.hub/agent.json" ]]; then
507
565
  color_warn "~/.hub/agent.json が既にあります。--force で上書きします"
508
- hub-agent enroll "$HUB_AGENT_TOKEN" --hub-url "${HUB_AGENT_URL:-https://api.hub.cocorograph.com}" --force
566
+ retry 2 hub-agent enroll "$HUB_AGENT_TOKEN" --hub-url "$hub_url" --force
509
567
  else
510
- hub-agent enroll "$HUB_AGENT_TOKEN" --hub-url "${HUB_AGENT_URL:-https://api.hub.cocorograph.com}"
568
+ retry 2 hub-agent enroll "$HUB_AGENT_TOKEN" --hub-url "$hub_url"
569
+ fi
570
+
571
+ # enroll 内部の syncBundle 失敗は warning だけで握りつぶされる (enroll 自体は
572
+ # success 扱い) ため、ここで bundle 展開状況を verify する。
573
+ # CLAUDE.md の HUB-AI-RULES マーカーが入っていれば bundle 反映済みと判定。
574
+ if [[ ! -f "$HOME/.claude/CLAUDE.md" ]] \
575
+ || ! grep -q "BEGIN HUB-AI-RULES" "$HOME/.claude/CLAUDE.md" 2>/dev/null; then
576
+ color_warn "Hub AI bundle が ~/.claude に展開されていない可能性。sync-bundle を再試行"
577
+ if ! retry 2 hub-agent sync-bundle; then
578
+ color_warn "hub-agent sync-bundle が継続失敗。あとで手動実行してください:"
579
+ color_warn " hub-agent sync-bundle"
580
+ fi
511
581
  fi
512
582
  }
513
583
 
514
584
  do_install_service() {
515
585
  color_step "OS サービスとして自動起動を登録"
516
- hub-agent install-service
586
+ # install-service は launchctl bootout/bootstrap の transient で初回失敗する
587
+ # ことがある (既存 unit の残骸 + 同名 bootstrap 競合 等)。retry でカバー。
588
+ retry 2 hub-agent install-service
517
589
  color_ok "install-service 完了。ログ: ~/.hub/agent.log"
518
590
  }
519
591
 
592
+ # セットアップ最終検証。
593
+ # 「online には見えるがバンドル未配信」「サービス起動失敗」等の半完了状態を
594
+ # 検知してユーザーに次の手を案内する。返り値は 0 (errors > 0 でも継続)。
595
+ verify_setup() {
596
+ local errors=0
597
+
598
+ # 1. hub-agent CLI
599
+ if present hub-agent; then
600
+ color_ok "hub-agent CLI: $(hub-agent --version 2>/dev/null || echo 'installed')"
601
+ else
602
+ color_err "hub-agent コマンドが PATH に見つかりません"
603
+ errors=$((errors + 1))
604
+ fi
605
+
606
+ # 2. Claude Code (任意なので warn のみ)
607
+ if present claude; then
608
+ color_ok "Claude Code: $(claude --version 2>/dev/null || echo 'installed')"
609
+ else
610
+ color_warn "Claude Code (claude) コマンドが見つかりません (cockpit から claude を呼ぶ場合は必要)"
611
+ fi
612
+
613
+ # 3. Hub AI bundle 展開
614
+ if [[ -f "$HOME/.claude/CLAUDE.md" ]] \
615
+ && grep -q "BEGIN HUB-AI-RULES" "$HOME/.claude/CLAUDE.md" 2>/dev/null; then
616
+ color_ok "Hub AI bundle 展開済み (~/.claude/CLAUDE.md)"
617
+ else
618
+ color_warn "Hub AI bundle が ~/.claude に展開されていません"
619
+ color_warn " 手動再同期: hub-agent sync-bundle"
620
+ errors=$((errors + 1))
621
+ fi
622
+
623
+ # 4. OS サービス起動 (Darwin 限定の確認。Linux は systemctl --user で別途)
624
+ if [[ "$(uname)" == "Darwin" ]]; then
625
+ if launchctl list 2>/dev/null | grep -q "co.cocorograph.hub-agent"; then
626
+ color_ok "launchd service 起動中 (co.cocorograph.hub-agent)"
627
+ else
628
+ color_warn "launchd service が見つかりません"
629
+ color_warn " 手動起動: hub-agent install-service"
630
+ errors=$((errors + 1))
631
+ fi
632
+ fi
633
+
634
+ if (( errors > 0 )); then
635
+ color_warn ""
636
+ color_warn "${errors} 件の不整合を検出。Hub UI で agent が online でない場合は以下を試してください:"
637
+ color_warn " hub-agent restart # サービス再起動"
638
+ color_warn " hub-agent sync-bundle # bundle 再配信"
639
+ color_warn " tail -20 ~/.hub/agent.log # 詳細ログ"
640
+ fi
641
+ }
642
+
520
643
  macos_perm_guidance() {
521
644
  [[ "$(uname)" != "Darwin" ]] && return 0
522
645
  # 現在 PATH 上の node 実体パスを案内に埋め込む(フルディスクアクセス登録時に役立つ)
@@ -544,19 +667,34 @@ EOF
544
667
 
545
668
  main() {
546
669
  color_step "hub-agent ワンライナーセットアップを開始"
670
+ STEP_TOTAL=10
671
+ STEP_NUM=0
672
+
673
+ step_header "Homebrew"
547
674
  ensure_brew
675
+ step_header "tmux"
548
676
  ensure_pkg tmux tmux tmux
677
+ step_header "Node.js (Active LTS)"
549
678
  ensure_node_version
679
+ step_header "npm global prefix"
550
680
  ensure_npm_user_prefix
551
681
  # ensure_node_version 直後だと brew link でシェルの command hash がズレている
552
682
  # 場合があるため、prefix 設定後にまとめて TLS pre-flight check + 自動 fallback
553
683
  # を行う。失敗時はガイダンス付きで exit するので、後段の npm install で TLS
554
684
  # エラーを再度浴びる経路はカットされる。
685
+ step_header "Node TLS pre-flight"
555
686
  ensure_node_tls_works
687
+ step_header "hub-agent install"
556
688
  ensure_global_install
689
+ step_header "Claude Code install"
557
690
  ensure_claude_code
691
+ step_header "enroll + bundle 同期"
558
692
  do_enroll
693
+ step_header "OS サービス化"
559
694
  do_install_service
695
+ step_header "最終検証"
696
+ verify_setup
697
+
560
698
  echo ""
561
699
  color_ok "セットアップ完了。Hub UI で online 表示を確認してください"
562
700
  echo " https://hub.cocorograph.com/user/cockpit/agents"