tailii-host 0.1.0 → 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 +35 -14
  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
@@ -9,15 +9,16 @@ import * as os from "node:os";
9
9
  import * as path from "node:path";
10
10
  import { TranscriptTailer } from "./transcriptTailer.js";
11
11
  import { SubagentTailer } from "./subagentTailer.js";
12
- import { CodexRolloutTailer } from "./codexRolloutTailer.js";
13
- import { canonicalPath } from "./paths.js";
12
+ import { readBackgroundOutput, readCodexSubagentTranscript, readSubagentTranscript, } from "./subagentTranscript.js";
13
+ import { CodexRolloutTailer, } from "../codex/codexRolloutTailer.js";
14
+ import { canonicalPath, claudeProjectSlug } from "../shared/paths.js";
14
15
  /** セッション連動で transcript を tail し chat_output を engine チャネルへ流す制御子。 */
15
16
  export class ChatTailController {
16
17
  writer;
17
18
  tailer;
18
19
  subagentTailer;
19
20
  projectsRoot;
20
- /** チャット添付(user 発話の `@"path"`)のサムネ発行に使う。null なら発行しない。 */
21
+ /** チャット添付(user 発話の `@"path"` / Tailii upload path)のサムネ発行に使う。 */
21
22
  imageService;
22
23
  /** subagent_node の送出可否を判断する negotiated protocol version。 */
23
24
  protocolVersion;
@@ -47,6 +48,25 @@ export class ChatTailController {
47
48
  this.openAgent = this.agent;
48
49
  this.codexTailer =
49
50
  options.codexTailer ?? new CodexRolloutTailer({ tailIndefinitely: true, emitReplayDoneMarker: true });
51
+ if (options.onCodexTurnLifecycle !== undefined) {
52
+ this.codexTailer.setTurnLifecycleObserver(options.onCodexTurnLifecycle);
53
+ }
54
+ }
55
+ /** 全文取得要求向けに、現在の subagent transcript パスを解決する。 */
56
+ subagentTranscriptPath(nodeId) {
57
+ return this.subagentTailer.jsonlPath(nodeId);
58
+ }
59
+ /** Hub からのオンデマンド要求に、現在 tail 中のノード全文を返す。 */
60
+ subagentTranscript(nodeId) {
61
+ if (this.openAgent === "codex" && this.currentDir !== null) {
62
+ const rollout = this.codexTailer.resolve(this.currentDir, null, nodeId);
63
+ return readCodexSubagentTranscript(rollout);
64
+ }
65
+ const jsonl = this.subagentTranscriptPath(nodeId);
66
+ if (jsonl !== null)
67
+ return readSubagentTranscript(jsonl);
68
+ // バックグラウンドコマンドは jsonl を持たないので、出力ファイルの末尾を返す。
69
+ return readBackgroundOutput(this.subagentTailer.outputPath(nodeId));
50
70
  }
51
71
  /**
52
72
  * `cwd` からそのセッションの project dir を解決し、transcript tail を開始/切替する。
@@ -59,13 +79,13 @@ export class ChatTailController {
59
79
  }
60
80
  this.openAgent = agent;
61
81
  if (agent === "codex") {
62
- this.openCodex(cwd, newerThanMs);
82
+ this.openCodex(cwd, preferredSessionId, newerThanMs);
63
83
  return;
64
84
  }
65
85
  // claude はシンボリックリンクを解決した canonical パスで project slug を作る
66
86
  //(例 /tmp → /private/tmp)。tail も同じく解決してから slug 化する。
67
87
  const canonicalCwd = canonicalPath(cwd);
68
- const slug = canonicalCwd.replaceAll("/", "-");
88
+ const slug = claudeProjectSlug(cwd);
69
89
  const dir = path.join(this.projectsRoot, slug);
70
90
  const dirExists = fs.existsSync(dir);
71
91
  ChatTailController.diag(`open cwd=${cwd} preferred=${preferredSessionId ?? "nil"} dir=${dir} dirExists=${dirExists}`);
@@ -84,6 +104,17 @@ export class ChatTailController {
84
104
  const { writer, tailer, subagentTailer, imageService, protocolVersion } = this;
85
105
  this.currentPump = (async () => {
86
106
  ChatTailController.diag(`tail task started for dir=${dir} newerThan=${newerThanMs === null ? "nil" : String(newerThanMs)}`);
107
+ // この tail で添付(att-)として image_available を発行済みの原本パス
108
+ // (chat-image-dedupe)。添付で表示済みの画像を Claude が Read すると
109
+ // read-<toolUseId> でも再発行され、iOS の imageId 冪等ガードを素通りして
110
+ // 同一画像のサムネが2枚並ぶため、att- 由来のパスに限り read- 側を抑止する。
111
+ // transcript 上は必ず user 行(att-)が Read(read-)より先に現れるため、
112
+ // pump ローカルの集合で決定的に働く。
113
+ // Read→Read の同一パスは抑止しない: 反復レンダリング(同名ファイルへ再出力→再 Read)
114
+ // では内容が毎回変わり、初回 Read の id に発行を独占させると最新の Read カードに
115
+ // 画像が付かず、初回アンカーがキャッシュ窓外の端末では1枚も表示されない
116
+ // (chat-image-reread。Lab 会話の実障害)。各 Read の id で毎回発行する。
117
+ const attachedImagePaths = new Set();
87
118
  let count = 0;
88
119
  try {
89
120
  for await (const message of tailer.streamProjectDir(dir, preferredSessionId, newerThanMs, ac.signal)) {
@@ -91,27 +122,40 @@ export class ChatTailController {
91
122
  ChatTailController.diag(`tail cancelled (emitted ${count})`);
92
123
  break;
93
124
  }
125
+ // AskUserQuestion のライフサイクルは hook relay(question_event → engine)が唯一の
126
+ // ソース。Claude Code は設問が未回答の間 transcript に tool_use 行を書かない
127
+ // (v2.1.206 実測)ため、tail に現れる question_prompt/question_dismiss は常に
128
+ // 「回答済みの残骸」であり、履歴 replay や回答時 flush のたびに現行の設問シートを
129
+ // 上書き・消灯してしまう(再オープン時にモーダルが一瞬出て消えるバグ)。転送しない。
130
+ if (message.type === "question_prompt" || message.type === "question_dismiss") {
131
+ continue;
132
+ }
94
133
  count += 1;
95
134
  if (count <= 3 || count % 25 === 0)
96
135
  ChatTailController.diag(`emit chat_output #${count}`);
97
136
  try {
98
137
  writer.write(message);
99
- // user 発話中の添付画像(@"path")はサムネ(image_available)を後続で発行し、
138
+ // user 発話中の添付画像(@"path" / Tailii upload path)は
139
+ // サムネ(image_available)を後続で発行し、
100
140
  // iOS にインライン表示させる(chat-attachments)。id は決定的(att-<streamId>-<n>)。
101
141
  if (imageService !== null && message.type === "chat_output" && message.role === "user") {
102
142
  const paths = ChatTailController.attachmentImagePaths(message.text);
103
143
  for (let n = 0; n < paths.length; n += 1) {
104
144
  const available = await imageService.makeAvailable(paths[n], `att-${message.streamId}-${n}`);
105
- if (available !== null)
145
+ if (available !== null) {
146
+ attachedImagePaths.add(paths[n]);
106
147
  writer.write(available);
148
+ }
107
149
  }
108
150
  }
109
151
  // Read ツールで画像ファイルを読んだら、そのサムネ(image_available)を後続で発行し
110
152
  // iOS にインライン表示させる(既存 chat-attachments と同じ描画経路を再利用)。
111
153
  // id は tool_use id 由来で決定的(read-<id>)→ 再 tail/再オープンでも二重挿入されない。
154
+ // 添付(att-)で発行済みのパスだけ再発行しない(同一画像のサムネ二重表示防止)。
155
+ // 同一パスの再 Read はその Read の id で毎回発行する(chat-image-reread)。
112
156
  if (imageService !== null && message.type === "tool_activity") {
113
157
  const readPath = ChatTailController.readImagePath(message.activity);
114
- if (readPath !== null) {
158
+ if (readPath !== null && !attachedImagePaths.has(readPath)) {
115
159
  const available = await imageService.makeAvailable(readPath, `read-${message.activity.id}`);
116
160
  if (available !== null)
117
161
  writer.write(available);
@@ -152,11 +196,12 @@ export class ChatTailController {
152
196
  })();
153
197
  }
154
198
  /**
155
- * codex モードの tail 開始/切替。claude の slug/subagent/添付は使わず、
156
- * cwd から rollout を解決して chat_output を流す。同一 rollout への張り直しはスキップする。
199
+ * codex モードの tail 開始/切替。Claude の slug/subagent transcript 監視は使わず、
200
+ * cwd から rollout を解決して chat_output を流す。Codex sub-agent の進捗は App Server の
201
+ * collabAgentToolCall を CodexNativeTurnController が subagent_node へ変換する。
157
202
  */
158
- openCodex(cwd, newerThanMs) {
159
- const resolvedNow = this.codexTailer.resolve(cwd, newerThanMs);
203
+ openCodex(cwd, preferredSessionId, newerThanMs) {
204
+ const resolvedNow = this.codexTailer.resolve(cwd, newerThanMs, preferredSessionId);
160
205
  if (resolvedNow !== null && this.currentPump !== null && resolvedNow === this.currentResolvedPath) {
161
206
  ChatTailController.diag(`openCodex skipped: same rollout already tailing (${resolvedNow})`);
162
207
  return;
@@ -165,16 +210,16 @@ export class ChatTailController {
165
210
  const ac = new AbortController();
166
211
  this.abortController = ac;
167
212
  this.currentDir = cwd;
168
- this.currentPreferred = null;
213
+ this.currentPreferred = preferredSessionId;
169
214
  this.currentNewerThanMs = newerThanMs;
170
215
  this.currentResolvedPath = resolvedNow;
171
216
  this.currentSubagentPump = null;
172
217
  const { writer, codexTailer } = this;
173
- ChatTailController.diag(`openCodex cwd=${cwd} newerThan=${newerThanMs === null ? "nil" : String(newerThanMs)} resolved=${resolvedNow ?? "nil"}`);
218
+ ChatTailController.diag(`openCodex cwd=${cwd} preferred=${preferredSessionId ?? "nil"} newerThan=${newerThanMs === null ? "nil" : String(newerThanMs)} resolved=${resolvedNow ?? "nil"}`);
174
219
  this.currentPump = (async () => {
175
220
  let count = 0;
176
221
  try {
177
- for await (const message of codexTailer.streamForCwd(cwd, newerThanMs, ac.signal)) {
222
+ for await (const message of codexTailer.streamForCwd(cwd, newerThanMs, ac.signal, preferredSessionId)) {
178
223
  if (ac.signal.aborted)
179
224
  break;
180
225
  count += 1;
@@ -200,11 +245,11 @@ export class ChatTailController {
200
245
  ]);
201
246
  /**
202
247
  * user 発話テキストから添付「画像」ファイルの絶対パスを抽出する(chat-attachments, TESTABLE)。
203
- * `@"/path with space.png"`(引用形式)と `@/path/to/file.png`(非引用)の両方を対象にする。
248
+ * `@"/path with space.png"`(引用形式)、`@/path/to/file.png`(非引用)に加え、
249
+ * iOS の添付チップが本文へ合成する裸の `~/.tailii/uploads/<name>` も対象にする。
250
+ * 裸パスは Tailii 管理配下に限定し、通常本文の任意の画像パスを添付と誤認しない。
204
251
  */
205
252
  static attachmentImagePaths(text) {
206
- if (!text.includes("@"))
207
- return [];
208
253
  const paths = [];
209
254
  for (const match of text.matchAll(/@"(\/[^"]+)"/g)) {
210
255
  if (match[1] !== undefined)
@@ -214,6 +259,12 @@ export class ChatTailController {
214
259
  if (match[1] !== undefined)
215
260
  paths.push(match[1]);
216
261
  }
262
+ // MessageInputBar.composeOutgoing は upload 済みパスを @ なしで本文先頭へ置く。
263
+ // ファイル名は iOS 側で安全な文字へ正規化済みなので、空白/引用符を境界に抽出できる。
264
+ for (const match of text.matchAll(/(?:^|[\s"])(\/(?:[^\s"]*\/)?\.tailii\/uploads\/[^\s"]+)/g)) {
265
+ if (match[1] !== undefined)
266
+ paths.push(match[1]);
267
+ }
217
268
  const seen = new Set();
218
269
  return paths.filter((p) => {
219
270
  const ext = path.extname(p).slice(1).toLowerCase();
@@ -266,6 +317,31 @@ export class ChatTailController {
266
317
  currentAgent() {
267
318
  return this.openAgent;
268
319
  }
320
+ /**
321
+ * kill された tmux セッションのメタから、その会話を tail 中なら tail を停止する。
322
+ *
323
+ * tail を生かしたままだと、次の再オープン(session_start)の `open()` が
324
+ * 「同一会話を tail 中」としてスキップして履歴を再生しない。kill 後の再オープンは
325
+ * tmux 名が変わり得る(生存別名 → `cs-<id>`)ためクライアントのキャッシュも外れ、
326
+ * 何も表示されなくなる。kill の全経路(session_kill / idle reaper / 処理完了時 kill)
327
+ * から呼ぶこと。
328
+ */
329
+ stopIfSession(meta) {
330
+ if (meta === null || this.currentPump === null)
331
+ return;
332
+ if (this.openAgent === "codex") {
333
+ // codex は会話 id 束縛を持たないため cwd 一致で判定する(openCodex の解決単位)。
334
+ if (meta.agent === "codex" && meta.cwd === this.currentDir) {
335
+ ChatTailController.diag(`stopIfSession: codex tail 停止 cwd=${meta.cwd}`);
336
+ this.stop();
337
+ }
338
+ return;
339
+ }
340
+ if (meta.claudeSessionId !== undefined && meta.claudeSessionId === this.currentPreferred) {
341
+ ChatTailController.diag(`stopIfSession: claude tail 停止 claudeSessionId=${meta.claudeSessionId}`);
342
+ this.stop();
343
+ }
344
+ }
269
345
  /** tail を停止する(engine チャネル断)。 */
270
346
  stop() {
271
347
  this.abortController?.abort();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatTailController.js","sourceRoot":"","sources":["../../src/chat/chatTailController.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type ControlMessage } from "./protocol.js";
1
+ import { type ControlMessage } from "../protocol.js";
2
2
  /** サムネ生成結果(サムネ画像 base64 + 原寸)。base64 は HEIC(環境非対応時は PNG)。 */
3
3
  export interface ThumbnailResult {
4
4
  /**
@@ -7,11 +7,15 @@ export interface ThumbnailResult {
7
7
  * 形式を自動判定するため、どちらでも復号できる。
8
8
  */
9
9
  thumbnailBase64: string;
10
+ /** 実際に生成したサムネ形式。旧注入実装との互換のため省略可。 */
11
+ imageFormat?: "heic" | "png";
10
12
  width: number;
11
13
  height: number;
12
14
  }
13
15
  /** サムネ生成の注入可能な抽象。読めない/画像でない場合は null。 */
14
16
  export type Thumbnailer = (imagePath: string, maxPixelSize: number) => Promise<ThumbnailResult | null>;
17
+ /** 画像として扱う拡張子集合(小文字・ドットなし)。 */
18
+ export declare const IMAGE_EXTENSIONS: Set<string>;
15
19
  export declare function mimeTypeForExtension(ext: string): string;
16
20
  /** macOS 標準 `sips` によるサムネ生成(既定 thumbnailer)。 */
17
21
  export declare function sipsThumbnailer(sipsPath?: string): Thumbnailer;
@@ -21,6 +25,13 @@ export declare class ImageService {
21
25
  private readonly indexBase;
22
26
  private readonly thumbnailMaxPixelSize;
23
27
  private readonly thumbnailer;
28
+ /**
29
+ * サムネ生成結果のメモ(key = path + mtimeMs + size)。同一パスの再 Read を毎回発行する
30
+ * ようになった(chat-image-reread)ため、replay で同じ未変更ファイルに sips を何十回も
31
+ * 走らせない。ファイルが書き換われば mtime/size が変わり自然に再生成される。
32
+ */
33
+ private readonly thumbnailMemo;
34
+ private static readonly THUMBNAIL_MEMO_LIMIT;
24
35
  constructor(options?: {
25
36
  pendingBase?: string;
26
37
  indexBase?: string;
@@ -11,12 +11,12 @@ import { execFile } from "node:child_process";
11
11
  import * as fs from "node:fs";
12
12
  import * as os from "node:os";
13
13
  import * as path from "node:path";
14
- import { PROTOCOL_V1 } from "./protocol.js";
15
- import { ensureDirectory0700 } from "./paths.js";
14
+ import { PROTOCOL_V1 } from "../protocol.js";
15
+ import { ensureDirectory0700 } from "../shared/paths.js";
16
16
  /** 原本 fetch の分割チャンクサイズ(生バイト, ≈32KiB)。base64 化前の生バイトで数える。 */
17
17
  const FETCH_CHUNK_SIZE = 32 * 1024;
18
18
  /** 画像として扱う拡張子集合(小文字・ドットなし)。 */
19
- const IMAGE_EXTENSIONS = new Set([
19
+ export const IMAGE_EXTENSIONS = new Set([
20
20
  "png", "jpg", "jpeg", "gif", "webp", "heic", "heif", "bmp", "tiff", "tif",
21
21
  ]);
22
22
  /** 拡張子 → mime(index に mime を持たないため拡張子起点)。 */
@@ -67,7 +67,7 @@ export function sipsThumbnailer(sipsPath = "/usr/bin/sips") {
67
67
  ]);
68
68
  if (convert.code !== 0)
69
69
  return null;
70
- return fs.readFileSync(tmp).toString("base64");
70
+ return { base64: fs.readFileSync(tmp).toString("base64"), format };
71
71
  }
72
72
  catch {
73
73
  return null;
@@ -81,10 +81,15 @@ export function sipsThumbnailer(sipsPath = "/usr/bin/sips") {
81
81
  }
82
82
  }
83
83
  };
84
- const base64 = (await attempt("heic")) ?? (await attempt("png"));
85
- if (base64 === null)
84
+ const converted = (await attempt("heic")) ?? (await attempt("png"));
85
+ if (converted === null)
86
86
  return null;
87
- return { thumbnailBase64: base64, width, height };
87
+ return {
88
+ thumbnailBase64: converted.base64,
89
+ imageFormat: converted.format,
90
+ width,
91
+ height,
92
+ };
88
93
  };
89
94
  }
90
95
  function parseSipsProperty(stdout, name) {
@@ -100,6 +105,13 @@ export class ImageService {
100
105
  indexBase;
101
106
  thumbnailMaxPixelSize;
102
107
  thumbnailer;
108
+ /**
109
+ * サムネ生成結果のメモ(key = path + mtimeMs + size)。同一パスの再 Read を毎回発行する
110
+ * ようになった(chat-image-reread)ため、replay で同じ未変更ファイルに sips を何十回も
111
+ * 走らせない。ファイルが書き換われば mtime/size が変わり自然に再生成される。
112
+ */
113
+ thumbnailMemo = new Map();
114
+ static THUMBNAIL_MEMO_LIMIT = 256;
103
115
  constructor(options = {}) {
104
116
  const home = os.homedir();
105
117
  this.pendingBase = options.pendingBase ?? path.join(home, ".tailii", "images", "pending");
@@ -191,10 +203,26 @@ export class ImageService {
191
203
  if (!IMAGE_EXTENSIONS.has(ext)) {
192
204
  return { type: "error", v: PROTOCOL_V1, id: imageId, code: "not_an_image", message: "画像として扱えません" };
193
205
  }
194
- // サムネ生成 + 原寸取得。読み取り不可 / 画像でない → not_an_image
195
- const thumb = await this.thumbnailer(imagePath, this.thumbnailMaxPixelSize);
196
- if (thumb === null) {
197
- return { type: "error", v: PROTOCOL_V1, id: imageId, code: "not_an_image", message: "画像として読み取れません" };
206
+ // サムネ生成 + 原寸取得。読み取り不可 / 画像でない → not_an_image。
207
+ // 未変更ファイル(path + mtime + size 一致)はメモ命中で sips を再実行しない。
208
+ const memoKey = `${imagePath}\u0000${stat.mtimeMs}\u0000${stat.size}`;
209
+ let thumb = this.thumbnailMemo.get(memoKey) ?? null;
210
+ if (thumb !== null) {
211
+ // 命中エントリを末尾へ移して LRU 順を保つ。
212
+ this.thumbnailMemo.delete(memoKey);
213
+ this.thumbnailMemo.set(memoKey, thumb);
214
+ }
215
+ else {
216
+ thumb = await this.thumbnailer(imagePath, this.thumbnailMaxPixelSize);
217
+ if (thumb === null) {
218
+ return { type: "error", v: PROTOCOL_V1, id: imageId, code: "not_an_image", message: "画像として読み取れません" };
219
+ }
220
+ this.thumbnailMemo.set(memoKey, thumb);
221
+ if (this.thumbnailMemo.size > ImageService.THUMBNAIL_MEMO_LIMIT) {
222
+ const oldest = this.thumbnailMemo.keys().next().value;
223
+ if (oldest !== undefined)
224
+ this.thumbnailMemo.delete(oldest);
225
+ }
198
226
  }
199
227
  // 生成成功時のみ id→path を index に記録
200
228
  try {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageService.js","sourceRoot":"","sources":["../../src/chat/imageService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { LineWriter } from "../shared/lineWriter.js";
2
+ import type { SessionMetadataStore } from "../sessions/sessionMetadataStore.js";
3
+ import type { SessionBackend } from "../backend/sessionBackend.js";
4
+ export declare class RemoteQuestionMonitor {
5
+ private readonly sessionManager;
6
+ private readonly metadataStore;
7
+ private readonly projectsRoot;
8
+ private readonly writer;
9
+ private readonly activeSession;
10
+ private readonly pollIntervalMs;
11
+ private readonly pumps;
12
+ private loopAbort;
13
+ private loopTask;
14
+ constructor(options: {
15
+ sessionManager: SessionBackend;
16
+ metadataStore: SessionMetadataStore;
17
+ projectsRoot: string;
18
+ writer: LineWriter;
19
+ activeSession: () => string | null;
20
+ pollIntervalMs?: number;
21
+ });
22
+ start(): void;
23
+ stop(): void;
24
+ private run;
25
+ private syncOnce;
26
+ private startPump;
27
+ }
@@ -0,0 +1,128 @@
1
+ // remoteQuestionMonitor.ts
2
+ // tailii (TS host) — foreground connected 中に別 conversation の AskUserQuestion を検知する軽量 monitor。
3
+ import * as path from "node:path";
4
+ import { claudeProjectSlug } from "../shared/paths.js";
5
+ import { PROTOCOL_V1 } from "../protocol.js";
6
+ import { abortableSleep } from "../shared/sleep.js";
7
+ import { HISTORY_DONE_STREAM_ID, TranscriptTailer } from "./transcriptTailer.js";
8
+ export class RemoteQuestionMonitor {
9
+ sessionManager;
10
+ metadataStore;
11
+ projectsRoot;
12
+ writer;
13
+ activeSession;
14
+ pollIntervalMs;
15
+ pumps = new Map();
16
+ loopAbort = null;
17
+ loopTask = null;
18
+ constructor(options) {
19
+ this.sessionManager = options.sessionManager;
20
+ this.metadataStore = options.metadataStore;
21
+ this.projectsRoot = options.projectsRoot;
22
+ this.writer = options.writer;
23
+ this.activeSession = options.activeSession;
24
+ this.pollIntervalMs = options.pollIntervalMs ?? 1000;
25
+ }
26
+ start() {
27
+ if (this.loopTask !== null)
28
+ return;
29
+ const ac = new AbortController();
30
+ this.loopAbort = ac;
31
+ this.loopTask = this.run(ac.signal);
32
+ this.loopTask.catch(() => { });
33
+ }
34
+ stop() {
35
+ this.loopAbort?.abort();
36
+ this.loopAbort = null;
37
+ this.loopTask = null;
38
+ for (const pump of this.pumps.values())
39
+ pump.abort();
40
+ this.pumps.clear();
41
+ }
42
+ async run(signal) {
43
+ while (!signal.aborted) {
44
+ await this.syncOnce(signal);
45
+ await abortableSleep(this.pollIntervalMs, signal);
46
+ }
47
+ }
48
+ async syncOnce(signal) {
49
+ let live = new Set();
50
+ try {
51
+ live = new Set((await this.sessionManager.list()).filter((s) => s.alive).map((s) => s.name));
52
+ }
53
+ catch {
54
+ live = new Set();
55
+ }
56
+ const active = this.activeSession();
57
+ const wanted = new Map();
58
+ for (const meta of this.metadataStore.all()) {
59
+ if (!live.has(meta.name))
60
+ continue;
61
+ if (meta.name === active)
62
+ continue;
63
+ if ((meta.agent ?? "claude") !== "claude")
64
+ continue;
65
+ if (meta.claudeSessionId === undefined)
66
+ continue;
67
+ wanted.set(meta.name, meta);
68
+ }
69
+ for (const name of this.pumps.keys()) {
70
+ if (!wanted.has(name)) {
71
+ this.pumps.get(name)?.abort();
72
+ this.pumps.delete(name);
73
+ }
74
+ }
75
+ for (const meta of wanted.values()) {
76
+ if (this.pumps.has(meta.name))
77
+ continue;
78
+ this.startPump(meta, signal);
79
+ }
80
+ }
81
+ startPump(meta, parentSignal) {
82
+ const ac = new AbortController();
83
+ this.pumps.set(meta.name, ac);
84
+ const dir = path.join(this.projectsRoot, claudeProjectSlug(meta.cwd));
85
+ const tailer = new TranscriptTailer({ tailIndefinitely: true, emitReplayDoneMarker: true });
86
+ (async () => {
87
+ let replayDone = false;
88
+ try {
89
+ for await (const message of tailer.streamProjectDir(dir, meta.claudeSessionId ?? null, null, ac.signal)) {
90
+ if (parentSignal.aborted || ac.signal.aborted)
91
+ break;
92
+ if (message.type === "chat_output" && message.streamId === HISTORY_DONE_STREAM_ID) {
93
+ replayDone = true;
94
+ continue;
95
+ }
96
+ if (!replayDone)
97
+ continue;
98
+ if (message.type === "question_prompt") {
99
+ const first = message.questions[0];
100
+ const summary = first?.question || first?.header || "Question prompt";
101
+ this.writer.write({
102
+ type: "remote_pending",
103
+ v: PROTOCOL_V1,
104
+ id: message.id,
105
+ session: meta.name,
106
+ kind: "question",
107
+ summary,
108
+ });
109
+ }
110
+ else if (message.type === "question_dismiss") {
111
+ this.writer.write({
112
+ type: "remote_pending_cleared",
113
+ v: PROTOCOL_V1,
114
+ id: message.id,
115
+ session: meta.name,
116
+ kind: "question",
117
+ });
118
+ }
119
+ }
120
+ }
121
+ finally {
122
+ if (this.pumps.get(meta.name) === ac)
123
+ this.pumps.delete(meta.name);
124
+ }
125
+ })().catch(() => { });
126
+ }
127
+ }
128
+ //# sourceMappingURL=remoteQuestionMonitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteQuestionMonitor.js","sourceRoot":"","sources":["../../src/chat/remoteQuestionMonitor.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,8FAA8F;AAE9F,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGjF,MAAM,OAAO,qBAAqB;IACf,cAAc,CAAiB;IAC/B,aAAa,CAAuB;IACpC,YAAY,CAAS;IACrB,MAAM,CAAa;IACnB,aAAa,CAAsB;IACnC,cAAc,CAAS;IACvB,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;IACpD,SAAS,GAA2B,IAAI,CAAC;IACzC,QAAQ,GAAyB,IAAI,CAAC;IAE9C,YAAY,OAOX;QACC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC;IACvD,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO;QACnC,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,IAAI;QACF,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,MAAmB;QACnC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5B,MAAM,cAAc,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,MAAmB;QACxC,IAAI,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/F,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC3B,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YACnC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS;YACnC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,QAAQ;gBAAE,SAAS;YACpD,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;gBAAE,SAAS;YACjD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YACxC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,IAAiB,EAAE,YAAyB;QAC5D,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5F,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,MAAM,CAAC,gBAAgB,CACjD,GAAG,EACH,IAAI,CAAC,eAAe,IAAI,IAAI,EAC5B,IAAI,EACJ,EAAE,CAAC,MAAM,CACV,EAAE,CAAC;oBACF,IAAI,YAAY,CAAC,OAAO,IAAI,EAAE,CAAC,MAAM,CAAC,OAAO;wBAAE,MAAM;oBACrD,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,sBAAsB,EAAE,CAAC;wBAClF,UAAU,GAAG,IAAI,CAAC;wBAClB,SAAS;oBACX,CAAC;oBACD,IAAI,CAAC,UAAU;wBAAE,SAAS;oBAC1B,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;wBACvC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;wBACnC,MAAM,OAAO,GAAG,KAAK,EAAE,QAAQ,IAAI,KAAK,EAAE,MAAM,IAAI,iBAAiB,CAAC;wBACtE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;4BAChB,IAAI,EAAE,gBAAgB;4BACtB,CAAC,EAAE,WAAW;4BACd,EAAE,EAAE,OAAO,CAAC,EAAE;4BACd,OAAO,EAAE,IAAI,CAAC,IAAI;4BAClB,IAAI,EAAE,UAAU;4BAChB,OAAO;yBACR,CAAC,CAAC;oBACL,CAAC;yBAAM,IAAI,OAAO,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;wBAC/C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;4BAChB,IAAI,EAAE,wBAAwB;4BAC9B,CAAC,EAAE,WAAW;4BACd,EAAE,EAAE,OAAO,CAAC,EAAE;4BACd,OAAO,EAAE,IAAI,CAAC,IAAI;4BAClB,IAAI,EAAE,UAAU;yBACjB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;oBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrE,CAAC;QACH,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ import { type ControlMessage } from "../protocol.js";
2
+ export interface SubagentTailerOptions {
3
+ /** 追記ポーリング間隔(ms)。既定 50ms。 */
4
+ pollIntervalMs?: number;
5
+ /** EOF 後も abort まで無期限に tail するか。既定 true。 */
6
+ tailIndefinitely?: boolean;
7
+ /** 孤児判定を始めるまでの起動猶予(ms)。既定 60s。 */
8
+ orphanGraceMs?: number;
9
+ /** 孤児判定プローブの間隔(ms)。既定 30s。 */
10
+ orphanProbeIntervalMs?: number;
11
+ /** output ファイルを開いているプロセスの有無(null=判定不能)。テスト差し替え用。 */
12
+ probeOutputOpen?: (filePath: string) => Promise<boolean | null>;
13
+ }
14
+ /** サブエージェント meta/jsonl と親 transcript の tool_result を監視する。 */
15
+ export declare class SubagentTailer {
16
+ private readonly pollIntervalMs;
17
+ private readonly tailIndefinitely;
18
+ private readonly orphanGraceMs;
19
+ private readonly orphanProbeIntervalMs;
20
+ private readonly probeOutputOpen;
21
+ private readonly jsonlPaths;
22
+ private readonly outputPaths;
23
+ constructor(options?: SubagentTailerOptions);
24
+ /** 現在 tail 中の nodeId から transcript 実体を引く。 */
25
+ jsonlPath(nodeId: string): string | null;
26
+ /** バックグラウンドコマンドの nodeId(taskId) から出力ファイルを引く。 */
27
+ outputPath(nodeId: string): string | null;
28
+ streamProjectDir(projectDir: string, preferredSessionId: string | null, newerThanMs?: number | null, signal?: AbortSignal): AsyncGenerator<ControlMessage, void, void>;
29
+ streamSession(mainTranscript: string, signal?: AbortSignal): AsyncGenerator<ControlMessage, void, void>;
30
+ }