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,86 @@
1
+ // heartbeat.ts
2
+ // tailii (TS host) — セッション活動ハートビートの読み書き。
3
+ //
4
+ // reaper daemon(tmux セッション自動掃除)の判定権威。`~/.tailii/heartbeat/<session>` に
5
+ // JSON を書き、daemon が `now - ts >= timeout` の一律ルールで kill を判定する。
6
+ // mtime は判定に使わない(コピー/復元で蘇生するため)。時刻の正は常にファイル内容の ts。
7
+ //
8
+ // 書き手:
9
+ // - hook(claude): UserPromptSubmit/PreToolUse/PostToolUse → active、Stop → idle
10
+ // - Hub: chat open/leave、codex/relay の processing active/done、周期 tick の bump
11
+ // - Hub の reaper tick: claude active のプロセス生存 bump 代行、初見セッションの採番
12
+ // 読み手: Hub の reaper tick のみ。
13
+ import * as fs from "node:fs";
14
+ import * as os from "node:os";
15
+ import * as path from "node:path";
16
+ import { ensureDirectory0700 } from "../shared/paths.js";
17
+ import { validateSessionName } from "./sessionMetadataStore.js";
18
+ /** 既定のハートビート置き場(`~/.tailii/heartbeat`)。 */
19
+ export function defaultHeartbeatDir() {
20
+ return path.join(os.homedir(), ".tailii", "heartbeat");
21
+ }
22
+ function heartbeatPath(dir, session) {
23
+ validateSessionName(session);
24
+ return path.join(dir, session);
25
+ }
26
+ /** ハートビートを読む。不在・壊れは null(呼び手が採番する)。 */
27
+ export function readHeartbeat(dir, session) {
28
+ try {
29
+ const raw = fs.readFileSync(heartbeatPath(dir, session), "utf8");
30
+ const parsed = JSON.parse(raw);
31
+ if (typeof parsed.ts !== "number" || !Number.isFinite(parsed.ts))
32
+ return null;
33
+ if (parsed.state !== "active" && parsed.state !== "idle")
34
+ return null;
35
+ return {
36
+ ts: parsed.ts,
37
+ state: parsed.state,
38
+ ...(typeof parsed.event === "string" ? { event: parsed.event } : {}),
39
+ };
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /** ハートビートを書く(tmp 書き込み → rename のアトミック置換)。失敗は投げる。 */
46
+ export function writeHeartbeat(dir, session, heartbeat) {
47
+ ensureDirectory0700(dir);
48
+ const target = heartbeatPath(dir, session);
49
+ const tmp = `${target}.tmp-${process.pid}`;
50
+ fs.writeFileSync(tmp, JSON.stringify(heartbeat), { mode: 0o600 });
51
+ fs.renameSync(tmp, target);
52
+ }
53
+ /**
54
+ * ts だけ更新する(state は既存値を保持、不在時は fallbackState)。
55
+ * チャット表示中 ticker / daemon の bump 代行用。
56
+ */
57
+ export function bumpHeartbeat(dir, session, now, event, fallbackState = "idle") {
58
+ const existing = readHeartbeat(dir, session);
59
+ writeHeartbeat(dir, session, {
60
+ ts: now,
61
+ state: existing?.state ?? fallbackState,
62
+ event,
63
+ });
64
+ }
65
+ /** ハートビートファイルを消す(kill 後の掃除)。不在は無視。 */
66
+ export function removeHeartbeat(dir, session) {
67
+ try {
68
+ fs.unlinkSync(heartbeatPath(dir, session));
69
+ }
70
+ catch {
71
+ // 不在等は無視。
72
+ }
73
+ }
74
+ /** dir 配下の全ハートビートのセッション名(tmp 残骸は除外)。 */
75
+ export function listHeartbeatSessions(dir) {
76
+ try {
77
+ return fs
78
+ .readdirSync(dir)
79
+ .filter((name) => !name.includes(".tmp-"))
80
+ .sort();
81
+ }
82
+ catch {
83
+ return [];
84
+ }
85
+ }
86
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/sessions/heartbeat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { SessionInfo, TerminalBackendKind } from "../protocol.js";
2
+ /** 会話 1 行へ載せる生存セッション情報(live-pill)。 */
3
+ export interface LiveSessionAnnotation {
4
+ liveSessionName: string;
5
+ liveSessionBackend: TerminalBackendKind;
6
+ }
7
+ /**
8
+ * 生存セッション一覧を「agent + 会話 id」→ 代表 1 件へ畳む。
9
+ *
10
+ * @param liveSessions `SessionBackend.list()` の結果(alive でないものはここで除外する)。
11
+ * @param createdAtOf セッション名 → メタデータの createdAt(Unix 秒)。不明は null。
12
+ */
13
+ export declare function buildLiveSessionIndex(liveSessions: readonly SessionInfo[], createdAtOf: (name: string) => number | null): Map<string, LiveSessionAnnotation>;
14
+ /** 会話一覧の各行へ生存セッションを join する(一致しない行は素通し = 停止中)。 */
15
+ export declare function annotateLiveSessions<T extends {
16
+ sessionId: string;
17
+ agent?: "claude" | "codex";
18
+ }>(sessions: readonly T[], index: ReadonlyMap<string, LiveSessionAnnotation>): T[];
19
+ /** 生存セッション名の解決(テスト・呼び出し側の可読性用の薄いヘルパ)。 */
20
+ export declare function liveSessionFor(index: ReadonlyMap<string, LiveSessionAnnotation>, conversationId: string, agent?: "claude" | "codex"): LiveSessionAnnotation | undefined;
@@ -0,0 +1,80 @@
1
+ // liveSessionJoin.ts
2
+ // 会話一覧(claude_session_list_response)の各行へ「その会話を収容している生存セッション」を
3
+ // join する純関数群(live-pill)。
4
+ //
5
+ // 背景: iOS の「稼働中」ピルは以前、別 RPC(`session_list_request`, limit 5 ページング)の
6
+ // 結果とアプリ側 join で出していたため、生存セッションが 6 件以上あると母集合から漏れ、
7
+ // pull-to-refresh でも更新されず、一覧注視中の外部死も拾えなかった。host が一覧応答へ
8
+ // 同梱すれば、母集合の欠落も join のタイミングずれも原理的に消える。
9
+ //
10
+ // 同一会話を複数の生存セッションが掴んでいることは起こり得る(同一 session id の第 2
11
+ // インスタンス起動など)。返す名前は iOS の kill 対象になるため、選択は完全に決定的にする:
12
+ // ① 名前が `cs-` で始まるもの(アプリが会話 id から起こした pane)を優先
13
+ // ② メタデータの createdAt 降順(新しい方 = いま操作している側)
14
+ // ③ 名前昇順(同値の最終タイブレーク)
15
+ /**
16
+ * join キー: agent と会話 id の対(agent 省略は claude 相当に正規化する)。
17
+ * agent は enum(claude / codex)なので `::` 区切りで会話 id と衝突しない。
18
+ */
19
+ function joinKey(conversationId, agent) {
20
+ return `${agent ?? "claude"}::${conversationId}`;
21
+ }
22
+ /** アプリ起点 pane(`cs-<会話id先頭>`)の命名規約。 */
23
+ function isAppOriginName(name) {
24
+ return name.startsWith("cs-");
25
+ }
26
+ /**
27
+ * 生存セッション一覧を「agent + 会話 id」→ 代表 1 件へ畳む。
28
+ *
29
+ * @param liveSessions `SessionBackend.list()` の結果(alive でないものはここで除外する)。
30
+ * @param createdAtOf セッション名 → メタデータの createdAt(Unix 秒)。不明は null。
31
+ */
32
+ export function buildLiveSessionIndex(liveSessions, createdAtOf) {
33
+ const candidates = new Map();
34
+ for (const info of liveSessions) {
35
+ if (!info.alive)
36
+ continue;
37
+ const conversationId = info.providerSessionId ?? info.claudeSessionId ?? null;
38
+ if (conversationId === null || conversationId.length === 0)
39
+ continue;
40
+ const key = joinKey(conversationId, info.agent);
41
+ const bucket = candidates.get(key);
42
+ if (bucket === undefined)
43
+ candidates.set(key, [info]);
44
+ else
45
+ bucket.push(info);
46
+ }
47
+ const index = new Map();
48
+ for (const [key, bucket] of candidates) {
49
+ const chosen = [...bucket].sort((lhs, rhs) => {
50
+ const lhsApp = isAppOriginName(lhs.name);
51
+ const rhsApp = isAppOriginName(rhs.name);
52
+ if (lhsApp !== rhsApp)
53
+ return lhsApp ? -1 : 1;
54
+ // createdAt 不明は最劣後(-Infinity 相当)に置く。
55
+ const lhsCreated = createdAtOf(lhs.name) ?? Number.NEGATIVE_INFINITY;
56
+ const rhsCreated = createdAtOf(rhs.name) ?? Number.NEGATIVE_INFINITY;
57
+ if (lhsCreated !== rhsCreated)
58
+ return rhsCreated - lhsCreated;
59
+ return lhs.name < rhs.name ? -1 : lhs.name > rhs.name ? 1 : 0;
60
+ })[0];
61
+ index.set(key, {
62
+ liveSessionName: chosen.name,
63
+ // backend 未指定は後方互換で tmux 相当(session-backend の既存規約に合わせる)。
64
+ liveSessionBackend: chosen.backend ?? "tmux",
65
+ });
66
+ }
67
+ return index;
68
+ }
69
+ /** 会話一覧の各行へ生存セッションを join する(一致しない行は素通し = 停止中)。 */
70
+ export function annotateLiveSessions(sessions, index) {
71
+ return sessions.map((row) => {
72
+ const live = index.get(joinKey(row.sessionId, row.agent));
73
+ return live === undefined ? row : { ...row, ...live };
74
+ });
75
+ }
76
+ /** 生存セッション名の解決(テスト・呼び出し側の可読性用の薄いヘルパ)。 */
77
+ export function liveSessionFor(index, conversationId, agent) {
78
+ return index.get(joinKey(conversationId, agent));
79
+ }
80
+ //# sourceMappingURL=liveSessionJoin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveSessionJoin.js","sourceRoot":"","sources":["../../src/sessions/liveSessionJoin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type ClaudeSessionStore } from "./claudeSessionStore.js";
2
+ import type { CodexSessionStore } from "../codex/codexSessionStore.js";
3
+ import type { SessionInfo } from "../protocol.js";
4
+ import type { SessionMetadataStore } from "./sessionMetadataStore.js";
5
+ /** セッションの更新時刻(Unix 秒)を解決する注入可能な抽象。解決不能は null。 */
6
+ export type SessionActivityProvider = (session: SessionInfo) => number | null;
7
+ /** cwd を Claude Code projects の slug へ写す(共通変換 claudeProjectSlug に委譲)。 */
8
+ export declare function activitySlugForCwd(cwd: string): string;
9
+ /** セッション自身の会話 transcript の mtime を updatedAt として返す既定実装。 */
10
+ export declare function ownTranscriptActivityProvider(options: {
11
+ metadataStore: SessionMetadataStore;
12
+ claudeStore: ClaudeSessionStore;
13
+ codexStore: CodexSessionStore;
14
+ }): SessionActivityProvider;
@@ -0,0 +1,57 @@
1
+ // sessionActivityProvider.ts
2
+ // tailii (TS host) — セッション更新時刻の権威解決(session-list-lifecycle 1.3/1.4)
3
+ // updatedAt = そのセッション自身の最終会話時刻。
4
+ // claude: メタデータの claudeSessionId が指す transcript の最終 timestamp エントリ
5
+ // (lastConversationTimestamp; mtime は resume が状態行追記で進めるため使わない)。
6
+ // codex: 同一 cwd の codex 会話の最新 updatedAt(新規起動は会話 id を永続しないため cwd 近似)。
7
+ // 会話が無い(transcript 不在/状態行のみ)セッションは null = 一覧最下位に沈む。
8
+ // tmux `#{session_activity}` は使わない: セッション作成自体が「活動」として刻まれるため、
9
+ // 会話ゼロの新規セッションがどの実会話よりも上に浮いてしまう(2026-07-08 ユーザー報告の根治)。
10
+ // cwd 単位の共有 mtime(旧実装)も使わない: 同一 cwd の別セッションの会話を継承してしまう。
11
+ import { lastConversationTimestamp } from "./claudeSessionStore.js";
12
+ import { claudeProjectSlug, standardize } from "../shared/paths.js";
13
+ /** cwd を Claude Code projects の slug へ写す(共通変換 claudeProjectSlug に委譲)。 */
14
+ export function activitySlugForCwd(cwd) {
15
+ return claudeProjectSlug(cwd);
16
+ }
17
+ /** セッション自身の会話 transcript の mtime を updatedAt として返す既定実装。 */
18
+ export function ownTranscriptActivityProvider(options) {
19
+ const { metadataStore, claudeStore, codexStore } = options;
20
+ return (session) => {
21
+ let meta;
22
+ try {
23
+ meta = metadataStore.get(session.name);
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ if (!meta)
29
+ return null;
30
+ if (meta.agent === "codex") {
31
+ // codex は新規起動時に会話 id を永続していないため、同一 cwd の会話の最新で近似する。
32
+ const cwd = standardize(meta.cwd);
33
+ let latest = null;
34
+ try {
35
+ for (const info of codexStore.list(cwd)) {
36
+ if (standardize(info.cwd) !== cwd)
37
+ continue;
38
+ if (info.updatedAt !== undefined && (latest === null || info.updatedAt > latest)) {
39
+ latest = info.updatedAt;
40
+ }
41
+ }
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ return latest;
47
+ }
48
+ const sessionId = meta.claudeSessionId;
49
+ if (!sessionId)
50
+ return null;
51
+ const transcript = claudeStore.transcriptPath(sessionId);
52
+ if (transcript === null)
53
+ return null;
54
+ return lastConversationTimestamp(transcript);
55
+ };
56
+ }
57
+ //# sourceMappingURL=sessionActivityProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionActivityProvider.js","sourceRoot":"","sources":["../../src/sessions/sessionActivityProvider.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,oEAAoE;AACpE,gCAAgC;AAChC,mEAAmE;AACnE,wEAAwE;AACxE,sEAAsE;AACtE,oDAAoD;AACpD,6DAA6D;AAC7D,uDAAuD;AACvD,wDAAwD;AAExD,OAAO,EAAE,yBAAyB,EAA2B,MAAM,yBAAyB,CAAC;AAI7F,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKpE,yEAAyE;AACzE,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,6BAA6B,CAAC,OAI7C;IACC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC3D,OAAO,CAAC,OAAO,EAAE,EAAE;QACjB,IAAI,IAAwB,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YAC3B,oDAAoD;YACpD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,MAAM,GAAkB,IAAI,CAAC;YACjC,IAAI,CAAC;gBACH,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxC,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG;wBAAE,SAAS;oBAC5C,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;wBACjF,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;oBAC1B,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC;QACvC,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAC5B,MAAM,UAAU,GAAG,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACrC,OAAO,yBAAyB,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC"}
@@ -1,6 +1,6 @@
1
- import type { SessionInfo } from "./protocol.js";
1
+ import type { SessionInfo } from "../protocol.js";
2
2
  import type { SessionActivityProvider } from "./sessionActivityProvider.js";
3
- import type { TmuxSessionManager } from "./tmux.js";
3
+ import type { SessionBackend } from "../backend/sessionBackend.js";
4
4
  /** 1 ページ分の整列済みセッションと続き位置。 */
5
5
  export interface SessionListPage {
6
6
  sessions: SessionInfo[];
@@ -20,7 +20,7 @@ export declare function decodeSessionListCursor(token: string): CursorKey | null
20
20
  export declare class SessionListService {
21
21
  private readonly sessionManager;
22
22
  private readonly activityProvider;
23
- constructor(sessionManager: TmuxSessionManager, activityProvider: SessionActivityProvider);
23
+ constructor(sessionManager: SessionBackend, activityProvider: SessionActivityProvider);
24
24
  /** 更新時間降順/名前昇順で整列し、cursor より後方を limit 件返す。 */
25
25
  page(limit: number | undefined, cursor: string | undefined): Promise<SessionListPage>;
26
26
  }
@@ -36,15 +36,32 @@ export class SessionListService {
36
36
  /** 更新時間降順/名前昇順で整列し、cursor より後方を limit 件返す。 */
37
37
  async page(limit, cursor) {
38
38
  const raw = await this.sessionManager.list();
39
- // updatedAt を付与する(未解決は省略 = 比較上 0)。
40
- // tmux 由来の per-session 活動時刻(sessionManager.list() が付与)を最優先し、
41
- // 無い場合のみ従来の provider(claude transcript mtime)へフォールバックする。
42
- // これにより同一 cwd の複数セッションでも共有トランスクリプト mtime に潰されず、
43
- // セッション個別の最近使用順で正しく整列する(最新セッションが一覧に埋もれない)。
39
+ // updatedAt を付与する(未解決は省略 = 比較上 0 で最下位)。
40
+ // 権威は provider(セッション自身の会話 transcript の mtime = 最終会話時刻)。
41
+ // tmux の活動時刻や cwd 共有の mtime は使わない: 前者は作成だけで最新になり、
42
+ // 後者は同一 cwd の別セッションの会話を継承するため、どちらも
43
+ // 「会話していないセッションが実会話より上に浮く」誤整列を生む。
44
+ // Codex の activity provider は rollout 一覧を走査する。同一 cwd の複数メタは設計上
45
+ // 同じ updatedAt 近似値になるため、1ページ生成中は cwd ごとに1回だけ解決する。
46
+ // これが無いと過去セッション数に比例して同じ ~/.codex/sessions を再走査し、iOS の
47
+ // 一覧更新を不必要に遅らせる。
48
+ const codexActivityByCwd = new Map();
44
49
  const annotated = raw.map((info) => {
45
50
  if (info.updatedAt !== undefined)
46
51
  return info;
47
- const updatedAt = this.activityProvider(info);
52
+ let updatedAt;
53
+ if (info.agent === "codex") {
54
+ if (codexActivityByCwd.has(info.cwd)) {
55
+ updatedAt = codexActivityByCwd.get(info.cwd) ?? null;
56
+ }
57
+ else {
58
+ updatedAt = this.activityProvider(info);
59
+ codexActivityByCwd.set(info.cwd, updatedAt);
60
+ }
61
+ }
62
+ else {
63
+ updatedAt = this.activityProvider(info);
64
+ }
48
65
  return updatedAt === null ? { ...info } : { ...info, updatedAt };
49
66
  });
50
67
  // (updatedAt desc, name asc) の安定ソート。
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionListService.js","sourceRoot":"","sources":["../../src/sessions/sessionListService.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,20 @@ export interface SessionMeta {
7
7
  agent?: "claude" | "codex";
8
8
  /** Claude の会話 JSONL 名に対応する session-id。未記録は従来どおり最新 JSONL 解決へ戻す。 */
9
9
  claudeSessionId?: string;
10
+ /** provider 共通の論理会話 ID。Claude UUID / Codex thread ID を同じ欄で扱う。 */
11
+ providerSessionId?: string;
12
+ /** runtime を収容する tmux pane の安定 ID(`%N`)。未記録時は session 名へフォールバック。 */
13
+ tmuxPaneId?: string;
14
+ /** セッションを収容する端末バックエンド。未記録は tmux 相当(後方互換)。 */
15
+ backend?: "tmux" | "herdr";
16
+ /** herdr backend のときの pane ID(`w<N>:p<id>`)。herdr への入出力 target。 */
17
+ herdrPaneId?: string;
18
+ /**
19
+ * hub tick がタブへ自動適用した会話タイトル(session-title)。
20
+ * 「ラベル==この値」のタブは自動命名のままとみなし、ai-title の更新へ追随して
21
+ * 再リネームする。人為リネーム(それ以外のラベル)とを区別する権威。
22
+ */
23
+ autoTabTitle?: string;
10
24
  }
11
25
  /** session 名が安全でないときに投げる型付きエラー。 */
12
26
  export declare class InvalidSessionNameError extends Error {
@@ -29,5 +43,9 @@ export declare class SessionMetadataStore {
29
43
  get(name: string): SessionMeta | null;
30
44
  /** 保存済みの全メタデータ(壊れたファイルは無視、順序不定)。 */
31
45
  all(): SessionMeta[];
46
+ /** provider + 会話 ID から現在の tmux メタデータを逆引きする。 */
47
+ findByProviderSessionId(agent: "claude" | "codex", providerSessionId: string): SessionMeta | null;
32
48
  private fileFor;
33
49
  }
50
+ /** herdr pane ID の形式(例 `w4:p2`。実測で英数字混在の pane 連番あり)。 */
51
+ export declare const HERDR_PANE_ID_PATTERN: RegExp;
@@ -5,7 +5,7 @@
5
5
  import * as fs from "node:fs";
6
6
  import * as os from "node:os";
7
7
  import * as path from "node:path";
8
- import { ensureDirectory0700 } from "./paths.js";
8
+ import { ensureDirectory0700 } from "../shared/paths.js";
9
9
  /** session 名が安全でないときに投げる型付きエラー。 */
10
10
  export class InvalidSessionNameError extends Error {
11
11
  constructor(name) {
@@ -45,10 +45,15 @@ export class SessionMetadataStore {
45
45
  // sortedKeys 相当。任意キーは指定時のみ書く(後方互換: 未指定は従来どおりのキー構成)。
46
46
  {
47
47
  ...(meta.agent !== undefined ? { agent: meta.agent } : {}),
48
+ ...(meta.autoTabTitle !== undefined ? { autoTabTitle: meta.autoTabTitle } : {}),
49
+ ...(meta.backend !== undefined ? { backend: meta.backend } : {}),
48
50
  ...(meta.claudeSessionId !== undefined ? { claudeSessionId: meta.claudeSessionId } : {}),
49
51
  createdAt: meta.createdAt,
50
52
  cwd: meta.cwd,
53
+ ...(meta.herdrPaneId !== undefined ? { herdrPaneId: meta.herdrPaneId } : {}),
51
54
  name: meta.name,
55
+ ...(meta.providerSessionId !== undefined ? { providerSessionId: meta.providerSessionId } : {}),
56
+ ...(meta.tmuxPaneId !== undefined ? { tmuxPaneId: meta.tmuxPaneId } : {}),
52
57
  });
53
58
  const target = this.fileFor(meta.name);
54
59
  const tmp = target + ".tmp";
@@ -96,6 +101,18 @@ export class SessionMetadataStore {
96
101
  }
97
102
  return result;
98
103
  }
104
+ /** provider + 会話 ID から現在の tmux メタデータを逆引きする。 */
105
+ findByProviderSessionId(agent, providerSessionId) {
106
+ for (const meta of this.all()) {
107
+ const metaAgent = meta.agent ?? "claude";
108
+ if (metaAgent !== agent)
109
+ continue;
110
+ const id = meta.providerSessionId ?? (metaAgent === "claude" ? meta.claudeSessionId : undefined);
111
+ if (id === providerSessionId)
112
+ return meta;
113
+ }
114
+ return null;
115
+ }
99
116
  fileFor(name) {
100
117
  return path.join(this.base, `${name}.json`);
101
118
  }
@@ -111,12 +128,30 @@ function decodeMeta(raw) {
111
128
  }
112
129
  const agent = obj["agent"] === "codex" || obj["agent"] === "claude" ? obj["agent"] : undefined;
113
130
  const claudeSessionId = typeof obj["claudeSessionId"] === "string" ? obj["claudeSessionId"] : undefined;
131
+ const providerSessionId = typeof obj["providerSessionId"] === "string" ? obj["providerSessionId"] : undefined;
132
+ const tmuxPaneId = typeof obj["tmuxPaneId"] === "string" && /^%\d+$/.test(obj["tmuxPaneId"])
133
+ ? obj["tmuxPaneId"]
134
+ : undefined;
135
+ const backend = obj["backend"] === "herdr" || obj["backend"] === "tmux" ? obj["backend"] : undefined;
136
+ const herdrPaneId = typeof obj["herdrPaneId"] === "string" && HERDR_PANE_ID_PATTERN.test(obj["herdrPaneId"])
137
+ ? obj["herdrPaneId"]
138
+ : undefined;
139
+ const autoTabTitle = typeof obj["autoTabTitle"] === "string" && obj["autoTabTitle"].length > 0
140
+ ? obj["autoTabTitle"]
141
+ : undefined;
114
142
  return {
115
143
  name: obj["name"],
116
144
  cwd: obj["cwd"],
117
145
  createdAt: obj["createdAt"],
118
146
  ...(agent !== undefined ? { agent } : {}),
119
147
  ...(claudeSessionId !== undefined ? { claudeSessionId } : {}),
148
+ ...(providerSessionId !== undefined ? { providerSessionId } : {}),
149
+ ...(tmuxPaneId !== undefined ? { tmuxPaneId } : {}),
150
+ ...(backend !== undefined ? { backend } : {}),
151
+ ...(herdrPaneId !== undefined ? { herdrPaneId } : {}),
152
+ ...(autoTabTitle !== undefined ? { autoTabTitle } : {}),
120
153
  };
121
154
  }
155
+ /** herdr pane ID の形式(例 `w4:p2`。実測で英数字混在の pane 連番あり)。 */
156
+ export const HERDR_PANE_ID_PATTERN = /^w\d+:p[A-Za-z0-9]+$/;
122
157
  //# sourceMappingURL=sessionMetadataStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionMetadataStore.js","sourceRoot":"","sources":["../../src/sessions/sessionMetadataStore.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { ClaudeSessionInfo, SessionSearchResult } from "./protocol.js";
1
+ import type { ClaudeSessionInfo, SessionSearchResult } from "../protocol.js";
2
2
  export interface SessionSearchSource {
3
3
  list(): ClaudeSessionInfo[];
4
4
  transcriptPath(sessionId: string): string | null;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionSearch.js","sourceRoot":"","sources":["../../src/sessions/sessionSearch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** テスト注入用の依存(既定は実環境)。 */
2
+ export interface HostDisplayNameDeps {
3
+ platform: NodeJS.Platform;
4
+ hostname: () => string;
5
+ scutilComputerName: () => string;
6
+ }
7
+ /**
8
+ * マシン名を解決する。空しか得られなければ undefined(hello から hostName を省略する)。
9
+ * 引数省略(実環境)は初回のみ解決してキャッシュする。
10
+ */
11
+ export declare function resolveHostDisplayName(deps?: HostDisplayNameDeps): string | undefined;
@@ -0,0 +1,50 @@
1
+ // hostDisplayName.ts
2
+ // このホストの人間可読なマシン名(channel_hello の hostName)。
3
+ //
4
+ // iOS の接続先一覧が IP しか出せない問題への供給源。ユーザーが「マシン名」として
5
+ // 認識しているのは Finder / AirDrop に出る macOS の ComputerName(日本語可)なので、
6
+ // darwin では `scutil --get ComputerName` を第一候補にし、失敗時と他 OS は
7
+ // `os.hostname()` の `.local` 末尾を落として使う。
8
+ //
9
+ // 解決は engine 起動時に一度だけ(プロセス内で不変とみなす)。失敗しても hello の
10
+ // hostName を省略するだけで機能劣化はない(iOS 側は従来どおり IP 表示へフォールバック)。
11
+ import * as os from "node:os";
12
+ import { execFileSync } from "node:child_process";
13
+ const defaultDeps = {
14
+ platform: process.platform,
15
+ hostname: os.hostname,
16
+ scutilComputerName: () => execFileSync("scutil", ["--get", "ComputerName"], { encoding: "utf8", timeout: 2_000 }),
17
+ };
18
+ /** 実環境解決の結果キャッシュ(プロセス内不変。scutil exec を engine 起動毎に繰り返さない)。 */
19
+ let cachedDefault = null;
20
+ /**
21
+ * マシン名を解決する。空しか得られなければ undefined(hello から hostName を省略する)。
22
+ * 引数省略(実環境)は初回のみ解決してキャッシュする。
23
+ */
24
+ export function resolveHostDisplayName(deps) {
25
+ if (deps === undefined) {
26
+ cachedDefault ??= { value: resolve(defaultDeps) };
27
+ return cachedDefault.value;
28
+ }
29
+ return resolve(deps);
30
+ }
31
+ function resolve(deps) {
32
+ if (deps.platform === "darwin") {
33
+ try {
34
+ const name = deps.scutilComputerName().trim();
35
+ if (name.length > 0)
36
+ return name;
37
+ }
38
+ catch {
39
+ // scutil 不在/失敗は hostname へフォールバック
40
+ }
41
+ }
42
+ try {
43
+ const name = deps.hostname().trim().replace(/\.local$/i, "");
44
+ return name.length > 0 ? name : undefined;
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ //# sourceMappingURL=hostDisplayName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostDisplayName.js","sourceRoot":"","sources":["../../src/shared/hostDisplayName.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,6CAA6C;AAC7C,EAAE;AACF,8CAA8C;AAC9C,+DAA+D;AAC/D,2DAA2D;AAC3D,wCAAwC;AACxC,EAAE;AACF,kDAAkD;AAClD,uDAAuD;AAEvD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASlD,MAAM,WAAW,GAAwB;IACvC,QAAQ,EAAE,OAAO,CAAC,QAAQ;IAC1B,QAAQ,EAAE,EAAE,CAAC,QAAQ;IACrB,kBAAkB,EAAE,GAAG,EAAE,CACvB,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;CAC1F,CAAC;AAEF,8DAA8D;AAC9D,IAAI,aAAa,GAAyC,IAAI,CAAC;AAE/D;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAA0B;IAC/D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,aAAa,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAClD,OAAO,aAAa,CAAC,KAAK,CAAC;IAC7B,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,OAAO,CAAC,IAAyB;IACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC;YAC9C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { Writable } from "node:stream";
2
- import { type ControlMessage } from "./protocol.js";
2
+ import { type ControlMessage } from "../protocol.js";
3
3
  /** 出力ストリームへ `ControlMessage` を NDJSON 行(末尾改行付き)で書き出す。 */
4
4
  export declare class LineWriter {
5
5
  private readonly out;
@@ -1,7 +1,7 @@
1
1
  // lineWriter.ts
2
2
  // tailii (TS host) — ControlMessage を NDJSON 行で直列に書き出す writer
3
3
  // Swift 版 Engine.swift の LineWriter に対応(Node の Writable は書込順序を保証するためロック不要)。
4
- import { encodeControlMessage } from "./protocol.js";
4
+ import { encodeControlMessage } from "../protocol.js";
5
5
  /** 出力ストリームへ `ControlMessage` を NDJSON 行(末尾改行付き)で書き出す。 */
6
6
  export class LineWriter {
7
7
  out;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineWriter.js","sourceRoot":"","sources":["../../src/shared/lineWriter.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,8DAA8D;AAC9D,4EAA4E;AAG5E,OAAO,EAAE,oBAAoB,EAAuB,MAAM,gBAAgB,CAAC;AAE3E,yDAAyD;AACzD,MAAM,OAAO,UAAU;IACQ,GAAG;IAAhC,YAA6B,GAAa;mBAAb,GAAG;IAAa,CAAC;IAE9C,iDAAiD;IACjD,KAAK,CAAC,OAAuB;QAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC7C,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"observationLog.js","sourceRoot":"","sources":["../src/observationLog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"observationLog.js","sourceRoot":"","sources":["../../src/shared/observationLog.ts"],"names":[],"mappings":"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"}
@@ -11,3 +11,10 @@ export declare function isInsideBase(p: string, base: string): boolean;
11
11
  export declare function ensureDirectory0700(dir: string): void;
12
12
  /** シンボリックリンクを解決した canonical パス(解決不能時は字句正準化のみ)。 */
13
13
  export declare function canonicalPath(p: string): string;
14
+ /**
15
+ * cwd → Claude Code の project ディレクトリ名(`~/.claude/projects/<slug>`)。
16
+ * Claude は `/` に加えて `.` も `-` へ置換する(例: `.claude/worktrees/x` →
17
+ * `--claude-worktrees-x`)。`/` だけ置換すると worktree など dot を含む cwd で
18
+ * transcript を見失う(実機で会話が表示されない事故の根因)。
19
+ */
20
+ export declare function claudeProjectSlug(cwd: string): string;