@cocorograph/hub-agent 0.5.17 → 0.5.18

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/src/main.mjs +44 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocorograph/hub-agent",
3
- "version": "0.5.17",
3
+ "version": "0.5.18",
4
4
  "description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの tmux/pty を中継する。",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
package/src/main.mjs CHANGED
@@ -169,6 +169,40 @@ export async function startDaemon({ version, ptyModule } = {}) {
169
169
  const SESSION_EVENTS_DIR =
170
170
  process.env.COCKPIT_SESSION_EVENTS_DIR || "/tmp/cockpit_session_events"
171
171
 
172
+ /**
173
+ * `/tmp/cockpit_session_events/` 全 .json を読んで session_name → {event, at}
174
+ * の Map を返す (Phase 4: tmux.list_sessions レスポンスに含めて配信する用)。
175
+ *
176
+ * fs.watch 由来の `session.event` push はファイル変更時のみのため、frontend が
177
+ * 新規マウント (ハードリロード等) すると過去 event を取得できず CockpitStatusDot
178
+ * が全グレー表示になる問題があった。これを list 同梱で復元する。
179
+ */
180
+ async function readAllSessionEvents() {
181
+ const out = new Map()
182
+ let files
183
+ try {
184
+ files = await readdir(SESSION_EVENTS_DIR)
185
+ } catch {
186
+ return out
187
+ }
188
+ for (const f of files) {
189
+ if (!f.endsWith(".json")) continue
190
+ const sessionName = f.slice(0, -5)
191
+ try {
192
+ const text = await readFile(path.join(SESSION_EVENTS_DIR, f), "utf-8")
193
+ const data = JSON.parse(text)
194
+ if (!data || typeof data.event !== "string") continue
195
+ out.set(sessionName, {
196
+ event: data.event,
197
+ at: typeof data.at === "number" ? data.at : Date.now(),
198
+ })
199
+ } catch {
200
+ // 一時欠如 / parse 失敗は無視
201
+ }
202
+ }
203
+ return out
204
+ }
205
+
172
206
  /**
173
207
  * `/tmp/cockpit_session_events/<tmux_session>.json` を fs.watch して
174
208
  * UserPromptSubmit / Stop の event を `session.event` 型で Hub に push する。
@@ -437,10 +471,19 @@ async function dispatch(msg, ctx) {
437
471
  case "tmux.list_sessions": {
438
472
  try {
439
473
  const sessions = await listTmuxSessions({ plugins: ctx.plugins, logger: ctx.logger })
474
+ // 各 session の最新 hook event を /tmp/cockpit_session_events/ から読んで
475
+ // レスポンスに含める (Phase 4: ハードリロード時の lastEvent 復元用)。
476
+ // fs.watch 由来の session.event push は揮発性のため、frontend が新規
477
+ // マウントすると過去 event を取れず全グレー表示になる事象を解消する。
478
+ const lastEventByName = await readAllSessionEvents()
479
+ const enriched = sessions.map((s) => ({
480
+ ...s,
481
+ last_event: lastEventByName.get(s.name) || null,
482
+ }))
440
483
  ctx.client.send({
441
484
  type: "tmux.sessions",
442
485
  request_id: msg.request_id,
443
- sessions,
486
+ sessions: enriched,
444
487
  })
445
488
  } catch (err) {
446
489
  ctx.client.send({