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
@@ -0,0 +1,1036 @@
1
+ // protocol/decode.ts
2
+ // NDJSON 1 行 → ControlMessage のデコード。未知 type / 非対応版 / 必須欠落は
3
+ // ProtocolDecodeError(呼び出し元は安全側 = 破棄/deny に倒す)。
4
+ import { PROTOCOL_LEGACY, PROTOCOL_MAX_SUPPORTED, } from "./messages.js";
5
+ import { compact, optionalBoolean, optionalNullableString, optionalNumber, optionalString, ProtocolDecodeError, requireArray, requireBoolean, requireNumber, requireObject, requireString, requireStringArray, } from "./common.js";
6
+ // MARK: - decode
7
+ /** NDJSON 1 行(改行なし)を `ControlMessage` へデコードする。失敗は `ProtocolDecodeError`。 */
8
+ export function decodeControlMessage(line) {
9
+ const text = typeof line === "string" ? line : line.toString("utf8");
10
+ let parsed;
11
+ try {
12
+ parsed = JSON.parse(text);
13
+ }
14
+ catch {
15
+ throw new ProtocolDecodeError("invalid-json", text.slice(0, 80));
16
+ }
17
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
18
+ throw new ProtocolDecodeError("invalid-json", "not an object");
19
+ }
20
+ const raw = parsed;
21
+ const type = raw["type"];
22
+ if (typeof type !== "string")
23
+ throw new ProtocolDecodeError("missing-type", text.slice(0, 80));
24
+ // v 欠落 = v0 レガシー(承認 2 型のみ復元。他は破棄 = throw)。
25
+ const rawV = raw["v"];
26
+ const v = typeof rawV === "number" ? rawV : PROTOCOL_LEGACY;
27
+ if (v > PROTOCOL_MAX_SUPPORTED)
28
+ throw new ProtocolDecodeError("unsupported-version", String(v));
29
+ if (v === PROTOCOL_LEGACY && type !== "approval_request" && type !== "approval_decision") {
30
+ throw new ProtocolDecodeError("legacy-unsupported-type", type);
31
+ }
32
+ switch (type) {
33
+ case "channel_hello":
34
+ return compact({ type, v, maxVersion: requireNumber(raw, "maxVersion"), serverVersion: optionalString(raw, "serverVersion"), hostName: optionalString(raw, "hostName") });
35
+ case "approval_request":
36
+ return compact({
37
+ type, v,
38
+ id: requireString(raw, "id"),
39
+ tool: requireString(raw, "tool"),
40
+ summary: requireString(raw, "summary"),
41
+ cwd: requireString(raw, "cwd"),
42
+ diff: decodeToolDiff(raw["diff"]),
43
+ });
44
+ case "approval_decision": {
45
+ const decision = requireString(raw, "decision");
46
+ if (decision !== "allow" && decision !== "deny") {
47
+ throw new ProtocolDecodeError("missing-field", "decision");
48
+ }
49
+ return compact({
50
+ type, v,
51
+ id: requireString(raw, "id"),
52
+ decision,
53
+ reason: optionalString(raw, "reason"),
54
+ });
55
+ }
56
+ case "remote_pending": {
57
+ const kind = requireRemotePendingKind(raw);
58
+ return compact({
59
+ type, v,
60
+ id: requireString(raw, "id"),
61
+ session: requireString(raw, "session"),
62
+ kind,
63
+ tool: optionalString(raw, "tool"),
64
+ summary: requireString(raw, "summary"),
65
+ });
66
+ }
67
+ case "remote_pending_cleared":
68
+ return {
69
+ type, v,
70
+ id: requireString(raw, "id"),
71
+ session: requireString(raw, "session"),
72
+ kind: requireRemotePendingKind(raw),
73
+ };
74
+ case "session_list_request":
75
+ return compact({
76
+ type, v,
77
+ id: requireString(raw, "id"),
78
+ limit: optionalNumber(raw, "limit"),
79
+ cursor: optionalString(raw, "cursor"),
80
+ });
81
+ case "session_list_response":
82
+ return compact({
83
+ type, v,
84
+ id: requireString(raw, "id"),
85
+ sessions: requireArray(raw, "sessions").map((element) => {
86
+ const obj = requireObject(element, "sessions");
87
+ return compact({
88
+ name: requireString(obj, "name"),
89
+ cwd: requireString(obj, "cwd"),
90
+ alive: requireBoolean(obj, "alive"),
91
+ updatedAt: optionalNumber(obj, "updatedAt"),
92
+ claudeSessionId: optionalString(obj, "claudeSessionId"),
93
+ agent: optionalString(obj, "agent") === "codex"
94
+ ? "codex"
95
+ : optionalString(obj, "agent") === "claude"
96
+ ? "claude"
97
+ : undefined,
98
+ providerSessionId: optionalString(obj, "providerSessionId"),
99
+ // 未知値は未指定(= tmux 相当)へ倒す(後方互換)。
100
+ backend: optionalString(obj, "backend") === "herdr" ? "herdr" : undefined,
101
+ displayTitle: optionalString(obj, "displayTitle"),
102
+ });
103
+ }),
104
+ nextCursor: optionalString(raw, "nextCursor"),
105
+ adoptedName: optionalString(raw, "adoptedName"),
106
+ worktreePath: optionalString(raw, "worktreePath"),
107
+ worktreeRemoved: optionalBoolean(raw, "worktreeRemoved"),
108
+ worktreeDirty: optionalBoolean(raw, "worktreeDirty"),
109
+ });
110
+ case "session_start": {
111
+ // agentType は "claude"|"codex" のみ採用。未知値/未指定は undefined(host 側既定に委ねる)。
112
+ const rawAgent = optionalString(raw, "agentType");
113
+ const agentType = rawAgent === "codex" || rawAgent === "claude" ? rawAgent : undefined;
114
+ // codexSandbox は既知 3 値のみ採用(codex-input)。未知/未指定は undefined(host 既定)。
115
+ const rawSandbox = optionalString(raw, "codexSandbox");
116
+ const codexSandbox = rawSandbox === "read-only" || rawSandbox === "workspace-write" || rawSandbox === "danger-full-access"
117
+ ? rawSandbox
118
+ : undefined;
119
+ // permissionMode は既知 4 値のみ採用(claude 新規起動の --permission-mode)。未知/未指定は
120
+ // undefined(フラグ無し=claude 既定)。
121
+ const rawMode = optionalString(raw, "permissionMode");
122
+ const permissionMode = rawMode === "default" || rawMode === "acceptEdits" || rawMode === "plan" || rawMode === "auto"
123
+ ? rawMode
124
+ : undefined;
125
+ return compact({
126
+ type, v,
127
+ id: requireString(raw, "id"),
128
+ cwd: requireString(raw, "cwd"),
129
+ name: requireString(raw, "name"),
130
+ baseDir: optionalString(raw, "baseDir"),
131
+ resumeSessionId: optionalString(raw, "resumeSessionId"),
132
+ title: optionalString(raw, "title"),
133
+ agentType,
134
+ model: optionalString(raw, "model"),
135
+ permissionMode,
136
+ codexModel: optionalString(raw, "codexModel"),
137
+ codexSandbox,
138
+ deferSubscribe: optionalBoolean(raw, "deferSubscribe"),
139
+ });
140
+ }
141
+ case "session_reattach":
142
+ case "session_kill":
143
+ case "session_idle_hint":
144
+ return { type, v, id: requireString(raw, "id"), name: requireString(raw, "name") };
145
+ case "codex_model_list_request":
146
+ return { type, v, id: requireString(raw, "id") };
147
+ case "codex_model_list_response":
148
+ return {
149
+ type, v,
150
+ id: requireString(raw, "id"),
151
+ models: requireArray(raw, "models").map((element) => {
152
+ const obj = requireObject(element, "models");
153
+ const contextWindow = optionalNumber(obj, "contextWindow");
154
+ if (contextWindow !== undefined && (!Number.isInteger(contextWindow) || contextWindow <= 0)) {
155
+ throw new ProtocolDecodeError("missing-field", "models.contextWindow");
156
+ }
157
+ return compact({
158
+ id: requireString(obj, "id"),
159
+ displayName: requireString(obj, "displayName"),
160
+ description: requireString(obj, "description"),
161
+ contextWindow,
162
+ defaultReasoningEffort: optionalString(obj, "defaultReasoningEffort"),
163
+ supportedReasoningEfforts: obj["supportedReasoningEfforts"] === undefined
164
+ ? undefined
165
+ : requireStringArray(obj, "supportedReasoningEfforts"),
166
+ isDefault: requireBoolean(obj, "isDefault"),
167
+ });
168
+ }),
169
+ };
170
+ case "claude_model_list_request":
171
+ return { type, v, id: requireString(raw, "id") };
172
+ case "claude_model_list_response":
173
+ return {
174
+ type, v,
175
+ id: requireString(raw, "id"),
176
+ models: requireArray(raw, "models").map((element) => {
177
+ const obj = requireObject(element, "models");
178
+ return {
179
+ id: requireString(obj, "id"),
180
+ displayName: requireString(obj, "displayName"),
181
+ };
182
+ }),
183
+ };
184
+ case "official_app_status_request":
185
+ return {
186
+ type, v,
187
+ id: requireString(raw, "id"),
188
+ session: requireString(raw, "session"),
189
+ provider: decodeOfficialAppProvider(raw, "provider"),
190
+ };
191
+ case "official_app_status_response": {
192
+ const state = requireString(raw, "state");
193
+ if (state !== "active" && state !== "inactive" && state !== "unavailable") {
194
+ throw new ProtocolDecodeError("missing-field", "state");
195
+ }
196
+ return compact({
197
+ type, v,
198
+ id: requireString(raw, "id"),
199
+ provider: decodeOfficialAppProvider(raw, "provider"),
200
+ version: optionalString(raw, "version"),
201
+ state,
202
+ canOpen: requireBoolean(raw, "canOpen"),
203
+ canStart: requireBoolean(raw, "canStart"),
204
+ launchUrl: optionalString(raw, "launchUrl"),
205
+ unavailableReason: optionalString(raw, "unavailableReason"),
206
+ });
207
+ }
208
+ case "official_app_action_request": {
209
+ const action = requireString(raw, "action");
210
+ if (action !== "open" && action !== "repair" && action !== "stop") {
211
+ throw new ProtocolDecodeError("missing-field", "action");
212
+ }
213
+ return {
214
+ type, v,
215
+ id: requireString(raw, "id"),
216
+ session: requireString(raw, "session"),
217
+ provider: decodeOfficialAppProvider(raw, "provider"),
218
+ action,
219
+ automaticEnable: requireBoolean(raw, "automaticEnable"),
220
+ paired: requireBoolean(raw, "paired"),
221
+ };
222
+ }
223
+ case "official_app_action_response": {
224
+ const outcome = requireString(raw, "outcome");
225
+ if (outcome !== "open" &&
226
+ outcome !== "pair" &&
227
+ outcome !== "stopped" &&
228
+ outcome !== "unavailable") {
229
+ throw new ProtocolDecodeError("missing-field", "outcome");
230
+ }
231
+ return compact({
232
+ type, v,
233
+ id: requireString(raw, "id"),
234
+ provider: decodeOfficialAppProvider(raw, "provider"),
235
+ outcome,
236
+ launchUrl: optionalString(raw, "launchUrl"),
237
+ manualPairingCode: optionalString(raw, "manualPairingCode"),
238
+ expiresAt: optionalNumber(raw, "expiresAt"),
239
+ unavailableReason: optionalString(raw, "unavailableReason"),
240
+ });
241
+ }
242
+ case "codex_turn_start":
243
+ const rawTurnSandbox = optionalString(raw, "sandbox");
244
+ const sandbox = rawTurnSandbox === "read-only" || rawTurnSandbox === "workspace-write" || rawTurnSandbox === "danger-full-access"
245
+ ? rawTurnSandbox : undefined;
246
+ const rawApprovalPolicy = optionalString(raw, "approvalPolicy");
247
+ const approvalPolicy = rawApprovalPolicy === "untrusted" || rawApprovalPolicy === "on-request" || rawApprovalPolicy === "never"
248
+ ? rawApprovalPolicy
249
+ : undefined;
250
+ return compact({
251
+ type, v,
252
+ id: requireString(raw, "id"),
253
+ session: requireString(raw, "session"),
254
+ text: requireString(raw, "text"),
255
+ clientUserMessageId: optionalString(raw, "clientUserMessageId"),
256
+ effort: optionalString(raw, "effort"),
257
+ approvalPolicy,
258
+ sandbox,
259
+ explicitRetry: optionalBoolean(raw, "explicitRetry"),
260
+ });
261
+ case "codex_turn_start_result": {
262
+ const status = requireString(raw, "status");
263
+ if (status !== "started" && status !== "duplicate" && status !== "failed") {
264
+ throw new ProtocolDecodeError("missing-field", "status");
265
+ }
266
+ return compact({ type, v, id: requireString(raw, "id"), status, error: optionalString(raw, "error") });
267
+ }
268
+ case "codex_turn_interrupt":
269
+ return {
270
+ type, v,
271
+ id: requireString(raw, "id"),
272
+ session: requireString(raw, "session"),
273
+ };
274
+ case "session_processing_state":
275
+ return {
276
+ type, v,
277
+ session: requireString(raw, "session"),
278
+ active: requireBoolean(raw, "active"),
279
+ };
280
+ case "chat_send": {
281
+ const text = requireString(raw, "text");
282
+ if (text.length === 0)
283
+ throw new ProtocolDecodeError("missing-field", "text");
284
+ return compact({
285
+ type, v,
286
+ id: requireString(raw, "id"),
287
+ session: requireString(raw, "session"),
288
+ clientMessageId: requireString(raw, "clientMessageId"),
289
+ text,
290
+ explicitRetry: optionalBoolean(raw, "explicitRetry"),
291
+ });
292
+ }
293
+ case "chat_send_result": {
294
+ const status = requireString(raw, "status");
295
+ if (status !== "accepted" && status !== "duplicate" && status !== "failed") {
296
+ throw new ProtocolDecodeError("missing-field", "status");
297
+ }
298
+ return compact({ type, v, id: requireString(raw, "id"), status, error: optionalString(raw, "error") });
299
+ }
300
+ case "pending_message_delete": {
301
+ const kind = requireString(raw, "kind");
302
+ if (kind !== "chat" && kind !== "codex") {
303
+ throw new ProtocolDecodeError("missing-field", "kind");
304
+ }
305
+ return {
306
+ type, v,
307
+ id: requireString(raw, "id"),
308
+ session: requireString(raw, "session"),
309
+ clientMessageId: requireString(raw, "clientMessageId"),
310
+ kind,
311
+ };
312
+ }
313
+ case "pending_message_delete_result": {
314
+ const status = requireString(raw, "status");
315
+ if (status !== "deleted" && status !== "not_found" &&
316
+ status !== "processing" && status !== "failed") {
317
+ throw new ProtocolDecodeError("missing-field", "status");
318
+ }
319
+ return compact({ type, v, id: requireString(raw, "id"), status, error: optionalString(raw, "error") });
320
+ }
321
+ case "error":
322
+ return compact({
323
+ type, v,
324
+ id: optionalString(raw, "id"),
325
+ code: requireString(raw, "code"),
326
+ message: requireString(raw, "message"),
327
+ });
328
+ case "image_available":
329
+ return compact({
330
+ type, v,
331
+ id: requireString(raw, "id"),
332
+ path: requireString(raw, "path"),
333
+ mime: requireString(raw, "mime"),
334
+ thumbnail: requireString(raw, "thumbnail"),
335
+ width: requireNumber(raw, "width"),
336
+ height: requireNumber(raw, "height"),
337
+ relatedApprovalId: optionalString(raw, "relatedApprovalId"),
338
+ });
339
+ case "usage_request": {
340
+ const rawAgent = optionalString(raw, "agentType");
341
+ return compact({
342
+ type, v,
343
+ id: requireString(raw, "id"),
344
+ agentType: rawAgent === "claude" || rawAgent === "codex" ? rawAgent : undefined,
345
+ });
346
+ }
347
+ case "image_fetch_request":
348
+ case "account_usage_request":
349
+ case "question_dismiss":
350
+ case "claude_session_list_request":
351
+ return { type, v, id: requireString(raw, "id") };
352
+ case "image_fetch_response":
353
+ return {
354
+ type, v,
355
+ id: requireString(raw, "id"),
356
+ seq: requireNumber(raw, "seq"),
357
+ data: requireString(raw, "data"),
358
+ eof: requireBoolean(raw, "eof"),
359
+ mime: requireString(raw, "mime"),
360
+ };
361
+ case "subagent_transcript_request":
362
+ return { type, v, id: requireString(raw, "id"), nodeId: requireString(raw, "nodeId") };
363
+ case "subagent_transcript_response":
364
+ return {
365
+ type, v,
366
+ id: requireString(raw, "id"),
367
+ nodeId: requireString(raw, "nodeId"),
368
+ entries: requireArray(raw, "entries").map((element) => {
369
+ const entry = requireObject(element, "entries");
370
+ const role = requireString(entry, "role");
371
+ if (role !== "user" && role !== "assistant" && role !== "tool") {
372
+ throw new ProtocolDecodeError("missing-field", "entries.role");
373
+ }
374
+ const rawKind = optionalString(entry, "kind");
375
+ const kind = role === "tool" && (rawKind === "tool_use" || rawKind === "tool_result")
376
+ ? rawKind : undefined;
377
+ return compact({
378
+ role,
379
+ text: requireString(entry, "text"),
380
+ ts: optionalNumber(entry, "ts"),
381
+ kind,
382
+ });
383
+ }),
384
+ omitted: requireNumber(raw, "omitted"),
385
+ };
386
+ case "chat_stream_alias":
387
+ return {
388
+ type, v,
389
+ streamId: requireString(raw, "streamId"),
390
+ aliasStreamIds: requireStringArray(raw, "aliasStreamIds"),
391
+ };
392
+ case "chat_output": {
393
+ const role = requireString(raw, "role");
394
+ if (role !== "assistant" && role !== "user" && role !== "system") {
395
+ throw new ProtocolDecodeError("missing-field", "role");
396
+ }
397
+ return {
398
+ type, v,
399
+ streamId: requireString(raw, "streamId"),
400
+ role,
401
+ text: requireString(raw, "text"),
402
+ eof: requireBoolean(raw, "eof"),
403
+ };
404
+ }
405
+ case "session_chat_stream_alias":
406
+ return {
407
+ type, v,
408
+ session: requireString(raw, "session"),
409
+ serverSeq: requireNumber(raw, "serverSeq"),
410
+ streamId: requireString(raw, "streamId"),
411
+ aliasStreamIds: requireStringArray(raw, "aliasStreamIds"),
412
+ };
413
+ case "session_chat_output": {
414
+ const role = requireString(raw, "role");
415
+ if (role !== "assistant" && role !== "user" && role !== "system") {
416
+ throw new ProtocolDecodeError("missing-field", "role");
417
+ }
418
+ return {
419
+ type, v,
420
+ session: requireString(raw, "session"),
421
+ serverSeq: requireNumber(raw, "serverSeq"),
422
+ streamId: requireString(raw, "streamId"),
423
+ role,
424
+ text: requireString(raw, "text"),
425
+ eof: requireBoolean(raw, "eof"),
426
+ };
427
+ }
428
+ case "tool_activity":
429
+ return { type, v, activity: decodeToolActivity(raw) };
430
+ case "session_tool_activity":
431
+ return {
432
+ type, v,
433
+ session: requireString(raw, "session"),
434
+ serverSeq: requireNumber(raw, "serverSeq"),
435
+ activity: decodeToolActivity(raw),
436
+ };
437
+ case "subagent_node":
438
+ return { type, v, node: decodeSubagentNode(raw) };
439
+ case "pane_preview": {
440
+ const mode = optionalString(raw, "mode");
441
+ if (mode !== undefined && mode !== "codex_terminal") {
442
+ throw new ProtocolDecodeError("missing-field", "mode");
443
+ }
444
+ return compact({
445
+ type, v,
446
+ session: requireString(raw, "session"),
447
+ seq: requireNumber(raw, "seq"),
448
+ active: requireBoolean(raw, "active"),
449
+ text: requireString(raw, "text"),
450
+ mode,
451
+ });
452
+ }
453
+ case "session_preview_watch":
454
+ return { type, v, enabled: requireBoolean(raw, "enabled") };
455
+ case "session_liveness_event":
456
+ return {
457
+ type, v,
458
+ session: requireString(raw, "session"),
459
+ alive: requireBoolean(raw, "alive"),
460
+ };
461
+ case "pane_choice_send":
462
+ case "pane_key_send":
463
+ return {
464
+ type, v,
465
+ id: requireString(raw, "id"),
466
+ session: requireString(raw, "session"),
467
+ key: requireString(raw, "key"),
468
+ };
469
+ case "pane_choice_send_result":
470
+ case "pane_key_send_result":
471
+ case "session_title_set_result":
472
+ case "codex_thread_title_set_result":
473
+ return {
474
+ type, v,
475
+ id: requireString(raw, "id"),
476
+ ok: requireBoolean(raw, "ok"),
477
+ error: optionalNullableString(raw, "error") ?? null,
478
+ };
479
+ case "session_title_set":
480
+ return {
481
+ type, v,
482
+ id: requireString(raw, "id"),
483
+ session: requireString(raw, "session"),
484
+ title: requireString(raw, "title"),
485
+ };
486
+ case "codex_thread_title_set":
487
+ return {
488
+ type, v,
489
+ id: requireString(raw, "id"),
490
+ threadId: requireString(raw, "threadId"),
491
+ title: requireString(raw, "title"),
492
+ };
493
+ case "question_prompt":
494
+ return {
495
+ type, v,
496
+ id: requireString(raw, "id"),
497
+ questions: requireArray(raw, "questions").map((element) => {
498
+ const obj = requireObject(element, "questions");
499
+ return {
500
+ header: requireString(obj, "header"),
501
+ question: requireString(obj, "question"),
502
+ multiSelect: requireBoolean(obj, "multiSelect"),
503
+ options: requireArray(obj, "options").map((option) => {
504
+ const optionObj = requireObject(option, "options");
505
+ return {
506
+ label: requireString(optionObj, "label"),
507
+ description: requireString(optionObj, "description"),
508
+ };
509
+ }),
510
+ };
511
+ }),
512
+ };
513
+ case "question_answer":
514
+ return {
515
+ type, v,
516
+ id: requireString(raw, "id"),
517
+ session: requireString(raw, "session"),
518
+ answers: requireArray(raw, "answers").map((element) => {
519
+ const obj = requireObject(element, "answers");
520
+ return compact({
521
+ questionIndex: requireNumber(obj, "questionIndex"),
522
+ selectedOptionIndexes: requireArray(obj, "selectedOptionIndexes").map((index) => {
523
+ if (typeof index !== "number")
524
+ throw new ProtocolDecodeError("missing-field", "selectedOptionIndexes");
525
+ return index;
526
+ }),
527
+ otherText: optionalString(obj, "otherText"),
528
+ multiSelect: optionalBoolean(obj, "multiSelect") ?? false,
529
+ });
530
+ }),
531
+ };
532
+ case "usage_response":
533
+ return compact({
534
+ type, v,
535
+ id: requireString(raw, "id"),
536
+ inputTokens: requireNumber(raw, "inputTokens"),
537
+ outputTokens: requireNumber(raw, "outputTokens"),
538
+ cacheReadTokens: requireNumber(raw, "cacheReadTokens"),
539
+ cacheCreationTokens: requireNumber(raw, "cacheCreationTokens"),
540
+ turns: requireNumber(raw, "turns"),
541
+ fiveHourUtilization: optionalNumber(raw, "fiveHourUtilization"),
542
+ fiveHourResetsAt: optionalString(raw, "fiveHourResetsAt"),
543
+ sevenDayUtilization: optionalNumber(raw, "sevenDayUtilization"),
544
+ sevenDayResetsAt: optionalString(raw, "sevenDayResetsAt"),
545
+ sevenDayFableUtilization: optionalNumber(raw, "sevenDayFableUtilization"),
546
+ sevenDayFableResetsAt: optionalString(raw, "sevenDayFableResetsAt"),
547
+ });
548
+ case "account_usage_response":
549
+ return compact({
550
+ type, v,
551
+ id: requireString(raw, "id"),
552
+ claude: decodeClaudeAccountUsage(raw["claude"]),
553
+ codex: decodeCodexAccountUsage(raw["codex"]),
554
+ claudeError: optionalString(raw, "claudeError"),
555
+ codexError: optionalString(raw, "codexError"),
556
+ host: decodeHostVersions(raw["host"]),
557
+ fetchedAt: optionalString(raw, "fetchedAt"),
558
+ });
559
+ case "mode_get":
560
+ return { type, v, id: requireString(raw, "id"), session: requireString(raw, "session") };
561
+ case "mode_set":
562
+ return {
563
+ type, v,
564
+ id: requireString(raw, "id"),
565
+ session: requireString(raw, "session"),
566
+ mode: requireString(raw, "mode"),
567
+ };
568
+ case "mode_set_response":
569
+ return { type, v, id: requireString(raw, "id"), mode: requireString(raw, "mode") };
570
+ case "slash_list_request":
571
+ return compact({ type, v, id: requireString(raw, "id"), cwd: optionalString(raw, "cwd") });
572
+ case "slash_list_response":
573
+ return {
574
+ type, v,
575
+ id: requireString(raw, "id"),
576
+ commands: requireArray(raw, "commands").map((element) => {
577
+ const obj = requireObject(element, "commands");
578
+ return {
579
+ name: requireString(obj, "name"),
580
+ summary: requireString(obj, "summary"),
581
+ };
582
+ }),
583
+ };
584
+ case "dir_list_request":
585
+ return {
586
+ type, v,
587
+ id: requireString(raw, "id"),
588
+ baseDir: requireString(raw, "baseDir"),
589
+ partial: requireString(raw, "partial"),
590
+ };
591
+ case "dir_list_response":
592
+ return { type, v, id: requireString(raw, "id"), entries: requireStringArray(raw, "entries") };
593
+ case "browse_request":
594
+ return { type, v, id: requireString(raw, "id"), path: requireString(raw, "path") };
595
+ case "browse_response":
596
+ return {
597
+ type, v,
598
+ id: requireString(raw, "id"),
599
+ path: requireString(raw, "path"),
600
+ entries: requireStringArray(raw, "entries"),
601
+ canCreateDirectory: optionalBoolean(raw, "canCreateDirectory"),
602
+ };
603
+ case "file_list_request":
604
+ case "file_read_request":
605
+ case "git_status_request":
606
+ case "git_branch_list_request":
607
+ case "git_init_request":
608
+ return { type, v, id: requireString(raw, "id"), path: requireString(raw, "path") };
609
+ case "git_worktree_create_request":
610
+ return {
611
+ type, v, id: requireString(raw, "id"), path: requireString(raw, "path"),
612
+ baseBranch: requireString(raw, "baseBranch"),
613
+ };
614
+ case "git_worktree_remove_request":
615
+ return {
616
+ type, v, id: requireString(raw, "id"), path: requireString(raw, "path"),
617
+ force: requireBoolean(raw, "force"),
618
+ };
619
+ case "file_list_response":
620
+ return {
621
+ type, v,
622
+ id: requireString(raw, "id"), path: requireString(raw, "path"),
623
+ entries: requireArray(raw, "entries").map((element) => {
624
+ const entry = requireObject(element, "entries");
625
+ const kind = requireString(entry, "kind");
626
+ if (kind !== "dir" && kind !== "file" && kind !== "symlink") {
627
+ throw new ProtocolDecodeError("missing-field", "entries.kind");
628
+ }
629
+ return compact({
630
+ name: requireString(entry, "name"), kind,
631
+ size: requireNumber(entry, "size"), mtimeMs: requireNumber(entry, "mtimeMs"),
632
+ gitStatus: optionalString(entry, "gitStatus"),
633
+ });
634
+ }),
635
+ truncated: requireBoolean(raw, "truncated"),
636
+ };
637
+ case "file_read_response": {
638
+ const kind = requireString(raw, "kind");
639
+ if (kind !== "text" && kind !== "image" && kind !== "binary" &&
640
+ kind !== "tooLarge" && kind !== "error") {
641
+ throw new ProtocolDecodeError("missing-field", "kind");
642
+ }
643
+ return compact({
644
+ type, v,
645
+ id: requireString(raw, "id"), path: requireString(raw, "path"), kind,
646
+ size: requireNumber(raw, "size"), mtimeMs: requireNumber(raw, "mtimeMs"),
647
+ content: optionalString(raw, "content"), truncated: optionalBoolean(raw, "truncated"),
648
+ imageBase64: optionalString(raw, "imageBase64"), imageFormat: optionalString(raw, "imageFormat"),
649
+ error: optionalString(raw, "error"),
650
+ });
651
+ }
652
+ case "git_status_response":
653
+ return compact({
654
+ type, v,
655
+ id: requireString(raw, "id"), isRepo: requireBoolean(raw, "isRepo"),
656
+ branch: requireString(raw, "branch"), upstream: optionalNullableString(raw, "upstream") ?? null,
657
+ ahead: requireNumber(raw, "ahead"), behind: requireNumber(raw, "behind"),
658
+ files: requireArray(raw, "files").map((element) => {
659
+ const file = requireObject(element, "files");
660
+ return {
661
+ path: requireString(file, "path"), indexStatus: requireString(file, "indexStatus"),
662
+ worktreeStatus: requireString(file, "worktreeStatus"),
663
+ renamedFrom: optionalNullableString(file, "renamedFrom") ?? null,
664
+ };
665
+ }),
666
+ repoRoot: optionalString(raw, "repoRoot"),
667
+ diffAdditions: optionalNumber(raw, "diffAdditions"),
668
+ diffDeletions: optionalNumber(raw, "diffDeletions"),
669
+ });
670
+ case "git_diff_request":
671
+ return compact({
672
+ type, v, id: requireString(raw, "id"), path: requireString(raw, "path"),
673
+ file: optionalString(raw, "file"), staged: optionalBoolean(raw, "staged"),
674
+ commit: optionalNullableString(raw, "commit"),
675
+ });
676
+ case "git_diff_response":
677
+ return {
678
+ type, v, id: requireString(raw, "id"), isRepo: requireBoolean(raw, "isRepo"),
679
+ diff: requireString(raw, "diff"), truncated: requireBoolean(raw, "truncated"),
680
+ };
681
+ case "git_log_request":
682
+ return compact({
683
+ type, v, id: requireString(raw, "id"), path: requireString(raw, "path"),
684
+ limit: optionalNumber(raw, "limit"),
685
+ });
686
+ case "git_log_response":
687
+ return {
688
+ type, v, id: requireString(raw, "id"), isRepo: requireBoolean(raw, "isRepo"),
689
+ commits: requireArray(raw, "commits").map((element) => {
690
+ const commit = requireObject(element, "commits");
691
+ return {
692
+ hash: requireString(commit, "hash"), shortHash: requireString(commit, "shortHash"),
693
+ subject: requireString(commit, "subject"), authorName: requireString(commit, "authorName"),
694
+ dateMs: requireNumber(commit, "dateMs"),
695
+ };
696
+ }),
697
+ };
698
+ case "git_branch_list_response":
699
+ return {
700
+ type, v, id: requireString(raw, "id"), isRepo: requireBoolean(raw, "isRepo"),
701
+ branches: requireArray(raw, "branches").map((element) => {
702
+ const branch = requireObject(element, "branches");
703
+ return {
704
+ name: requireString(branch, "name"), subject: requireString(branch, "subject"),
705
+ dateMs: requireNumber(branch, "dateMs"), isCurrent: requireBoolean(branch, "isCurrent"),
706
+ ahead: requireNumber(branch, "ahead"), behind: requireNumber(branch, "behind"),
707
+ };
708
+ }),
709
+ };
710
+ case "git_checkout_request":
711
+ return {
712
+ type, v, id: requireString(raw, "id"), path: requireString(raw, "path"),
713
+ branch: requireString(raw, "branch"), create: requireBoolean(raw, "create"),
714
+ };
715
+ case "git_checkout_response":
716
+ return {
717
+ type, v, id: requireString(raw, "id"), ok: requireBoolean(raw, "ok"),
718
+ branch: requireString(raw, "branch"),
719
+ error: optionalNullableString(raw, "error") ?? null,
720
+ };
721
+ case "git_discard_request":
722
+ return {
723
+ type, v, id: requireString(raw, "id"), path: requireString(raw, "path"),
724
+ files: requireStringArray(raw, "files"),
725
+ };
726
+ case "git_discard_response":
727
+ case "git_init_response":
728
+ case "git_worktree_remove_response":
729
+ return {
730
+ type, v, id: requireString(raw, "id"), ok: requireBoolean(raw, "ok"),
731
+ error: optionalNullableString(raw, "error") ?? null,
732
+ };
733
+ case "git_worktree_create_response":
734
+ return {
735
+ type, v, id: requireString(raw, "id"), ok: requireBoolean(raw, "ok"),
736
+ branch: requireString(raw, "branch"), worktreePath: requireString(raw, "worktreePath"),
737
+ error: optionalNullableString(raw, "error") ?? null,
738
+ };
739
+ case "claude_session_list_response":
740
+ return compact({
741
+ type, v,
742
+ id: requireString(raw, "id"),
743
+ claudeSessions: requireArray(raw, "claudeSessions").map((element) => {
744
+ const obj = requireObject(element, "claudeSessions");
745
+ const rawSessionAgent = optionalString(obj, "agent");
746
+ const sessionAgent = rawSessionAgent === "codex" || rawSessionAgent === "claude" ? rawSessionAgent : undefined;
747
+ // live-pill: 生存セッション名が権威。バックエンドは名前があるときの enum のみ採る。
748
+ const liveSessionName = optionalString(obj, "liveSessionName");
749
+ const rawLiveBackend = optionalString(obj, "liveSessionBackend");
750
+ const liveSessionBackend = liveSessionName !== undefined && (rawLiveBackend === "tmux" || rawLiveBackend === "herdr")
751
+ ? rawLiveBackend
752
+ : undefined;
753
+ return compact({
754
+ sessionId: requireString(obj, "sessionId"),
755
+ cwd: requireString(obj, "cwd"),
756
+ title: requireString(obj, "title"),
757
+ updatedAt: optionalNumber(obj, "updatedAt"),
758
+ agent: sessionAgent,
759
+ hasProviderTitle: optionalBoolean(obj, "hasProviderTitle"),
760
+ lastMessage: optionalString(obj, "lastMessage"),
761
+ liveSessionName,
762
+ liveSessionBackend,
763
+ });
764
+ }),
765
+ liveSessionsResolved: optionalBoolean(raw, "liveSessionsResolved"),
766
+ });
767
+ case "dir_create_request":
768
+ return {
769
+ type, v,
770
+ id: requireString(raw, "id"),
771
+ baseDir: requireString(raw, "baseDir"),
772
+ relative: requireString(raw, "relative"),
773
+ };
774
+ case "dir_create_response":
775
+ return {
776
+ type, v,
777
+ id: requireString(raw, "id"),
778
+ path: requireString(raw, "path"),
779
+ ok: requireBoolean(raw, "ok"),
780
+ error: optionalString(raw, "error"),
781
+ };
782
+ case "session_search_request":
783
+ return compact({
784
+ type, v,
785
+ id: requireString(raw, "id"),
786
+ query: requireString(raw, "query"),
787
+ limit: optionalNumber(raw, "limit"),
788
+ });
789
+ case "session_search_response":
790
+ return {
791
+ type, v,
792
+ id: requireString(raw, "id"),
793
+ results: requireArray(raw, "results").map((element) => {
794
+ const obj = requireObject(element, "results");
795
+ return compact({
796
+ sessionId: requireString(obj, "sessionId"),
797
+ title: requireString(obj, "title"),
798
+ cwd: requireString(obj, "cwd"),
799
+ snippet: requireString(obj, "snippet"),
800
+ updatedAt: optionalNumber(obj, "updatedAt"),
801
+ });
802
+ }),
803
+ };
804
+ case "preview_open":
805
+ return {
806
+ type, v,
807
+ id: requireString(raw, "id"),
808
+ target: requireString(raw, "target"),
809
+ };
810
+ case "preview_ready":
811
+ return {
812
+ type, v,
813
+ id: requireString(raw, "id"),
814
+ url: requireString(raw, "url"),
815
+ };
816
+ case "preview_error":
817
+ return {
818
+ type, v,
819
+ id: requireString(raw, "id"),
820
+ message: requireString(raw, "message"),
821
+ };
822
+ case "preview_close":
823
+ return {
824
+ type, v,
825
+ id: requireString(raw, "id"),
826
+ };
827
+ case "serve_list_request":
828
+ return { type, v, id: requireString(raw, "id") };
829
+ case "serve_list_response":
830
+ return {
831
+ type, v,
832
+ id: requireString(raw, "id"),
833
+ servers: requireArray(raw, "servers").map((element) => {
834
+ const obj = requireObject(element, "servers");
835
+ return compact({
836
+ pid: requireNumber(obj, "pid"),
837
+ port: requireNumber(obj, "port"),
838
+ command: requireString(obj, "command"),
839
+ commandLine: optionalString(obj, "commandLine"),
840
+ cwd: optionalString(obj, "cwd"),
841
+ title: optionalString(obj, "title"),
842
+ });
843
+ }),
844
+ };
845
+ case "serve_stop_request":
846
+ return {
847
+ type, v,
848
+ id: requireString(raw, "id"),
849
+ pid: requireNumber(raw, "pid"),
850
+ port: requireNumber(raw, "port"),
851
+ };
852
+ case "serve_stop_response":
853
+ return {
854
+ type, v,
855
+ id: requireString(raw, "id"),
856
+ ok: requireBoolean(raw, "ok"),
857
+ error: optionalNullableString(raw, "error") ?? null,
858
+ };
859
+ case "backend_get_request":
860
+ return { type, v, id: requireString(raw, "id") };
861
+ case "backend_get_response":
862
+ return {
863
+ type, v,
864
+ id: requireString(raw, "id"),
865
+ backend: requireBackendKind(raw),
866
+ herdrInstalled: requireBoolean(raw, "herdrInstalled"),
867
+ };
868
+ case "backend_set_request":
869
+ return {
870
+ type, v,
871
+ id: requireString(raw, "id"),
872
+ backend: requireBackendKind(raw),
873
+ };
874
+ case "backend_set_response":
875
+ return {
876
+ type, v,
877
+ id: requireString(raw, "id"),
878
+ ok: requireBoolean(raw, "ok"),
879
+ backend: requireBackendKind(raw),
880
+ error: optionalNullableString(raw, "error") ?? null,
881
+ };
882
+ default:
883
+ throw new ProtocolDecodeError("unknown-type", type);
884
+ }
885
+ }
886
+ /** `account_usage_response.claude` を読む(欠落は undefined = 「Claude 側は載っていない」)。 */
887
+ function decodeClaudeAccountUsage(value) {
888
+ if (value === undefined || value === null)
889
+ return undefined;
890
+ const obj = requireObject(value, "claude");
891
+ return compact({
892
+ fiveHourPercent: optionalNumber(obj, "fiveHourPercent"),
893
+ fiveHourResetsAt: optionalString(obj, "fiveHourResetsAt"),
894
+ sevenDayPercent: optionalNumber(obj, "sevenDayPercent"),
895
+ sevenDayResetsAt: optionalString(obj, "sevenDayResetsAt"),
896
+ premiumPercent: optionalNumber(obj, "premiumPercent"),
897
+ premiumResetsAt: optionalString(obj, "premiumResetsAt"),
898
+ plan: optionalString(obj, "plan"),
899
+ rateLimitTier: optionalString(obj, "rateLimitTier"),
900
+ account: optionalString(obj, "account"),
901
+ });
902
+ }
903
+ /** `account_usage_response.host` を読む(欠落は undefined = 「ホスト情報は載っていない」)。 */
904
+ function decodeHostVersions(value) {
905
+ if (value === undefined || value === null)
906
+ return undefined;
907
+ const obj = requireObject(value, "host");
908
+ return compact({
909
+ hostVersion: optionalString(obj, "hostVersion"),
910
+ claudeCliVersion: optionalString(obj, "claudeCliVersion"),
911
+ codexCliVersion: optionalString(obj, "codexCliVersion"),
912
+ diagnostics: obj["diagnostics"] === undefined
913
+ ? undefined
914
+ : requireArray(obj, "diagnostics").map((item) => {
915
+ const check = requireObject(item, "host.diagnostics[]");
916
+ return compact({
917
+ id: requireString(check, "id"),
918
+ label: requireString(check, "label"),
919
+ ok: requireBoolean(check, "ok"),
920
+ required: requireBoolean(check, "required"),
921
+ detail: requireString(check, "detail"),
922
+ remediation: optionalString(check, "remediation"),
923
+ });
924
+ }),
925
+ });
926
+ }
927
+ /** `account_usage_response.codex` を読む(欠落は undefined = 「Codex 側は載っていない」)。 */
928
+ function decodeCodexAccountUsage(value) {
929
+ if (value === undefined || value === null)
930
+ return undefined;
931
+ const obj = requireObject(value, "codex");
932
+ return compact({
933
+ planType: optionalString(obj, "planType"),
934
+ fiveHourPercent: optionalNumber(obj, "fiveHourPercent"),
935
+ fiveHourResetsAt: optionalString(obj, "fiveHourResetsAt"),
936
+ weeklyPercent: optionalNumber(obj, "weeklyPercent"),
937
+ weeklyResetsAt: optionalString(obj, "weeklyResetsAt"),
938
+ account: optionalString(obj, "account"),
939
+ });
940
+ }
941
+ function requireBackendKind(raw) {
942
+ const backend = requireString(raw, "backend");
943
+ if (backend !== "tmux" && backend !== "herdr") {
944
+ throw new ProtocolDecodeError("missing-field", "backend");
945
+ }
946
+ return backend;
947
+ }
948
+ function requireRemotePendingKind(raw) {
949
+ const kind = requireString(raw, "kind");
950
+ if (kind !== "approval" && kind !== "question") {
951
+ throw new ProtocolDecodeError("missing-field", "kind");
952
+ }
953
+ return kind;
954
+ }
955
+ function decodeToolDiff(value) {
956
+ if (value === undefined || value === null)
957
+ return undefined;
958
+ const obj = requireObject(value, "diff");
959
+ const kind = requireString(obj, "kind");
960
+ if (kind !== "create" && kind !== "edit")
961
+ throw new ProtocolDecodeError("missing-field", "diff.kind");
962
+ return compact({
963
+ kind,
964
+ path: requireString(obj, "path"),
965
+ newText: optionalString(obj, "newText"),
966
+ oldString: optionalString(obj, "oldString"),
967
+ newString: optionalString(obj, "newString"),
968
+ });
969
+ }
970
+ function decodeToolActivity(raw) {
971
+ const diffValue = raw["diff"];
972
+ let diff;
973
+ if (diffValue !== undefined && diffValue !== null) {
974
+ const obj = requireObject(diffValue, "diff");
975
+ diff = compact({
976
+ oldString: optionalString(obj, "oldString"),
977
+ newString: optionalString(obj, "newString"),
978
+ oldStringTruncated: optionalBoolean(obj, "oldStringTruncated") ?? false,
979
+ newStringTruncated: optionalBoolean(obj, "newStringTruncated") ?? false,
980
+ });
981
+ }
982
+ const todosValue = raw["todos"];
983
+ let todos;
984
+ if (todosValue !== undefined && todosValue !== null) {
985
+ if (!Array.isArray(todosValue))
986
+ throw new ProtocolDecodeError("missing-field", "todos");
987
+ todos = todosValue.map((element) => {
988
+ const obj = requireObject(element, "todos");
989
+ return { content: requireString(obj, "content"), status: requireString(obj, "status") };
990
+ });
991
+ }
992
+ return compact({
993
+ id: requireString(raw, "id"),
994
+ name: requireString(raw, "name"),
995
+ label: requireString(raw, "label"),
996
+ file: optionalString(raw, "file"),
997
+ addedLines: optionalNumber(raw, "addedLines"),
998
+ removedLines: optionalNumber(raw, "removedLines"),
999
+ diff,
1000
+ command: optionalString(raw, "command"),
1001
+ commandTruncated: optionalBoolean(raw, "commandTruncated") ?? false,
1002
+ description: optionalString(raw, "description"),
1003
+ descriptionTruncated: optionalBoolean(raw, "descriptionTruncated") ?? false,
1004
+ todos,
1005
+ });
1006
+ }
1007
+ function decodeSubagentNode(raw) {
1008
+ const status = requireString(raw, "status");
1009
+ if (status !== "running" && status !== "completed" && status !== "error") {
1010
+ throw new ProtocolDecodeError("missing-field", "status");
1011
+ }
1012
+ const kind = optionalString(raw, "kind");
1013
+ if (kind !== undefined && kind !== "command") {
1014
+ throw new ProtocolDecodeError("missing-field", "kind");
1015
+ }
1016
+ return compact({
1017
+ nodeId: requireString(raw, "nodeId"),
1018
+ toolUseId: requireString(raw, "toolUseId"),
1019
+ parentNodeId: optionalNullableString(raw, "parentNodeId"),
1020
+ agentType: requireString(raw, "agentType"),
1021
+ label: requireString(raw, "label"),
1022
+ depth: requireNumber(raw, "depth"),
1023
+ status,
1024
+ currentActivity: optionalNullableString(raw, "currentActivity"),
1025
+ ts: requireNumber(raw, "ts"),
1026
+ kind,
1027
+ });
1028
+ }
1029
+ function decodeOfficialAppProvider(raw, key) {
1030
+ const provider = requireString(raw, key);
1031
+ if (provider !== "claude" && provider !== "codex") {
1032
+ throw new ProtocolDecodeError("missing-field", key);
1033
+ }
1034
+ return provider;
1035
+ }
1036
+ //# sourceMappingURL=decode.js.map