@cocorograph/hub-agent 0.8.24 → 0.8.25
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/README.md +13 -12
- package/bin/hub-agent.mjs +7 -37
- package/package.json +2 -5
- package/scripts/install.sh +5 -5
- package/src/claude-stream-bridge.mjs +2 -3
- package/src/codex-stream-bridge.mjs +1 -1
- package/src/hooks.mjs +0 -17
- package/src/main.mjs +91 -291
- package/src/plugin-loader.mjs +49 -4
- package/src/plugin-uninstall.mjs +61 -0
- package/src/tmux.mjs +4 -32
- package/src/ws-client.mjs +19 -89
- package/plugins/10-tailscale-remote/README.md +0 -71
- package/plugins/10-tailscale-remote/config.example.json +0 -6
- package/plugins/10-tailscale-remote/plugin.mjs +0 -99
- package/scripts/fix-node-pty-perms.mjs +0 -89
- package/src/plugin-install.mjs +0 -111
- package/src/pty-bridge.mjs +0 -510
package/README.md
CHANGED
|
@@ -62,9 +62,7 @@ hub-agent stop # 停止方法のヒント表示
|
|
|
62
62
|
hub-agent install-service [--bin PATH]
|
|
63
63
|
hub-agent uninstall-service
|
|
64
64
|
hub-agent plugins list # ~/.hub/plugins/ から読み込み済プラグイン
|
|
65
|
-
hub-agent plugins
|
|
66
|
-
hub-agent plugins install <name> [--force]
|
|
67
|
-
hub-agent plugins uninstall <name>
|
|
65
|
+
hub-agent plugins uninstall <name> # ~/.hub/plugins/<prio>-<name>/ を削除
|
|
68
66
|
```
|
|
69
67
|
|
|
70
68
|
## 設定ファイル
|
|
@@ -86,7 +84,8 @@ hub-agent/
|
|
|
86
84
|
│ ├── config.mjs # ~/.hub/agent.json 管理
|
|
87
85
|
│ ├── enroll.mjs # enrollment フロー
|
|
88
86
|
│ ├── ws-client.mjs # outbound WSS + reconnect with jitter
|
|
89
|
-
│ ├──
|
|
87
|
+
│ ├── claude-stream-bridge.mjs # Claude Agent SDK チャット中継
|
|
88
|
+
│ ├── codex-stream-bridge.mjs # Codex app-server チャット中継
|
|
90
89
|
│ ├── tmux.mjs # tmux exec/list/create/kill
|
|
91
90
|
│ ├── state.mjs # session status / context_pct 検知
|
|
92
91
|
│ ├── skills.mjs # ~/.claude/skills 集計
|
|
@@ -98,7 +97,8 @@ hub-agent/
|
|
|
98
97
|
│ ├── co.cocorograph.hub-agent.plist
|
|
99
98
|
│ └── hub-agent.service
|
|
100
99
|
├── scripts/
|
|
101
|
-
│
|
|
100
|
+
│ ├── install.sh # ワンライナーセットアップ (macOS / Linux / WSL)
|
|
101
|
+
│ └── install.ps1 # Windows (WSL2 導入 + Task Scheduler 登録)
|
|
102
102
|
└── test/
|
|
103
103
|
```
|
|
104
104
|
|
|
@@ -107,21 +107,22 @@ hub-agent/
|
|
|
107
107
|
- [x] Sprint A: 仕様書 (Hub knowledge id=6080)
|
|
108
108
|
- [x] Sprint B: Hub 側 enrollment API + WS endpoint 雛形
|
|
109
109
|
- [x] Sprint C: 本リポジトリの雛形 + outbound WSS + hook system
|
|
110
|
-
- [x] Sprint D: pty bridge
|
|
111
110
|
- [x] Sprint E: tmux exec/list/create/kill 移植 + auto list UI
|
|
112
111
|
- [x] Sprint F: Hub Browser↔Agent multiplex 中継
|
|
113
112
|
- [x] Sprint G: Hub frontend /user/cockpit/{agents,terminal} ページ
|
|
114
113
|
- [x] Sprint H: skills / state dot / usage badge リレー
|
|
115
114
|
- [x] Sprint I: 接続復旧 (jitter + force reconnect + Celery stale 検知)
|
|
116
115
|
- [x] Sprint J: 本リポジトリ publish 準備 + launchd/systemd 連携
|
|
117
|
-
- [x] Sprint K: remote-ops プラグイン例 (`plugins/10-tailscale-remote/`)
|
|
118
116
|
|
|
119
|
-
##
|
|
117
|
+
## プラグイン
|
|
120
118
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
プラグインは利用者が `~/.hub/plugins/<prio>-<name>/plugin.mjs` を自分で置く運用です。
|
|
120
|
+
置けば `plugins list` から読み込まれ、`plugins uninstall <prio>-<name>` で削除できます。
|
|
121
|
+
|
|
122
|
+
リポジトリ同梱の example プラグインはありません。唯一同梱していた
|
|
123
|
+
`plugins/10-tailscale-remote/` は pty spawn を横取りするプラグインで、pty 中継の撤去と
|
|
124
|
+
同時に削除しました。同梱 example が 0 件になったため、それを配る `plugins examples` /
|
|
125
|
+
`plugins install` と `package.json` の `files` の `plugins/` も外しています。
|
|
125
126
|
|
|
126
127
|
## ライセンス
|
|
127
128
|
|
package/bin/hub-agent.mjs
CHANGED
|
@@ -34,12 +34,8 @@ if (!process.env.LC_ALL) process.env.LC_ALL = "C.UTF-8"
|
|
|
34
34
|
import { hasConfig, readConfig } from "../src/config.mjs"
|
|
35
35
|
import { enroll } from "../src/enroll.mjs"
|
|
36
36
|
import { resolveSyncTargets, syncBundleTargets } from "../src/hub-bundle.mjs"
|
|
37
|
-
import {
|
|
38
|
-
installPlugin,
|
|
39
|
-
listInstallableExamples,
|
|
40
|
-
uninstallPlugin,
|
|
41
|
-
} from "../src/plugin-install.mjs"
|
|
42
37
|
import { loadPlugins } from "../src/plugin-loader.mjs"
|
|
38
|
+
import { uninstallPlugin } from "../src/plugin-uninstall.mjs"
|
|
43
39
|
import {
|
|
44
40
|
installService,
|
|
45
41
|
restartService,
|
|
@@ -264,6 +260,11 @@ program
|
|
|
264
260
|
}
|
|
265
261
|
})
|
|
266
262
|
|
|
263
|
+
// プラグインは利用者が `~/.hub/plugins/<prio>-<name>/` へ自分で配置する運用なので、
|
|
264
|
+
// CLI が提供するのは利用者配置分の管理 (list / uninstall) だけ。リポ同梱 example を配る
|
|
265
|
+
// `examples` / `install` は、唯一の example (`plugins/10-tailscale-remote/`) が pty spawn を
|
|
266
|
+
// 横取りするプラグインで pty 撤去と同時に削除され、同梱 example が 0 件になったため撤去した
|
|
267
|
+
// (あわせて package.json の files から `plugins/` を外している)。
|
|
267
268
|
const plugins = program.command("plugins").description("プラグイン管理")
|
|
268
269
|
plugins
|
|
269
270
|
.command("list")
|
|
@@ -279,40 +280,9 @@ plugins
|
|
|
279
280
|
}
|
|
280
281
|
})
|
|
281
282
|
|
|
282
|
-
plugins
|
|
283
|
-
.command("examples")
|
|
284
|
-
.description("リポ同梱の install 可能 example プラグイン一覧")
|
|
285
|
-
.action(async () => {
|
|
286
|
-
const list = await listInstallableExamples()
|
|
287
|
-
if (list.length === 0) {
|
|
288
|
-
console.log("(no examples bundled)")
|
|
289
|
-
return
|
|
290
|
-
}
|
|
291
|
-
for (const name of list) {
|
|
292
|
-
console.log(`- ${name}`)
|
|
293
|
-
}
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
plugins
|
|
297
|
-
.command("install <name>")
|
|
298
|
-
.description("repo plugins/<name>/ を ~/.hub/plugins/<name>/ にコピー (config.json は温存)")
|
|
299
|
-
.option("--force", "既存ディレクトリを上書きする")
|
|
300
|
-
.action(async (name, opts) => {
|
|
301
|
-
try {
|
|
302
|
-
const r = await installPlugin(name, { force: !!opts.force })
|
|
303
|
-
console.log(`installed: ${r.dest}`)
|
|
304
|
-
console.log("次のステップ:")
|
|
305
|
-
console.log(` $EDITOR ${r.dest}/config.json # 既存なら温存、新規なら example をコピー`)
|
|
306
|
-
console.log(` hub-agent restart (launchctl kickstart / systemctl restart)`)
|
|
307
|
-
} catch (err) {
|
|
308
|
-
console.error(`plugins install failed: ${err.message}`)
|
|
309
|
-
process.exit(1)
|
|
310
|
-
}
|
|
311
|
-
})
|
|
312
|
-
|
|
313
283
|
plugins
|
|
314
284
|
.command("uninstall <name>")
|
|
315
|
-
.description("~/.hub/plugins/<name>/
|
|
285
|
+
.description("~/.hub/plugins/<prio>-<name>/ を削除する")
|
|
316
286
|
.action(async (name) => {
|
|
317
287
|
try {
|
|
318
288
|
const r = await uninstallPlugin(name)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocorograph/hub-agent",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの
|
|
3
|
+
"version": "0.8.25",
|
|
4
|
+
"description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの Claude / Codex チャットと tmux セッションを中継する。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"private": false,
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"start": "node bin/hub-agent.mjs start",
|
|
21
21
|
"test": "node --test test/*.test.mjs",
|
|
22
|
-
"postinstall": "node scripts/fix-node-pty-perms.mjs",
|
|
23
22
|
"check:publish-on-main": "node scripts/check-publish-on-main.mjs",
|
|
24
23
|
"prepublishOnly": "node scripts/check-publish-on-main.mjs && npm test"
|
|
25
24
|
},
|
|
@@ -28,13 +27,11 @@
|
|
|
28
27
|
"src/",
|
|
29
28
|
"scripts/",
|
|
30
29
|
"templates/",
|
|
31
|
-
"plugins/",
|
|
32
30
|
"README.md",
|
|
33
31
|
"LICENSE"
|
|
34
32
|
],
|
|
35
33
|
"dependencies": {
|
|
36
34
|
"@anthropic-ai/claude-agent-sdk": "^0.3.158",
|
|
37
|
-
"@lydell/node-pty": "1.2.0-beta.12",
|
|
38
35
|
"commander": "^12.1.0",
|
|
39
36
|
"pino": "^9.0.0",
|
|
40
37
|
"ws": "^8.18.0"
|
package/scripts/install.sh
CHANGED
|
@@ -518,10 +518,10 @@ _install_node_lts_linux() {
|
|
|
518
518
|
}
|
|
519
519
|
|
|
520
520
|
# ネイティブアドオンのビルドに必要な make / g++ / python3 を導入する。
|
|
521
|
-
#
|
|
522
|
-
#
|
|
523
|
-
#
|
|
524
|
-
#
|
|
521
|
+
# 現在の依存はすべて純 JS で通常は native ビルド不要だが、optional な native 依存
|
|
522
|
+
# (ws の bufferutil 等) が prebuild なしで拾われると node-gyp rebuild にフォールバック
|
|
523
|
+
# する。クリーンな Ubuntu には build-essential が無く `gyp ERR! not found: make` で
|
|
524
|
+
# 失敗する (WSL クリーン Ubuntu で発覚) ため保険で導入する。
|
|
525
525
|
# macOS は Xcode CLT 前提なので何もしない。
|
|
526
526
|
ensure_build_tools() {
|
|
527
527
|
[[ "$(uname)" == "Darwin" ]] && return 0
|
|
@@ -812,7 +812,7 @@ macos_perm_guidance() {
|
|
|
812
812
|
cat <<EOF
|
|
813
813
|
|
|
814
814
|
📣 macOS の権限ダイアログについて
|
|
815
|
-
hub-agent は tmux/
|
|
815
|
+
hub-agent は tmux セッションとローカルの CLI (Claude / Codex) を中継するため、初回起動時に macOS から
|
|
816
816
|
「node がローカルネットワーク上の機器を検出することを求めています」
|
|
817
817
|
「node がアクセシビリティを制御することを求めています」
|
|
818
818
|
「node がほかのアプリからのデータへのアクセス権を求めています」
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
* - これは Claude CLI の `claude --resume <id> -p "<msg>"` を毎ターン叩くのと同じ
|
|
16
16
|
* モデルで、SDK の挙動と素直に噛み合う
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
* 受け持つ。テスト時は SDK を `{ query }` shape で stub 注入する。
|
|
18
|
+
* `claude.*` 系メッセージを受け持つ。テスト時は SDK を `{ query }` shape で stub 注入する。
|
|
20
19
|
*/
|
|
21
20
|
import { EventEmitter } from "node:events"
|
|
22
21
|
import { randomUUID } from "node:crypto"
|
|
@@ -2427,7 +2426,7 @@ export class ClaudeStreamBridge extends EventEmitter {
|
|
|
2427
2426
|
/**
|
|
2428
2427
|
* 指定 cwd / session_id に紐づく SDK セッションを**即停止**する (T04784 TUI bind 用)。
|
|
2429
2428
|
*
|
|
2430
|
-
* TUI モードに切り替えた session
|
|
2429
|
+
* TUI モードに切り替えた session は tmux ペインの対話 claude が write を担うため、
|
|
2431
2430
|
* SDK セッションを生かしたままだと同一 cwd の jsonl を二重ホストして競合する
|
|
2432
2431
|
* (DESIGN.md C7)。soft-detach (7 日 resident) では止まらないので、ここで明示 close する。
|
|
2433
2432
|
*
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* claude.input → input() (idle は turn/start、生成中は次ターン FIFO)
|
|
12
12
|
* claude.interrupt → interrupt() (turn/interrupt)
|
|
13
13
|
* claude.detach → detach() (TTL 付き graceful close)
|
|
14
|
-
* (codex 固有) → keepalive() (
|
|
14
|
+
* (codex 固有) → keepalive() (閲覧中の生存シグナル)
|
|
15
15
|
* claude.permission.reply → permissionReply() (client.respond/respondError)
|
|
16
16
|
* claude.event (生 SDK イベント素通し) → 'event' (生 notification 素通し、同じ思想)
|
|
17
17
|
* claude.permission.request → 'permission' (承認/入力要求の生 method+params 素通し)
|
package/src/hooks.mjs
CHANGED
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
export const HOOK_NAMES = Object.freeze([
|
|
18
18
|
"onAgentStart",
|
|
19
19
|
"onAgentStop",
|
|
20
|
-
"interceptPtySpawn",
|
|
21
20
|
"interceptTmuxExec",
|
|
22
21
|
"interceptSessionCreate",
|
|
23
22
|
"interceptSessionKill",
|
|
@@ -26,21 +25,6 @@ export const HOOK_NAMES = Object.freeze([
|
|
|
26
25
|
"transformStatusDetection",
|
|
27
26
|
])
|
|
28
27
|
|
|
29
|
-
/**
|
|
30
|
-
* @typedef {Object} PtySpawnArgs
|
|
31
|
-
* @property {string} sessionName
|
|
32
|
-
* @property {number} cols
|
|
33
|
-
* @property {number} rows
|
|
34
|
-
* @property {Record<string, string>} env
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @typedef {Object} PtySpawnDecision
|
|
39
|
-
* @property {string} command
|
|
40
|
-
* @property {string[]} args
|
|
41
|
-
* @property {Record<string, string>} [env]
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
28
|
/**
|
|
45
29
|
* @typedef {Object} TmuxExecArgs
|
|
46
30
|
* @property {string[]} args
|
|
@@ -60,7 +44,6 @@ export const HOOK_NAMES = Object.freeze([
|
|
|
60
44
|
* @property {{
|
|
61
45
|
* onAgentStart?: (ctx: HookContext) => Promise<void>,
|
|
62
46
|
* onAgentStop?: (ctx: HookContext) => Promise<void>,
|
|
63
|
-
* interceptPtySpawn?: (ctx: HookContext & PtySpawnArgs) => Promise<PtySpawnDecision | null>,
|
|
64
47
|
* interceptTmuxExec?: (ctx: HookContext & TmuxExecArgs) => Promise<TmuxExecDecision | null>,
|
|
65
48
|
* }} hooks
|
|
66
49
|
*/
|