tailii-host 0.1.1 → 0.3.0

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 (348) hide show
  1. package/README.md +27 -10
  2. package/dist/{broker.d.ts → approval/broker.d.ts} +9 -5
  3. package/dist/{broker.js → approval/broker.js} +42 -6
  4. package/dist/approval/broker.js.map +1 -0
  5. package/dist/{hook.d.ts → approval/hook.d.ts} +48 -7
  6. package/dist/{hook.js → approval/hook.js} +359 -50
  7. package/dist/approval/hook.js.map +1 -0
  8. package/dist/backend/herdr.d.ts +226 -0
  9. package/dist/backend/herdr.js +749 -0
  10. package/dist/backend/herdr.js.map +1 -0
  11. package/dist/backend/sessionBackend.d.ts +81 -0
  12. package/dist/backend/sessionBackend.js +114 -0
  13. package/dist/backend/sessionBackend.js.map +1 -0
  14. package/dist/backend/tmux.d.ts +125 -0
  15. package/dist/backend/tmux.js +392 -0
  16. package/dist/backend/tmux.js.map +1 -0
  17. package/dist/{chatTailController.d.ts → chat/chatTailController.d.ts} +29 -6
  18. package/dist/{chatTailController.js → chat/chatTailController.js} +94 -18
  19. package/dist/chat/chatTailController.js.map +1 -0
  20. package/dist/{imageService.d.ts → chat/imageService.d.ts} +12 -1
  21. package/dist/{imageService.js → chat/imageService.js} +39 -11
  22. package/dist/chat/imageService.js.map +1 -0
  23. package/dist/chat/remoteQuestionMonitor.d.ts +27 -0
  24. package/dist/chat/remoteQuestionMonitor.js +128 -0
  25. package/dist/chat/remoteQuestionMonitor.js.map +1 -0
  26. package/dist/chat/subagentTailer.d.ts +30 -0
  27. package/dist/chat/subagentTailer.js +704 -0
  28. package/dist/chat/subagentTailer.js.map +1 -0
  29. package/dist/chat/subagentTranscript.d.ts +20 -0
  30. package/dist/chat/subagentTranscript.js +273 -0
  31. package/dist/chat/subagentTranscript.js.map +1 -0
  32. package/dist/{transcriptTailer.d.ts → chat/transcriptTailer.d.ts} +12 -1
  33. package/dist/{transcriptTailer.js → chat/transcriptTailer.js} +183 -10
  34. package/dist/chat/transcriptTailer.js.map +1 -0
  35. package/dist/cli.js +15 -10
  36. package/dist/cli.js.map +1 -1
  37. package/dist/codex/codexAccountUsage.d.ts +22 -0
  38. package/dist/codex/codexAccountUsage.js +128 -0
  39. package/dist/codex/codexAccountUsage.js.map +1 -0
  40. package/dist/codex/codexAppServer.d.ts +166 -0
  41. package/dist/codex/codexAppServer.js +1297 -0
  42. package/dist/codex/codexAppServer.js.map +1 -0
  43. package/dist/codex/codexNativeTurnController.d.ts +153 -0
  44. package/dist/codex/codexNativeTurnController.js +673 -0
  45. package/dist/codex/codexNativeTurnController.js.map +1 -0
  46. package/dist/codex/codexRolloutTailer.d.ts +100 -0
  47. package/dist/codex/codexRolloutTailer.js +568 -0
  48. package/dist/codex/codexRolloutTailer.js.map +1 -0
  49. package/dist/{codexSessionStore.d.ts → codex/codexSessionStore.d.ts} +10 -2
  50. package/dist/{codexSessionStore.js → codex/codexSessionStore.js} +184 -15
  51. package/dist/codex/codexSessionStore.js.map +1 -0
  52. package/dist/codex/codexSubagentTracker.d.ts +21 -0
  53. package/dist/codex/codexSubagentTracker.js +281 -0
  54. package/dist/codex/codexSubagentTracker.js.map +1 -0
  55. package/dist/codex/codexToolActivity.d.ts +69 -0
  56. package/dist/codex/codexToolActivity.js +425 -0
  57. package/dist/codex/codexToolActivity.js.map +1 -0
  58. package/dist/{codexUsage.d.ts → codex/codexUsage.d.ts} +1 -1
  59. package/dist/{codexUsage.js → codex/codexUsage.js} +19 -26
  60. package/dist/codex/codexUsage.js.map +1 -0
  61. package/dist/commands/doctor.d.ts +65 -0
  62. package/dist/commands/doctor.js +425 -0
  63. package/dist/commands/doctor.js.map +1 -0
  64. package/dist/{hookSettings.d.ts → commands/hookSettings.d.ts} +14 -1
  65. package/dist/{hookSettings.js → commands/hookSettings.js} +96 -12
  66. package/dist/commands/hookSettings.js.map +1 -0
  67. package/dist/{kick.js → commands/kick.js} +16 -1
  68. package/dist/commands/kick.js.map +1 -0
  69. package/dist/{launch.d.ts → commands/launch.d.ts} +67 -5
  70. package/dist/commands/launch.js +716 -0
  71. package/dist/commands/launch.js.map +1 -0
  72. package/dist/commands/legacyHomeMigration.js.map +1 -0
  73. package/dist/{pairingCode.d.ts → commands/pairingCode.d.ts} +29 -2
  74. package/dist/{pairingCode.js → commands/pairingCode.js} +120 -11
  75. package/dist/commands/pairingCode.js.map +1 -0
  76. package/dist/{pushTokenCommand.d.ts → commands/pushTokenCommand.d.ts} +1 -1
  77. package/dist/{pushTokenCommand.js → commands/pushTokenCommand.js} +2 -2
  78. package/dist/commands/pushTokenCommand.js.map +1 -0
  79. package/dist/{setup.d.ts → commands/setup.d.ts} +17 -6
  80. package/dist/{setup.js → commands/setup.js} +133 -75
  81. package/dist/commands/setup.js.map +1 -0
  82. package/dist/engine/context.d.ts +145 -0
  83. package/dist/engine/context.js +184 -0
  84. package/dist/engine/context.js.map +1 -0
  85. package/dist/engine/engine.d.ts +121 -0
  86. package/dist/engine/engine.js +799 -0
  87. package/dist/engine/engine.js.map +1 -0
  88. package/dist/engine/handlers/accountUsage.d.ts +53 -0
  89. package/dist/engine/handlers/accountUsage.js +203 -0
  90. package/dist/engine/handlers/accountUsage.js.map +1 -0
  91. package/dist/engine/handlers/claudeModels.d.ts +2 -0
  92. package/dist/engine/handlers/claudeModels.js +23 -0
  93. package/dist/engine/handlers/claudeModels.js.map +1 -0
  94. package/dist/engine/handlers/codex.d.ts +2 -0
  95. package/dist/engine/handlers/codex.js +97 -0
  96. package/dist/engine/handlers/codex.js.map +1 -0
  97. package/dist/engine/handlers/conversation.d.ts +2 -0
  98. package/dist/engine/handlers/conversation.js +259 -0
  99. package/dist/engine/handlers/conversation.js.map +1 -0
  100. package/dist/engine/handlers/core.d.ts +2 -0
  101. package/dist/engine/handlers/core.js +66 -0
  102. package/dist/engine/handlers/core.js.map +1 -0
  103. package/dist/engine/handlers/git.d.ts +2 -0
  104. package/dist/engine/handlers/git.js +127 -0
  105. package/dist/engine/handlers/git.js.map +1 -0
  106. package/dist/engine/handlers/index.d.ts +2 -0
  107. package/dist/engine/handlers/index.js +32 -0
  108. package/dist/engine/handlers/index.js.map +1 -0
  109. package/dist/engine/handlers/mode.d.ts +2 -0
  110. package/dist/engine/handlers/mode.js +194 -0
  111. package/dist/engine/handlers/mode.js.map +1 -0
  112. package/dist/engine/handlers/officialApps.d.ts +2 -0
  113. package/dist/engine/handlers/officialApps.js +79 -0
  114. package/dist/engine/handlers/officialApps.js.map +1 -0
  115. package/dist/engine/handlers/preview.d.ts +2 -0
  116. package/dist/engine/handlers/preview.js +59 -0
  117. package/dist/engine/handlers/preview.js.map +1 -0
  118. package/dist/engine/handlers/session.d.ts +2 -0
  119. package/dist/engine/handlers/session.js +385 -0
  120. package/dist/engine/handlers/session.js.map +1 -0
  121. package/dist/engine/handlers/usage.d.ts +2 -0
  122. package/dist/engine/handlers/usage.js +96 -0
  123. package/dist/engine/handlers/usage.js.map +1 -0
  124. package/dist/engine/handlers/workspace.d.ts +2 -0
  125. package/dist/engine/handlers/workspace.js +110 -0
  126. package/dist/engine/handlers/workspace.js.map +1 -0
  127. package/dist/engine/slashCommands.d.ts +3 -0
  128. package/dist/engine/slashCommands.js +211 -0
  129. package/dist/engine/slashCommands.js.map +1 -0
  130. package/dist/hub/engineRelaySocket.d.ts +58 -0
  131. package/dist/hub/engineRelaySocket.js +161 -0
  132. package/dist/hub/engineRelaySocket.js.map +1 -0
  133. package/dist/hub/hubClient.d.ts +28 -0
  134. package/dist/hub/hubClient.js +187 -0
  135. package/dist/hub/hubClient.js.map +1 -0
  136. package/dist/hub/hubDaemon.d.ts +69 -0
  137. package/dist/hub/hubDaemon.js +466 -0
  138. package/dist/hub/hubDaemon.js.map +1 -0
  139. package/dist/hub/hubProtocol.d.ts +161 -0
  140. package/dist/hub/hubProtocol.js +379 -0
  141. package/dist/hub/hubProtocol.js.map +1 -0
  142. package/dist/hub/panePreviewPump.d.ts +65 -0
  143. package/dist/hub/panePreviewPump.js +187 -0
  144. package/dist/hub/panePreviewPump.js.map +1 -0
  145. package/dist/hub/questionInjection.d.ts +19 -0
  146. package/dist/hub/questionInjection.js +126 -0
  147. package/dist/hub/questionInjection.js.map +1 -0
  148. package/dist/hub/reaper.d.ts +74 -0
  149. package/dist/hub/reaper.js +333 -0
  150. package/dist/hub/reaper.js.map +1 -0
  151. package/dist/hub/sessionHub.d.ts +203 -0
  152. package/dist/hub/sessionHub.js +1862 -0
  153. package/dist/hub/sessionHub.js.map +1 -0
  154. package/dist/protocol/common.d.ts +18 -0
  155. package/dist/protocol/common.js +78 -0
  156. package/dist/protocol/common.js.map +1 -0
  157. package/dist/protocol/decode.d.ts +3 -0
  158. package/dist/protocol/decode.js +1036 -0
  159. package/dist/protocol/decode.js.map +1 -0
  160. package/dist/protocol/encode.d.ts +3 -0
  161. package/dist/protocol/encode.js +84 -0
  162. package/dist/protocol/encode.js.map +1 -0
  163. package/dist/protocol/messages.d.ts +1002 -0
  164. package/dist/protocol/messages.js +8 -0
  165. package/dist/protocol/messages.js.map +1 -0
  166. package/dist/protocol.d.ts +4 -329
  167. package/dist/protocol.js +13 -531
  168. package/dist/protocol.js.map +1 -1
  169. package/dist/push/apnsConfigStore.js.map +1 -0
  170. package/dist/push/apnsJwtProvider.js.map +1 -0
  171. package/dist/{apnsSender.js.map → push/apnsSender.js.map} +1 -1
  172. package/dist/{approvalPushNotifier.js → push/approvalPushNotifier.js} +1 -1
  173. package/dist/push/approvalPushNotifier.js.map +1 -0
  174. package/dist/push/deviceTokenStore.js.map +1 -0
  175. package/dist/{pushTypes.js → push/pushTypes.js} +1 -1
  176. package/dist/push/pushTypes.js.map +1 -0
  177. package/dist/push/sendLog.js.map +1 -0
  178. package/dist/services/accountIdentity.d.ts +44 -0
  179. package/dist/services/accountIdentity.js +184 -0
  180. package/dist/services/accountIdentity.js.map +1 -0
  181. package/dist/services/claudeCredentialRefresh.d.ts +30 -0
  182. package/dist/services/claudeCredentialRefresh.js +345 -0
  183. package/dist/services/claudeCredentialRefresh.js.map +1 -0
  184. package/dist/services/claudeModelCatalog.d.ts +21 -0
  185. package/dist/services/claudeModelCatalog.js +181 -0
  186. package/dist/services/claudeModelCatalog.js.map +1 -0
  187. package/dist/{dirLister.d.ts → services/dirLister.d.ts} +9 -4
  188. package/dist/services/dirLister.js +169 -0
  189. package/dist/services/dirLister.js.map +1 -0
  190. package/dist/services/fileService.d.ts +10 -0
  191. package/dist/services/fileService.js +123 -0
  192. package/dist/services/fileService.js.map +1 -0
  193. package/dist/services/gitService.d.ts +79 -0
  194. package/dist/services/gitService.js +648 -0
  195. package/dist/services/gitService.js.map +1 -0
  196. package/dist/services/hostVersions.d.ts +38 -0
  197. package/dist/services/hostVersions.js +120 -0
  198. package/dist/services/hostVersions.js.map +1 -0
  199. package/dist/services/officialApps.d.ts +148 -0
  200. package/dist/services/officialApps.js +1079 -0
  201. package/dist/services/officialApps.js.map +1 -0
  202. package/dist/services/planUsageFetcher.d.ts +119 -0
  203. package/dist/services/planUsageFetcher.js +357 -0
  204. package/dist/services/planUsageFetcher.js.map +1 -0
  205. package/dist/services/previewServer.d.ts +31 -0
  206. package/dist/services/previewServer.js +233 -0
  207. package/dist/services/previewServer.js.map +1 -0
  208. package/dist/services/quicGateway.d.ts +143 -0
  209. package/dist/services/quicGateway.js +292 -0
  210. package/dist/services/quicGateway.js.map +1 -0
  211. package/dist/services/serveService.d.ts +50 -0
  212. package/dist/services/serveService.js +302 -0
  213. package/dist/services/serveService.js.map +1 -0
  214. package/dist/services/usageAggregator.js.map +1 -0
  215. package/dist/sessions/claudeSessionStore.d.ts +80 -0
  216. package/dist/sessions/claudeSessionStore.js +477 -0
  217. package/dist/sessions/claudeSessionStore.js.map +1 -0
  218. package/dist/sessions/heartbeat.d.ts +24 -0
  219. package/dist/sessions/heartbeat.js +86 -0
  220. package/dist/sessions/heartbeat.js.map +1 -0
  221. package/dist/sessions/liveSessionJoin.d.ts +20 -0
  222. package/dist/sessions/liveSessionJoin.js +80 -0
  223. package/dist/sessions/liveSessionJoin.js.map +1 -0
  224. package/dist/sessions/sessionActivityProvider.d.ts +14 -0
  225. package/dist/sessions/sessionActivityProvider.js +57 -0
  226. package/dist/sessions/sessionActivityProvider.js.map +1 -0
  227. package/dist/{sessionListService.d.ts → sessions/sessionListService.d.ts} +3 -3
  228. package/dist/{sessionListService.js → sessions/sessionListService.js} +23 -6
  229. package/dist/sessions/sessionListService.js.map +1 -0
  230. package/dist/{sessionMetadataStore.d.ts → sessions/sessionMetadataStore.d.ts} +18 -0
  231. package/dist/{sessionMetadataStore.js → sessions/sessionMetadataStore.js} +36 -1
  232. package/dist/sessions/sessionMetadataStore.js.map +1 -0
  233. package/dist/{sessionSearch.d.ts → sessions/sessionSearch.d.ts} +1 -1
  234. package/dist/sessions/sessionSearch.js.map +1 -0
  235. package/dist/shared/hostDisplayName.d.ts +11 -0
  236. package/dist/shared/hostDisplayName.js +50 -0
  237. package/dist/shared/hostDisplayName.js.map +1 -0
  238. package/dist/{lineWriter.d.ts → shared/lineWriter.d.ts} +1 -1
  239. package/dist/{lineWriter.js → shared/lineWriter.js} +1 -1
  240. package/dist/shared/lineWriter.js.map +1 -0
  241. package/dist/{observationLog.js.map → shared/observationLog.js.map} +1 -1
  242. package/dist/{paths.d.ts → shared/paths.d.ts} +7 -0
  243. package/dist/{paths.js → shared/paths.js} +9 -0
  244. package/dist/shared/paths.js.map +1 -0
  245. package/dist/shared/permissionMode.d.ts +10 -0
  246. package/dist/shared/permissionMode.js +51 -0
  247. package/dist/shared/permissionMode.js.map +1 -0
  248. package/dist/shared/skillInjection.d.ts +9 -0
  249. package/dist/shared/skillInjection.js +16 -0
  250. package/dist/shared/skillInjection.js.map +1 -0
  251. package/dist/shared/sleep.js.map +1 -0
  252. package/dist/{socketPath.d.ts → shared/socketPath.d.ts} +4 -0
  253. package/dist/{socketPath.js → shared/socketPath.js} +22 -0
  254. package/dist/shared/socketPath.js.map +1 -0
  255. package/dist/shared/version.js.map +1 -0
  256. package/package.json +13 -7
  257. package/dist/apnsConfigStore.js.map +0 -1
  258. package/dist/apnsJwtProvider.js.map +0 -1
  259. package/dist/approvalPushNotifier.js.map +0 -1
  260. package/dist/broker.js.map +0 -1
  261. package/dist/chatTailController.js.map +0 -1
  262. package/dist/claudeSessionStore.d.ts +0 -15
  263. package/dist/claudeSessionStore.js +0 -201
  264. package/dist/claudeSessionStore.js.map +0 -1
  265. package/dist/codexRolloutTailer.d.ts +0 -56
  266. package/dist/codexRolloutTailer.js +0 -303
  267. package/dist/codexRolloutTailer.js.map +0 -1
  268. package/dist/codexSessionStore.js.map +0 -1
  269. package/dist/codexUsage.js.map +0 -1
  270. package/dist/deviceTokenStore.js.map +0 -1
  271. package/dist/dirLister.js +0 -98
  272. package/dist/dirLister.js.map +0 -1
  273. package/dist/doctor.d.ts +0 -36
  274. package/dist/doctor.js +0 -162
  275. package/dist/doctor.js.map +0 -1
  276. package/dist/engine.d.ts +0 -85
  277. package/dist/engine.js +0 -962
  278. package/dist/engine.js.map +0 -1
  279. package/dist/hook.js.map +0 -1
  280. package/dist/hookSettings.js.map +0 -1
  281. package/dist/idleReaper.d.ts +0 -13
  282. package/dist/idleReaper.js +0 -30
  283. package/dist/idleReaper.js.map +0 -1
  284. package/dist/imageService.js.map +0 -1
  285. package/dist/kick.js.map +0 -1
  286. package/dist/launch.js +0 -396
  287. package/dist/launch.js.map +0 -1
  288. package/dist/legacyHomeMigration.js.map +0 -1
  289. package/dist/lineWriter.js.map +0 -1
  290. package/dist/mdnsAdvertiser.d.ts +0 -46
  291. package/dist/mdnsAdvertiser.js +0 -268
  292. package/dist/mdnsAdvertiser.js.map +0 -1
  293. package/dist/pairingCode.js.map +0 -1
  294. package/dist/paths.js.map +0 -1
  295. package/dist/permissionMode.d.ts +0 -8
  296. package/dist/permissionMode.js +0 -32
  297. package/dist/permissionMode.js.map +0 -1
  298. package/dist/planUsageFetcher.d.ts +0 -35
  299. package/dist/planUsageFetcher.js +0 -172
  300. package/dist/planUsageFetcher.js.map +0 -1
  301. package/dist/pushTokenCommand.js.map +0 -1
  302. package/dist/pushTypes.js.map +0 -1
  303. package/dist/sendLog.js.map +0 -1
  304. package/dist/sessionActivityProvider.d.ts +0 -7
  305. package/dist/sessionActivityProvider.js +0 -44
  306. package/dist/sessionActivityProvider.js.map +0 -1
  307. package/dist/sessionIdleTracker.d.ts +0 -19
  308. package/dist/sessionIdleTracker.js +0 -42
  309. package/dist/sessionIdleTracker.js.map +0 -1
  310. package/dist/sessionListService.js.map +0 -1
  311. package/dist/sessionMetadataStore.js.map +0 -1
  312. package/dist/sessionSearch.js.map +0 -1
  313. package/dist/setup.js.map +0 -1
  314. package/dist/sleep.js.map +0 -1
  315. package/dist/socketPath.js.map +0 -1
  316. package/dist/subagentTailer.d.ts +0 -15
  317. package/dist/subagentTailer.js +0 -399
  318. package/dist/subagentTailer.js.map +0 -1
  319. package/dist/tmux.d.ts +0 -62
  320. package/dist/tmux.js +0 -163
  321. package/dist/tmux.js.map +0 -1
  322. package/dist/transcriptTailer.js.map +0 -1
  323. package/dist/usageAggregator.js.map +0 -1
  324. package/dist/version.js.map +0 -1
  325. /package/dist/{kick.d.ts → commands/kick.d.ts} +0 -0
  326. /package/dist/{legacyHomeMigration.d.ts → commands/legacyHomeMigration.d.ts} +0 -0
  327. /package/dist/{legacyHomeMigration.js → commands/legacyHomeMigration.js} +0 -0
  328. /package/dist/{apnsConfigStore.d.ts → push/apnsConfigStore.d.ts} +0 -0
  329. /package/dist/{apnsConfigStore.js → push/apnsConfigStore.js} +0 -0
  330. /package/dist/{apnsJwtProvider.d.ts → push/apnsJwtProvider.d.ts} +0 -0
  331. /package/dist/{apnsJwtProvider.js → push/apnsJwtProvider.js} +0 -0
  332. /package/dist/{apnsSender.d.ts → push/apnsSender.d.ts} +0 -0
  333. /package/dist/{apnsSender.js → push/apnsSender.js} +0 -0
  334. /package/dist/{approvalPushNotifier.d.ts → push/approvalPushNotifier.d.ts} +0 -0
  335. /package/dist/{deviceTokenStore.d.ts → push/deviceTokenStore.d.ts} +0 -0
  336. /package/dist/{deviceTokenStore.js → push/deviceTokenStore.js} +0 -0
  337. /package/dist/{pushTypes.d.ts → push/pushTypes.d.ts} +0 -0
  338. /package/dist/{sendLog.d.ts → push/sendLog.d.ts} +0 -0
  339. /package/dist/{sendLog.js → push/sendLog.js} +0 -0
  340. /package/dist/{usageAggregator.d.ts → services/usageAggregator.d.ts} +0 -0
  341. /package/dist/{usageAggregator.js → services/usageAggregator.js} +0 -0
  342. /package/dist/{sessionSearch.js → sessions/sessionSearch.js} +0 -0
  343. /package/dist/{observationLog.d.ts → shared/observationLog.d.ts} +0 -0
  344. /package/dist/{observationLog.js → shared/observationLog.js} +0 -0
  345. /package/dist/{sleep.d.ts → shared/sleep.d.ts} +0 -0
  346. /package/dist/{sleep.js → shared/sleep.js} +0 -0
  347. /package/dist/{version.d.ts → shared/version.d.ts} +0 -0
  348. /package/dist/{version.js → shared/version.js} +0 -0
