@cocorograph/hub-agent 0.6.91 → 0.6.93
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.
- package/package.json +1 -1
- package/scripts/install.sh +24 -0
- package/src/enroll.mjs +14 -0
- package/src/main.mjs +15 -0
- package/src/tmux.mjs +31 -5
package/package.json
CHANGED
package/scripts/install.sh
CHANGED
|
@@ -678,6 +678,28 @@ do_install_service() {
|
|
|
678
678
|
color_ok "install-service 完了。ログ: ~/.hub/agent.log"
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
+
# enroll で bundle 配信された ~/.claude/scripts/setup_hub_ai.py を同期実行して
|
|
682
|
+
# ~/.claude/CLAUDE.md と ~/.claude/settings.json を初期化する。
|
|
683
|
+
#
|
|
684
|
+
# enroll.mjs 内でも kickSetupHubAi で best-effort spawn しているが、それは
|
|
685
|
+
# detached + stdio ignore で完了を待たないため、続く verify_setup が
|
|
686
|
+
# CLAUDE.md マーカー欠落を warn として拾ってしまう。install.sh では同期実行で
|
|
687
|
+
# verify を成功させる。setup_hub_ai 不在 (bundle 同期失敗) のときは色付き
|
|
688
|
+
# warn を出して継続。再実行時は step_* が冪等処理を返すだけで害なし。
|
|
689
|
+
do_bootstrap_hub_ai() {
|
|
690
|
+
local setup_script="$HOME/.claude/scripts/setup_hub_ai.py"
|
|
691
|
+
if [[ ! -f "$setup_script" ]]; then
|
|
692
|
+
color_warn "setup_hub_ai.py 不在 (bundle 同期が失敗した可能性)。スキップ"
|
|
693
|
+
return 0
|
|
694
|
+
fi
|
|
695
|
+
color_step "setup_hub_ai.py --silent を実行 (~/.claude/CLAUDE.md / settings.json 初期化)"
|
|
696
|
+
if python3 "$setup_script" --silent; then
|
|
697
|
+
color_ok "Hub AI bootstrap 完了"
|
|
698
|
+
else
|
|
699
|
+
color_warn "setup_hub_ai.py --silent が exit≠0 で終了 (継続)。手動で再実行: python3 $setup_script"
|
|
700
|
+
fi
|
|
701
|
+
}
|
|
702
|
+
|
|
681
703
|
# セットアップ最終検証。
|
|
682
704
|
# 「online には見えるがバンドル未配信」「サービス起動失敗」等の半完了状態を
|
|
683
705
|
# 検知してユーザーに次の手を案内する。返り値は 0 (errors > 0 でも継続)。
|
|
@@ -788,6 +810,8 @@ main() {
|
|
|
788
810
|
ensure_claude_code
|
|
789
811
|
step_header "enroll + bundle 同期"
|
|
790
812
|
do_enroll
|
|
813
|
+
step_header "Hub AI bootstrap (CLAUDE.md / hooks 初期化)"
|
|
814
|
+
do_bootstrap_hub_ai
|
|
791
815
|
step_header "OS サービス化"
|
|
792
816
|
do_install_service
|
|
793
817
|
step_header "最終検証"
|
package/src/enroll.mjs
CHANGED
|
@@ -83,6 +83,20 @@ export async function enroll(enrollmentToken, opts = {}) {
|
|
|
83
83
|
opts.logger?.warn?.({ err: err.message }, "hub bundle sync failed (enroll still ok)")
|
|
84
84
|
bundleResult = { error: err.message }
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
// bundle 同期で ~/.claude/scripts/setup_hub_ai.py が配置された直後に kick する。
|
|
88
|
+
// 設計穴: 初回 enroll では誰も setup_hub_ai.py を実行しないため、`step_claude_md`
|
|
89
|
+
// が走らず ~/.claude/CLAUDE.md がいつまでも作成されない事故があった
|
|
90
|
+
// (2026-06-17 toma 環境)。bundle 配信は scripts と claude_md_fragment.md は
|
|
91
|
+
// 含むが、CLAUDE.md と settings.json は含まないため、誰かが setup_hub_ai を
|
|
92
|
+
// 一度叩かないと self-bootstrap しない。enroll 直後に best-effort で 1 回叩く。
|
|
93
|
+
// 既存環境では step_claude_md がマーカー範囲を冪等更新するだけで害なし。
|
|
94
|
+
try {
|
|
95
|
+
const { kickSetupHubAi } = await import("./main.mjs")
|
|
96
|
+
kickSetupHubAi({ logger: opts.logger })
|
|
97
|
+
} catch (err) {
|
|
98
|
+
opts.logger?.warn?.({ err: err.message }, "kickSetupHubAi from enroll failed (ignored)")
|
|
99
|
+
}
|
|
86
100
|
}
|
|
87
101
|
|
|
88
102
|
return {
|
package/src/main.mjs
CHANGED
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
recoverTuiInput,
|
|
71
71
|
removeWorktree as removeWorktreeDir,
|
|
72
72
|
resumeWithMessage,
|
|
73
|
+
setSessionMouse,
|
|
73
74
|
setTmuxGlobalEnv,
|
|
74
75
|
setTuiEffort,
|
|
75
76
|
setTuiModel,
|
|
@@ -383,6 +384,13 @@ export async function startDaemon({ version, ptyModule, claudeSdk } = {}) {
|
|
|
383
384
|
|
|
384
385
|
await runHookBroadcast(plugins, "onAgentStart", ctx)
|
|
385
386
|
|
|
387
|
+
// 起動時 self-heal: 過去に CLAUDE.md / settings.json bootstrap を踏まずに使い始めた
|
|
388
|
+
// 既存端末(初回 enroll で setup_hub_ai を kick していなかったバージョン経由)でも、
|
|
389
|
+
// `hub-agent restart` だけで CLAUDE.md と hooks を自動修復できるようにする。
|
|
390
|
+
// 既に整っている環境では step_* がマーカー範囲を冪等更新するだけで害なし
|
|
391
|
+
// (detached + stdio ignore で daemon は妨げない)。WHY: 2026-06-17 toma 環境調査。
|
|
392
|
+
kickSetupHubAi({ logger })
|
|
393
|
+
|
|
386
394
|
// node-pty (Microsoft 公式) は macOS arm64 で PTY master fd を spawn ごとに leak し
|
|
387
395
|
// (kill/destroy でも解放されず)、kern.tty.ptmx_max=511 到達で「新規ターミナルが
|
|
388
396
|
// 開けない」障害を起こした (2026-06-16)。node 20/22/24 全てで再現。API 互換の保守
|
|
@@ -1215,6 +1223,13 @@ async function dispatch(msg, ctx) {
|
|
|
1215
1223
|
cols: msg.cols,
|
|
1216
1224
|
rows: msg.rows,
|
|
1217
1225
|
})
|
|
1226
|
+
// 接続端末の種別に応じて tmux mouse mode を出し分ける (スマホ=on /
|
|
1227
|
+
// デスクトップ=off)。boolean のときだけ上書きし、未指定 (旧フロント) は
|
|
1228
|
+
// createSession の既定値 (on) を尊重する。fire-and-forget で pty.ready を
|
|
1229
|
+
// 妨げない (失敗は setSessionMouse 内で warn 済み)。
|
|
1230
|
+
if (typeof msg.mouse === "boolean" && msg.session_name) {
|
|
1231
|
+
setSessionMouse(msg.session_name, msg.mouse, { logger: ctx.logger })
|
|
1232
|
+
}
|
|
1218
1233
|
ctx.client.send({
|
|
1219
1234
|
type: "pty.ready",
|
|
1220
1235
|
stream_id,
|
package/src/tmux.mjs
CHANGED
|
@@ -715,11 +715,16 @@ export async function createSession(name, cwd, opts = {}) {
|
|
|
715
715
|
// has-session が非 0 = セッション無し
|
|
716
716
|
}
|
|
717
717
|
await execFileP(tmuxBin(opts), ["new-session", "-d", "-s", name, "-c", resolvedCwd])
|
|
718
|
-
//
|
|
719
|
-
//
|
|
720
|
-
// session-scoped、`-t <session>` 指定で他 session への副作用なし。
|
|
721
|
-
//
|
|
722
|
-
//
|
|
718
|
+
// 既定では mouse mode を ON にする (スマホの touch swipe → SGR wheel escape を
|
|
719
|
+
// tmux が copy-mode スクロールとして拾えるようにするため)。tmux 2.1+ で `mouse`
|
|
720
|
+
// option は session-scoped、`-t <session>` 指定で他 session への副作用なし。
|
|
721
|
+
//
|
|
722
|
+
// ⚠️ ただしこれは「初期既定値」にすぎない。実際の値は接続してきた端末に応じて
|
|
723
|
+
// pty.attach 時に setSessionMouse() で上書きされる: デスクトップ attach は off
|
|
724
|
+
// (= マウスのドラッグを xterm のローカル選択にして、コピー奪取・button release
|
|
725
|
+
// 取りこぼしによる操作不能を防ぐ。0.5.11 で全 session を mouse on にしたことが
|
|
726
|
+
// デスクトップのドラッグ選択を壊した回帰の修正)。スマホ attach は on のまま。
|
|
727
|
+
// 旧フロント (mouse フィールド未送信) はこの既定値 on がそのまま使われる。
|
|
723
728
|
try {
|
|
724
729
|
await execFileP(tmuxBin(opts), ["set-option", "-t", name, "mouse", "on"])
|
|
725
730
|
} catch (err) {
|
|
@@ -764,6 +769,27 @@ export async function createSession(name, cwd, opts = {}) {
|
|
|
764
769
|
}
|
|
765
770
|
}
|
|
766
771
|
|
|
772
|
+
/**
|
|
773
|
+
* 指定 session の tmux mouse mode を on/off する。pty.attach 時に接続端末の
|
|
774
|
+
* 種別に応じて呼ぶ (デスクトップ=off / スマホ=on)。失敗してもセッションの
|
|
775
|
+
* 基本機能は動くので warn のみで握り潰す。
|
|
776
|
+
* @param {string} name session 名
|
|
777
|
+
* @param {boolean} on true=mouse on / false=mouse off
|
|
778
|
+
* @param {{logger?: any, tmuxBin?: string}} [opts]
|
|
779
|
+
*/
|
|
780
|
+
export async function setSessionMouse(name, on, opts = {}) {
|
|
781
|
+
if (!name) return
|
|
782
|
+
const value = on ? "on" : "off"
|
|
783
|
+
try {
|
|
784
|
+
await execFileP(tmuxBin(opts), ["set-option", "-t", name, "mouse", value])
|
|
785
|
+
} catch (err) {
|
|
786
|
+
opts.logger?.warn?.(
|
|
787
|
+
{ session: name, mouse: value, err: err?.message || String(err) },
|
|
788
|
+
"tmux set-option mouse failed",
|
|
789
|
+
)
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
767
793
|
/** session_id として安全な形だけ許可する (send-keys へ流すためコマンド注入を防ぐ)。
|
|
768
794
|
* Claude の session_id は UUID (ASCII 英数 + ハイフン) なので、それ以外は弾く。 */
|
|
769
795
|
export function isSafeSessionId(sessionId) {
|