@cocorograph/hub-agent 0.8.7 → 0.8.8

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 +26 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocorograph/hub-agent",
3
- "version": "0.8.7",
3
+ "version": "0.8.8",
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
@@ -1811,6 +1811,7 @@ export async function readAllSessionLastTexts(
1811
1811
  const snap = getSnap(s.name)
1812
1812
  if (!snap || snap.cli_kind !== "claude") return
1813
1813
  let sessionId = snap.context_session_id
1814
+ let usedFallback = false
1814
1815
  // hub-agent 再起動で in-memory の TUI bind が消えると、state loop の snapshot は
1815
1816
  // `unbound:<session>` へ落ちる。一方、Claude bridge の warm/live session は cwd
1816
1817
  // から同じ会話 ID を復元できる。ここでフォールバックしないと、再起動後に全行の
@@ -1820,14 +1821,37 @@ export async function readAllSessionLastTexts(
1820
1821
  // 危険値の場合だけ使う。fallback も同じ containment 検査を通してから path 化する。
1821
1822
  if (!isSafeSessionIdForPath(sessionId) && resolveFallbackSessionId) {
1822
1823
  sessionId = resolveFallbackSessionId(s)
1824
+ usedFallback = true
1823
1825
  }
1824
1826
  // パス要素として安全な形だけを通す (外部由来の値なので containment を局所保証)。
1825
1827
  if (!isSafeSessionIdForPath(sessionId)) return
1826
1828
  if (!s.cwd) return
1827
- const fp = resolvePath({ cwd: s.cwd, session_id: sessionId })
1829
+ let fp = resolvePath({ cwd: s.cwd, session_id: sessionId })
1828
1830
  if (!fp) return
1831
+ let st
1832
+ try {
1833
+ st = await statFn(fp)
1834
+ } catch {
1835
+ // 再起動直後は snapshot に構文上は安全でも既に失効した session ID が残ることがある。
1836
+ // 0.8.7 は unbound/fresh だけを live session へ切り替えていたため、この場合は stat
1837
+ // 失敗を外側 catch が握りつぶし、サイドバーの依頼/応答だけが空のままになった。
1838
+ // primary path が読めない場合に限って、現在の cwd-scoped live session ID を再解決する。
1839
+ // snapshot path が実在する通常系では従来どおり snapshot を優先する。
1840
+ if (usedFallback || !resolveFallbackSessionId) return
1841
+ const fallbackId = resolveFallbackSessionId(s)
1842
+ if (!isSafeSessionIdForPath(fallbackId) || fallbackId === sessionId) return
1843
+ const fallbackPath = resolvePath({ cwd: s.cwd, session_id: fallbackId })
1844
+ if (!fallbackPath) return
1845
+ try {
1846
+ st = await statFn(fallbackPath)
1847
+ } catch {
1848
+ return
1849
+ }
1850
+ sessionId = fallbackId
1851
+ fp = fallbackPath
1852
+ usedFallback = true
1853
+ }
1829
1854
  livePaths.add(fp)
1830
- const st = await statFn(fp)
1831
1855
  const version = lastTurnTextsVersion(st)
1832
1856
  const cached = lastTurnTextsCache.get(fp)
1833
1857
  if (cached && cached.version === version) {