@@ -0,0 +1,333 @@
1
+ // reaper.ts
2
+ // tailii (TS host) — tmux セッション自動掃除の判定ロジック。
3
+ //
4
+ // engine 内蔵の idle reaper は「engine(=SSH 接続)が生きている間しか回らない」「tracker が
5
+ // in-memory で再起動時に空」という構造穴があった。Session Hub daemon は engine から独立した
6
+ // detached プロセスとして動き、heartbeat ファイル(heartbeat.ts)を唯一の判定権威にして
7
+ // `now - ts >= timeout`(一律 1800 秒)で kill する。ただし cwd 自身または子孫でローカル
8
+ // 開発サーバーが LISTEN 中なら activity とみなし、heartbeat を更新して巻き添え終了を防ぐ。
9
+ //
10
+ // state=active(処理中)の扱いはエージェントで異なる:
11
+ // - claude: ターン中でも hook はツール実行中に沈黙する(長い1ツール呼びの間イベントが無い)
12
+ // ため、pane のエージェントプロセス生存を確認できたら Hub が ts を bump 代行する。
13
+ // プロセスが死んでいる(pane がシェルだけ)なら idle に書き換え → 30 分後に通常ルールで kill。
14
+ // - codex: ターンは engine が駆動し engine と運命共同体。engine が 60 秒毎に bump するので、
15
+ // bump が止まって timeout を超えた active は「死んだターン」→ そのまま kill してよい。
16
+ // Hub は bump 代行しない(すると bump 停止=ターン死亡のシグナルが壊れる)。
17
+ //
18
+ // 対象は tailii が作る `cs-*` / `s-*` セッションのみ。ユーザーの他の tmux セッションには触れない。
19
+ // heartbeat 未採番の生存セッション(過去の残骸)は「今を idle」として採番し、次周期から計時する。
20
+ // 対象セッションが 0 になったら自然終了する(次の engine 接続 / hook 発火で ensure され再起動)。
21
+ import * as fs from "node:fs";
22
+ import * as path from "node:path";
23
+ import { bumpHeartbeat, listHeartbeatSessions, readHeartbeat, removeHeartbeat, writeHeartbeat, } from "../sessions/heartbeat.js";
24
+ import { HerdrSessionManager, isDefaultHerdrTabLabel } from "../backend/herdr.js";
25
+ import { CodexAppServerManager } from "../codex/codexAppServer.js";
26
+ import { ClaudeSessionStore, transcriptTitle } from "../sessions/claudeSessionStore.js";
27
+ import { paneCommandLooksLikeAgent } from "../backend/tmux.js";
28
+ /** 一律のアイドル timeout(秒)。idle/active(bump 停止)の両方に同じ値を使う。 */
29
+ export const REAPER_IDLE_TIMEOUT_SECONDS = 1800;
30
+ /** 巡回間隔(秒)。 */
31
+ export const REAPER_CHECK_INTERVAL_SECONDS = 60;
32
+ /** tailii が管理する tmux セッション名(これ以外は絶対に触らない)。 */
33
+ export const TAILII_SESSION_PATTERN = /^(cs|s)-/;
34
+ /** 存在するパスは symlink / `..` / 大文字小文字表記を実体パスへ寄せる。 */
35
+ function canonicalCwd(cwd) {
36
+ const absolute = path.resolve(cwd);
37
+ try {
38
+ return fs.realpathSync(absolute);
39
+ }
40
+ catch {
41
+ // stale metadata 等で既に消えた cwd も、字句正規化した値なら安全に比較できる。
42
+ return absolute;
43
+ }
44
+ }
45
+ /** server cwd がセッション cwd 自身またはその子孫か(prefix sibling は除外)。 */
46
+ export function serverCwdBelongsToSession(sessionCwd, serverCwd) {
47
+ const relative = path.relative(canonicalCwd(sessionCwd), canonicalCwd(serverCwd));
48
+ return relative === "" ||
49
+ (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
50
+ }
51
+ /** 生存中の tailii セッション名(`cs-*`/`s-*`)。tmux サーバ不在は空集合。 */
52
+ export async function liveTailiiSessions(runner) {
53
+ const result = await runner(["ls", "-F", "#{session_name}"]);
54
+ if (result.exitCode !== 0) {
55
+ const combined = (result.stdout + result.stderr).toLowerCase();
56
+ if (combined.includes("no server running") || combined.includes("no sessions"))
57
+ return [];
58
+ throw new Error(`tmux ls failed (exit ${result.exitCode}): ${result.stderr}`);
59
+ }
60
+ return result.stdout
61
+ .split("\n")
62
+ .map((line) => line.trim())
63
+ .filter((name) => TAILII_SESSION_PATTERN.test(name))
64
+ .sort();
65
+ }
66
+ /** ターミナルクライアントが attach 中のセッション名集合。取得失敗は空集合(保護なしに倒す)。 */
67
+ export async function attachedSessions(runner) {
68
+ try {
69
+ const result = await runner(["list-clients", "-F", "#{session_name}"]);
70
+ if (result.exitCode !== 0)
71
+ return new Set();
72
+ return new Set(result.stdout
73
+ .split("\n")
74
+ .map((line) => line.trim())
75
+ .filter((name) => name.length > 0));
76
+ }
77
+ catch {
78
+ return new Set();
79
+ }
80
+ }
81
+ /**
82
+ * pane のエージェントプロセス生存判定。判定不能(tmux エラー等)は true(=保護、安全側)。
83
+ * pane_current_command がシェル名なら claude/codex プロセスは終了している。
84
+ */
85
+ export async function agentProcessAlive(runner, name, metadataStore) {
86
+ const target = metadataStore.get(name)?.tmuxPaneId ?? name;
87
+ try {
88
+ const result = await runner(["display-message", "-p", "-t", target, "#{pane_current_command}"]);
89
+ if (result.exitCode !== 0)
90
+ return true;
91
+ return paneCommandLooksLikeAgent(result.stdout);
92
+ }
93
+ catch {
94
+ return true;
95
+ }
96
+ }
97
+ /**
98
+ * herdr 巡回の既定 ops。herdr メタが 1 つも無ければ null(herdr CLI を呼ばない)。
99
+ * kill は pane close 相当(HerdrSessionManager.kill)。
100
+ */
101
+ function defaultHerdrReaperOps(metadataStore) {
102
+ if (!metadataStore.all().some((meta) => meta.backend === "herdr"))
103
+ return null;
104
+ return new HerdrSessionManager({ store: metadataStore });
105
+ }
106
+ /** 既定の claude 会話タイトル導出(明示タイトル優先 → 最初のユーザー発話, 一覧と同じ規則)。 */
107
+ function defaultDeriveClaudeTitle(claudeSessionId) {
108
+ const transcript = new ClaudeSessionStore().transcriptPath(claudeSessionId);
109
+ if (transcript === null)
110
+ return null;
111
+ return transcriptTitle(transcript);
112
+ }
113
+ /** 稼働中の共有 App Server から正式名つき Codex thread を一括取得する(server は起動しない)。 */
114
+ async function loadCodexThreadTitles() {
115
+ const threads = await new CodexAppServerManager().listThreads();
116
+ if (threads === null)
117
+ return new Map();
118
+ return new Map(threads.flatMap((thread) => thread.name === null ? [] : [[thread.id, thread.name]]));
119
+ }
120
+ /** 巡回 1 回分。判定表は docs/architecture.md「セッション自動掃除」を参照。 */
121
+ export async function reaperTick(options) {
122
+ const { runner, heartbeatDir, metadataStore, timeoutSeconds, now } = options;
123
+ const log = options.log ?? (() => { });
124
+ const live = await liveTailiiSessions(runner);
125
+ const attached = live.length > 0 ? await attachedSessions(runner) : new Set();
126
+ const killed = [];
127
+ const demoted = [];
128
+ const reclaimed = [];
129
+ let localServerCwdsPromise = null;
130
+ let localServerUnavailableLogged = false;
131
+ /** 同一 tick では lsof 結果を全セッションで共有する。検出失敗は null にして回収を延期。 */
132
+ const localServerCwds = () => {
133
+ if (localServerCwdsPromise === null) {
134
+ localServerCwdsPromise = (options.listLocalServerCwds?.() ?? Promise.resolve(new Set()))
135
+ .catch((error) => {
136
+ log(`local server 検出失敗(回収を延期): ${String(error)}`);
137
+ localServerUnavailableLogged = true;
138
+ return null;
139
+ });
140
+ }
141
+ return localServerCwdsPromise;
142
+ };
143
+ /**
144
+ * 1 セッション分の判定(tmux / herdr 共通)。heartbeat のルールは backend に依らない:
145
+ * 未採番=adopt / attach 中=bump / claude active+alive=bump 代行 / active+dead=idle 降格 /
146
+ * idle・codex active の timeout 超過=kill。
147
+ */
148
+ const judge = async (name, isAttached, agentAlive, kill) => {
149
+ const heartbeat = readHeartbeat(heartbeatDir, name);
150
+ if (heartbeat === null) {
151
+ // 未採番(engine 再起動をまたいだ残骸等)。今を idle 起点として採番し次周期から計時。
152
+ writeHeartbeat(heartbeatDir, name, { ts: now, state: "idle", event: "adopted" });
153
+ log(`adopt ${name}`);
154
+ return;
155
+ }
156
+ if (isAttached) {
157
+ // ターミナルから attach 中 = 人間が使用中。hook/engine を経由しない利用でも殺さない。
158
+ bumpHeartbeat(heartbeatDir, name, now, "daemon-client-attached");
159
+ return;
160
+ }
161
+ const agent = metadataStore.get(name)?.agent ?? "claude";
162
+ if (heartbeat.state === "active" && agent === "claude") {
163
+ if (await agentAlive()) {
164
+ // 処理中(ツール実行中は hook が沈黙する)。デーモンが ts を bump 代行して保護。
165
+ bumpHeartbeat(heartbeatDir, name, now, "daemon-agent-alive", "active");
166
+ }
167
+ else {
168
+ // active のままプロセスだけ死んだ(クラッシュ等)。idle へ倒して通常計時に載せる。
169
+ writeHeartbeat(heartbeatDir, name, { ts: now, state: "idle", event: "agent-process-dead" });
170
+ demoted.push(name);
171
+ log(`demote ${name} (agent process dead)`);
172
+ }
173
+ return;
174
+ }
175
+ // idle、および codex の active(bump 停止=ターン死亡)は一律 timeout で kill。
176
+ if (now - heartbeat.ts < timeoutSeconds)
177
+ return;
178
+ // 同じプロジェクト配下でローカル開発サーバーが LISTEN 中なら、その pane を閉じると
179
+ // server まで巻き添え終了する。server 自体を利用中の activity とみなし、停止後に改めて
180
+ // timeout 分の猶予を取る(herdr は attach 状態を取得できないため特に重要)。
181
+ const serverCwds = await localServerCwds();
182
+ // lsof 未導入・timeout 等を「サーバーなし」に倒すと、その瞬間に pane と server を
183
+ // 破壊し得る。heartbeat は進めず次の 60 秒 tick で再検出する。
184
+ if (serverCwds === null) {
185
+ if (!localServerUnavailableLogged) {
186
+ log("local server 検出不能のため timeout セッション回収を延期");
187
+ localServerUnavailableLogged = true;
188
+ }
189
+ return;
190
+ }
191
+ const cwd = metadataStore.get(name)?.cwd;
192
+ if (cwd !== undefined && [...serverCwds].some((serverCwd) => serverCwdBelongsToSession(cwd, serverCwd))) {
193
+ bumpHeartbeat(heartbeatDir, name, now, "daemon-local-server");
194
+ log(`protect ${name} (local server cwd=${cwd})`);
195
+ return;
196
+ }
197
+ // kill 直前に再読取して再判定する: tick 中に会話が再オープンされ engine が bump した
198
+ // 直後のセッションを殺さない(読取→kill 間の競合窓を閉じる)。
199
+ const recheck = readHeartbeat(heartbeatDir, name);
200
+ if (recheck !== null && recheck.ts !== heartbeat.ts)
201
+ return;
202
+ await kill();
203
+ removeHeartbeat(heartbeatDir, name);
204
+ killed.push(name);
205
+ log(`kill ${name} (state=${heartbeat.state} idle=${now - heartbeat.ts}s)`);
206
+ };
207
+ for (const name of live) {
208
+ await judge(name, attached.has(name), () => agentProcessAlive(runner, name, metadataStore), async () => {
209
+ const result = await runner(["kill-session", "-t", name]);
210
+ if (result.exitCode !== 0) {
211
+ log(`kill 失敗(掃除して継続): ${name}: ${result.stderr.trim()}`);
212
+ }
213
+ });
214
+ }
215
+ // --- herdr backend の巡回(tailii named session の pane)---
216
+ // attach 保護は無し(herdr API にクライアント attach 情報が無い)。claude の
217
+ // agent-alive bump 代行と heartbeat 計時は tmux と同一ルール。
218
+ const herdrOps = options.herdrOps !== undefined ? options.herdrOps : defaultHerdrReaperOps(metadataStore);
219
+ let herdrLive = [];
220
+ if (herdrOps !== null) {
221
+ try {
222
+ herdrLive = (await herdrOps.list())
223
+ .filter((info) => info.alive && TAILII_SESSION_PATTERN.test(info.name))
224
+ .map((info) => info.name)
225
+ .sort();
226
+ }
227
+ catch {
228
+ herdrLive = [];
229
+ }
230
+ for (const name of herdrLive) {
231
+ await judge(name, false, () => herdrOps.agentProcessAlive(name), async () => {
232
+ try {
233
+ await herdrOps.kill(name);
234
+ }
235
+ catch (error) {
236
+ log(`kill 失敗(掃除して継続): ${name}: ${String(error)}`);
237
+ }
238
+ });
239
+ }
240
+ // 生存 Tailii セッションが 0 なら空 server を回収する(tmux server の自動終了に対応)。
241
+ // 判定は ops 側で pane 総数 0 のときだけ停止する(手動 pane があれば停止しない)。
242
+ if (herdrLive.length === 0) {
243
+ await herdrOps.stopServerIfEmpty?.();
244
+ }
245
+ // --- 未命名タブへ会話タイトルを自動反映(session-title)---
246
+ // タブラベルが未命名(null / 空 / セッション名 / 0.7.5 tab create の既定連番 "1"…)の
247
+ // 生存セッションだけを対象に、Claude は transcript の会話タイトル(明示タイトル
248
+ // custom-title/ai-title 優先)、Codex は App Server の正式名 thread.name をタブへ書く。
249
+ // 命名済み(それ以外のラベル)は手動を優先して触らない。
250
+ if (herdrLive.length > 0 &&
251
+ herdrOps.tabInfoByName !== undefined && herdrOps.setDisplayTitle !== undefined) {
252
+ const deriveClaudeTitle = options.deriveClaudeTitle ?? defaultDeriveClaudeTitle;
253
+ let codexTitlesPromise = null;
254
+ const deriveCodexTitle = options.deriveCodexTitle ?? (async (threadId) => {
255
+ codexTitlesPromise ??= loadCodexThreadTitles();
256
+ return (await codexTitlesPromise).get(threadId) ?? null;
257
+ });
258
+ try {
259
+ const tabInfo = await herdrOps.tabInfoByName();
260
+ for (const name of herdrLive) {
261
+ if (killed.includes(name))
262
+ continue;
263
+ const meta = metadataStore.get(name);
264
+ if (meta === null)
265
+ continue;
266
+ const agent = meta.agent ?? "claude";
267
+ const providerSessionId = agent === "codex"
268
+ ? meta.providerSessionId
269
+ : meta.providerSessionId ?? meta.claudeSessionId;
270
+ if (providerSessionId === undefined)
271
+ continue;
272
+ const info = tabInfo.get(name);
273
+ if (info === undefined)
274
+ continue;
275
+ // 「ラベル==前回の自動適用値」も未命名扱い = ai-title の更新へ追随して再リネーム
276
+ // する(追随しないと旧 ai-title がタブに固定され、iOS の逆方向取り込みが人為
277
+ // リネームと誤認して override 化する)。
278
+ const unnamed = info.label === null || info.label === "" || info.label === name ||
279
+ isDefaultHerdrTabLabel(info.label) || info.label === meta.autoTabTitle;
280
+ if (!unnamed)
281
+ continue; // 命名済み(人為リネーム)は触らない
282
+ let title;
283
+ try {
284
+ title =
285
+ agent === "codex"
286
+ ? await deriveCodexTitle(providerSessionId)
287
+ : deriveClaudeTitle(providerSessionId);
288
+ }
289
+ catch (error) {
290
+ log(`session-title 導出失敗(継続): ${name}: ${String(error)}`);
291
+ continue;
292
+ }
293
+ if (title === null || title.length === 0)
294
+ continue;
295
+ if (info.label === title) {
296
+ // ラベルは最新。自動適用の記録だけ追いつかせる(旧版からの移行時)。
297
+ if (meta.autoTabTitle !== title) {
298
+ try {
299
+ metadataStore.put({ ...meta, autoTabTitle: title });
300
+ }
301
+ catch (error) {
302
+ log(`session-title 記録失敗(継続): ${name}: ${String(error)}`);
303
+ }
304
+ }
305
+ continue;
306
+ }
307
+ try {
308
+ await herdrOps.setDisplayTitle(name, title);
309
+ metadataStore.put({ ...meta, autoTabTitle: title });
310
+ log(`session-title 自動反映: ${name} → ${title.slice(0, 30)}`);
311
+ }
312
+ catch (error) {
313
+ log(`session-title 反映失敗(継続): ${name}: ${String(error)}`);
314
+ }
315
+ }
316
+ }
317
+ catch (error) {
318
+ log(`session-title 巡回失敗(継続): ${String(error)}`);
319
+ }
320
+ }
321
+ }
322
+ // 生存セッションの無い heartbeat は残骸 → 掃除(メタデータ = cwd 権威記録は消さない)。
323
+ // herdr 生存分も和に含める(含めないと herdr セッションの heartbeat を毎周期誤回収する)。
324
+ const liveSet = new Set([...live, ...herdrLive]);
325
+ for (const name of listHeartbeatSessions(heartbeatDir)) {
326
+ if (!liveSet.has(name)) {
327
+ removeHeartbeat(heartbeatDir, name);
328
+ reclaimed.push(name);
329
+ }
330
+ }
331
+ return { liveCount: live.length + herdrLive.length, killed, demoted, reclaimed };
332
+ }
333
+ //# sourceMappingURL=reaper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reaper.js","sourceRoot":"","sources":["../../src/hub/reaper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ import type { ReaperTickOptions, ReaperTickResult } from "./reaper.js";
2
+ import type { EngineRelayMessage } from "./engineRelaySocket.js";
3
+ import { type HubClientMessage, type HubServerMessage } from "./hubProtocol.js";
4
+ import type { ControlMessage, QuestionPromptQuestion, SubagentTranscriptEntry } from "../protocol.js";
5
+ import type { ChatAgent } from "../chat/chatTailController.js";
6
+ import type { PanePreviewMode } from "./panePreviewPump.js";
7
+ import type { QuestionAnswer } from "../protocol.js";
8
+ import { type CodexAppServerThreadRuntime, type CodexNativeTurnControllerOptions, type CodexTurnControllerRuntime } from "../codex/codexNativeTurnController.js";
9
+ import { type CodexTurnLifecycleEvent } from "../codex/codexRolloutTailer.js";
10
+ export interface HubTail {
11
+ open(cwd: string, preferredSessionId: string | null, newerThanMs?: number | null, agent?: ChatAgent): void;
12
+ stop(): void;
13
+ subagentTranscript?(nodeId: string): {
14
+ entries: SubagentTranscriptEntry[];
15
+ omitted: number;
16
+ };
17
+ }
18
+ export interface HubPreviewPump {
19
+ start(session: string, mode?: PanePreviewMode, opts?: {
20
+ emitInitial?: boolean;
21
+ }): void;
22
+ stop(): void;
23
+ }
24
+ export type HubTailFactory = (write: (payload: ControlMessage) => void, onCodexTurnLifecycle?: (event: CodexTurnLifecycleEvent) => void) => HubTail;
25
+ export type HubPreviewPumpFactory = (write: (payload: ControlMessage) => void, onPermissionMode?: (mode: string) => void,
26
+ /** 毎周期評価するポーリング間隔(ms)。前面購読あり=高頻度 / 一覧 watch のみ=低頻度。 */
27
+ pollIntervalMs?: () => number) => HubPreviewPump;
28
+ export type SessionHubOptions = Omit<ReaperTickOptions, "now"> & {
29
+ /** Unix 秒。テストでは固定時計を注入する。 */
30
+ now?: () => number;
31
+ tailFactory?: HubTailFactory;
32
+ previewPumpFactory?: HubPreviewPumpFactory;
33
+ replayLimit?: number;
34
+ questionInjector?: (answers: QuestionAnswer[], session: string) => Promise<void>;
35
+ chatInjector?: (text: string, session: string) => Promise<void>;
36
+ codexAppServerFactory?: () => CodexAppServerThreadRuntime;
37
+ codexTurnControllerFactory?: (options: CodexNativeTurnControllerOptions) => CodexTurnControllerRuntime;
38
+ /** 未回答設問の永続化先。省略時は永続化しない(daemon は既定パスを明示する)。 */
39
+ pendingQuestionsPath?: string;
40
+ /** chat_send の durable queue / 配送済み receipt。daemon は既定パスを明示する。 */
41
+ chatReceiptsPath?: string;
42
+ /** receipt 永続化のテスト注入口。省略時は atomic rename を使う。 */
43
+ chatReceiptsWriter?: (target: string, contents: string) => void;
44
+ };
45
+ interface SubscriberState {
46
+ preview: boolean;
47
+ backfilling: boolean;
48
+ }
49
+ interface ReplayEvent {
50
+ serverSeq: number;
51
+ payload: ControlMessage;
52
+ }
53
+ interface PendingChatSend {
54
+ message: Extract<HubClientMessage, {
55
+ type: "chat_send";
56
+ }>;
57
+ waiters: Array<{
58
+ client: object;
59
+ id: string;
60
+ }>;
61
+ }
62
+ interface PendingCodexTurn {
63
+ message: Extract<HubClientMessage, {
64
+ type: "codex_turn_submit";
65
+ }>;
66
+ waiters: Array<{
67
+ client: object;
68
+ id: string;
69
+ }>;
70
+ }
71
+ interface CodexBufferedItem {
72
+ itemId: string;
73
+ payload: ControlMessage;
74
+ }
75
+ interface CodexLiveState {
76
+ phase: "starting" | "backfill" | "live" | "fallback-scan" | "fallback-live";
77
+ initialItemIds: ReadonlySet<string>;
78
+ initialContentCounts: ReadonlyMap<string, number>;
79
+ buffered: CodexBufferedItem[];
80
+ seenItemIds: Set<string>;
81
+ /** backfill と fallback の同文複数回を occurrence 単位で照合する。 */
82
+ publishedContentCounts: Map<string, number>;
83
+ scanContentCounts: Map<string, number>;
84
+ fallbackBaselineCounts: Map<string, number>;
85
+ disconnected: boolean;
86
+ }
87
+ interface SessionActor {
88
+ pendingQuestion: {
89
+ id: string;
90
+ questions: QuestionPromptQuestion[];
91
+ answerRoute: "tui" | "codex_native";
92
+ /** 注入失敗の自己修復で復元済みか。復元は毎回だが prompt 再配信は1回まで(再提示ループ防止)。 */
93
+ restoredAfterInjectionFailure?: boolean;
94
+ } | null;
95
+ processingSince: number | null;
96
+ focusedBy: Set<object>;
97
+ subscribers: Map<object, SubscriberState>;
98
+ nextServerSeq: number;
99
+ replayBuffer: ReplayEvent[];
100
+ tail: HubTail | null;
101
+ tailRetryTimer: ReturnType<typeof setTimeout> | null;
102
+ previewPump: HubPreviewPump | null;
103
+ backfillTails: Map<object, HubTail>;
104
+ seenClientMessageIds: Set<string>;
105
+ deliveredChatMessageIds: Map<string, number>;
106
+ deliveredCodexMessageIds: Map<string, number>;
107
+ deletedChatMessageIds: Map<string, number>;
108
+ deletedCodexMessageIds: Map<string, number>;
109
+ pendingChatMessages: Map<string, PendingChatSend>;
110
+ injectingChatMessageIds: Set<string>;
111
+ uncertainChatMessages: Map<string, Extract<HubClientMessage, {
112
+ type: "chat_send";
113
+ }>>;
114
+ uncertainCodexMessages: Map<string, Extract<HubClientMessage, {
115
+ type: "codex_turn_submit";
116
+ }>>;
117
+ pendingCodexTurns: Map<string, PendingCodexTurn>;
118
+ startingCodexMessageIds: Set<string>;
119
+ runtimeClaim: {
120
+ client: object;
121
+ expiresAt: number;
122
+ } | null;
123
+ codexLive: CodexLiveState | null;
124
+ chatQueue: PendingChatSend[];
125
+ chatOrder: string[];
126
+ chatDrainRunning: boolean;
127
+ chatDrainBlocked: boolean;
128
+ codexQueue: PendingCodexTurn[];
129
+ codexOrder: string[];
130
+ codexDrainRunning: boolean;
131
+ codexDrainBlocked: boolean;
132
+ }
133
+ export declare class SessionHub {
134
+ private readonly options;
135
+ private readonly clients;
136
+ /** 一覧 Mission Control の watcher(処理中会話全体の pane_preview 配信先)。 */
137
+ private readonly previewWatchers;
138
+ readonly actors: Map<string, SessionActor>;
139
+ private readonly now;
140
+ private readonly replayLimit;
141
+ private injectionsInFlight;
142
+ private codexStartsInFlight;
143
+ private modePushSeq;
144
+ private chatReceiptsDirty;
145
+ private readonly activeCodexTurns;
146
+ private codexTurnController;
147
+ constructor(options: SessionHubOptions);
148
+ get clientCount(): number;
149
+ get hasPendingQuestions(): boolean;
150
+ get hasInjectionsInFlight(): boolean;
151
+ get hasCodexTurnsInFlight(): boolean;
152
+ /** 新しく接続した engine が処理中会話を直ちに購読するための軽量スナップショット。 */
153
+ get processingSessionNames(): string[];
154
+ /** Hub 再起動前から active の heartbeat を actor の処理中状態へ戻す。 */
155
+ restoreFromHeartbeats(): void;
156
+ /** 永続化済み設問を復元する。App Server の request handle は再起動を越せないため TUI のみ対象。 */
157
+ restorePendingQuestions(): void;
158
+ /** daemon 再起動前に durable enqueue 済みだった chat_send と receipt を復元する。 */
159
+ restoreChatReceipts(): void;
160
+ registerClient(client: object, write: (line: string) => void): void;
161
+ unregisterClient(client: object): void;
162
+ broadcast(message: HubServerMessage): void;
163
+ sendTo(client: object, message: HubServerMessage): void;
164
+ handleRelayMessage(message: EngineRelayMessage): void;
165
+ handleClientMessage(client: object, line: string): void;
166
+ tick(): Promise<ReaperTickResult>;
167
+ close(): void;
168
+ /** tmux セッションの確定 kill に追従し、同名で将来作られる会話へ状態を持ち越さない。 */
169
+ private retireSession;
170
+ private subscribe;
171
+ private unsubscribe;
172
+ private startSharedTail;
173
+ private startCodexSharedStream;
174
+ private openCodexRollout;
175
+ private handleCodexChatItem;
176
+ private flushCodexBuffer;
177
+ private handleCodexDisconnect;
178
+ private startCodexFallback;
179
+ private publishCodexContent;
180
+ private publishConversationEvent;
181
+ private startBackfill;
182
+ private canReplay;
183
+ /** watch 状態・処理中遷移で全 actor の pump 要否を見直す(対象は疎なので全走査で足りる)。 */
184
+ private syncAllPreviews;
185
+ private syncPreview;
186
+ private actor;
187
+ private claimInput;
188
+ private deletePendingChatMessage;
189
+ private deletePendingCodexTurn;
190
+ private drainChatQueue;
191
+ private ensureCodexTurnController;
192
+ private drainCodexQueue;
193
+ private startCodexTurn;
194
+ private publishCodexMarker;
195
+ private applyProcessing;
196
+ private bumpSafe;
197
+ private setPendingQuestion;
198
+ private persistPendingQuestions;
199
+ private readPendingQuestions;
200
+ private persistChatReceipts;
201
+ private readChatReceipts;
202
+ }
203
+ export {};