@cocorograph/hub-agent 0.6.55 → 0.6.56

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 +40 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocorograph/hub-agent",
3
- "version": "0.6.55",
3
+ "version": "0.6.56",
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
@@ -711,6 +711,28 @@ async function readAllSessionEvents() {
711
711
  return out
712
712
  }
713
713
 
714
+ /**
715
+ * 単一 session の最新 session-event をファイル正本から読む。無ければ null。
716
+ * claude.tui.bind 時の `stop` 再配信 (取りこぼし回復) に使う。
717
+ */
718
+ async function readSessionEventFile(sessionName) {
719
+ if (!sessionName || /[/\\]/.test(sessionName)) return null
720
+ try {
721
+ const text = await readFile(
722
+ path.join(SESSION_EVENTS_DIR, `${sessionName}.json`),
723
+ "utf-8",
724
+ )
725
+ const data = JSON.parse(text)
726
+ if (!data || typeof data.event !== "string") return null
727
+ return {
728
+ event: data.event,
729
+ at: typeof data.at === "number" ? data.at : Date.now(),
730
+ }
731
+ } catch {
732
+ return null
733
+ }
734
+ }
735
+
714
736
  /**
715
737
  * `/tmp/cockpit_session_events/<tmux_session>.json` を fs.watch して
716
738
  * UserPromptSubmit / Stop の event を `session.event` 型で Hub に push する。
@@ -1436,6 +1458,24 @@ async function dispatch(msg, ctx) {
1436
1458
  skipped: !!rebind.skipped,
1437
1459
  error: rebind.ok ? undefined : rebind.error,
1438
1460
  })
1461
+ // 取りこぼし回復 (2026-06-07): 直近のターン境界が `stop` ならファイル正本から
1462
+ // 再配信する。fs.watch 由来の session.event push は揮発性 (WS 切断・remount 中の
1463
+ // broadcast は失われる) で、stop を取りこぼした frontend は三点リーダーが回り
1464
+ // 続ける。bind は TUI ビューのマウントごとに来るので、ここで最新 stop を返せば
1465
+ // 再表示時に必ずターン終了が伝わる。prompt_submit は再配信しない (stale な
1466
+ // 「処理中」を誤って点灯させないため。点灯は jsonl エコー / 実 hook が担う)。
1467
+ if (sessionName) {
1468
+ const lastEvent = await readSessionEventFile(sessionName)
1469
+ if (lastEvent && lastEvent.event === "stop") {
1470
+ ctx.client.send({
1471
+ type: "session.event",
1472
+ session_name: sessionName,
1473
+ event: lastEvent.event,
1474
+ at: lastEvent.at,
1475
+ replay: true,
1476
+ })
1477
+ }
1478
+ }
1439
1479
  } catch (err) {
1440
1480
  logger?.warn(
1441
1481
  { err: err?.message, sessionName, cwd },