@cocorograph/hub-agent 0.8.6 → 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.
- package/package.json +1 -1
- package/src/main.mjs +56 -5
package/package.json
CHANGED
package/src/main.mjs
CHANGED
|
@@ -1786,12 +1786,21 @@ function isSafeSessionIdForPath(id) {
|
|
|
1786
1786
|
*
|
|
1787
1787
|
* @param {Array} sessions listTmuxSessions の素の行 (name / cwd を使う)
|
|
1788
1788
|
* @param {((name: string) => object | null) | undefined} getSnap state loop の getSnapshot
|
|
1789
|
+
* @param {object} [options] I/O と session ID 解決の注入点
|
|
1790
|
+
* @param {((session: object) => string | null) | undefined} [options.resolveFallbackSessionId]
|
|
1791
|
+
* snapshot の context_session_id が再起動後の `unbound:*` のとき、TUI bind / live
|
|
1792
|
+
* Claude bridge から同じ cwd の会話 ID を復元する。戻り値にも containment 検査を行う。
|
|
1789
1793
|
* @returns {Promise<Map<string, {user: string, assistant: string}>>}
|
|
1790
1794
|
*/
|
|
1791
1795
|
export async function readAllSessionLastTexts(
|
|
1792
1796
|
sessions,
|
|
1793
1797
|
getSnap,
|
|
1794
|
-
{
|
|
1798
|
+
{
|
|
1799
|
+
extract = extractLastTurnTexts,
|
|
1800
|
+
statFn = stat,
|
|
1801
|
+
resolvePath = jsonlPath,
|
|
1802
|
+
resolveFallbackSessionId,
|
|
1803
|
+
} = {},
|
|
1795
1804
|
) {
|
|
1796
1805
|
const out = new Map()
|
|
1797
1806
|
if (!getSnap) return out
|
|
@@ -1801,14 +1810,48 @@ export async function readAllSessionLastTexts(
|
|
|
1801
1810
|
try {
|
|
1802
1811
|
const snap = getSnap(s.name)
|
|
1803
1812
|
if (!snap || snap.cli_kind !== "claude") return
|
|
1804
|
-
|
|
1813
|
+
let sessionId = snap.context_session_id
|
|
1814
|
+
let usedFallback = false
|
|
1815
|
+
// hub-agent 再起動で in-memory の TUI bind が消えると、state loop の snapshot は
|
|
1816
|
+
// `unbound:<session>` へ落ちる。一方、Claude bridge の warm/live session は cwd
|
|
1817
|
+
// から同じ会話 ID を復元できる。ここでフォールバックしないと、再起動後に全行の
|
|
1818
|
+
// 「最後の依頼 / 応答」だけが消え、次に chat signal が fresh になるまで戻らない。
|
|
1819
|
+
//
|
|
1820
|
+
// snapshot が安全な実 ID を持つ場合は必ずそちらを優先し、fallback は placeholder /
|
|
1821
|
+
// 危険値の場合だけ使う。fallback も同じ containment 検査を通してから path 化する。
|
|
1822
|
+
if (!isSafeSessionIdForPath(sessionId) && resolveFallbackSessionId) {
|
|
1823
|
+
sessionId = resolveFallbackSessionId(s)
|
|
1824
|
+
usedFallback = true
|
|
1825
|
+
}
|
|
1805
1826
|
// パス要素として安全な形だけを通す (外部由来の値なので containment を局所保証)。
|
|
1806
1827
|
if (!isSafeSessionIdForPath(sessionId)) return
|
|
1807
1828
|
if (!s.cwd) return
|
|
1808
|
-
|
|
1829
|
+
let fp = resolvePath({ cwd: s.cwd, session_id: sessionId })
|
|
1809
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
|
+
}
|
|
1810
1854
|
livePaths.add(fp)
|
|
1811
|
-
const st = await statFn(fp)
|
|
1812
1855
|
const version = lastTurnTextsVersion(st)
|
|
1813
1856
|
const cached = lastTurnTextsCache.get(fp)
|
|
1814
1857
|
if (cached && cached.version === version) {
|
|
@@ -4739,7 +4782,15 @@ async function dispatch(msg, ctx) {
|
|
|
4739
4782
|
})
|
|
4740
4783
|
const [lastEventByName, lastTextsByName] = await Promise.all([
|
|
4741
4784
|
readAllSessionEvents(),
|
|
4742
|
-
readAllSessionLastTexts(sessions, ctx.getSessionStateSnapshot
|
|
4785
|
+
readAllSessionLastTexts(sessions, ctx.getSessionStateSnapshot, {
|
|
4786
|
+
resolveFallbackSessionId: (session) =>
|
|
4787
|
+
resolveStateLoopBoundSessionId(
|
|
4788
|
+
ctx.tuiReboundSessions,
|
|
4789
|
+
session.name,
|
|
4790
|
+
session.cwd,
|
|
4791
|
+
ctx.claudeBridge,
|
|
4792
|
+
),
|
|
4793
|
+
}),
|
|
4743
4794
|
])
|
|
4744
4795
|
const enriched = enrichTmuxSessionsForListResponse(
|
|
4745
4796
|
sessions,
|