very-happy-cli 0.2.175 → 0.2.176

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 (179) hide show
  1. package/dist/{AcpBackend-Sb6N_HcB.cjs → AcpBackend-9_ZI1Bv3.cjs} +3 -3
  2. package/dist/{AcpBackend-BZrLVcHb.mjs → AcpBackend-COp6D8gl.mjs} +3 -3
  3. package/dist/{AcpSessionManager-C2MqOirs.cjs → AcpSessionManager-CjdJLofq.cjs} +1 -1
  4. package/dist/{AcpSessionManager-y1Iy1mzc.mjs → AcpSessionManager-DykjzBM4.mjs} +1 -1
  5. package/dist/{BasePermissionHandler-DriZLITp.mjs → BasePermissionHandler-ChMkmsGD.mjs} +1 -1
  6. package/dist/{BasePermissionHandler-BbLYwd13.cjs → BasePermissionHandler-DPvLN7aR.cjs} +1 -1
  7. package/dist/{BaseReasoningProcessor-_S1PbSvH.cjs → BaseReasoningProcessor-Dnf16mtJ.cjs} +1 -1
  8. package/dist/{BaseReasoningProcessor-DnykPlPo.mjs → BaseReasoningProcessor-pjvLSTQF.mjs} +1 -1
  9. package/dist/{agentHome-BoYfpemd.cjs → agentHome-BKi7tsE9.cjs} +4 -4
  10. package/dist/{agentHome-BtuRubHG.mjs → agentHome-D61ZMLXM.mjs} +4 -4
  11. package/dist/{api-KZmVqSKO.cjs → api-Buc_ejoA.cjs} +10 -10
  12. package/dist/{api-D08IEaWa.mjs → api-CbwDDXJt.mjs} +10 -10
  13. package/dist/{apiMachine-Dct2GDAq.cjs → apiMachine--PXoXwKq.cjs} +14 -14
  14. package/dist/{apiMachine-Cx9Zn-78.mjs → apiMachine-CS7t3Rg-.mjs} +15 -15
  15. package/dist/{attachmentContent-PrNJg8gG.mjs → attachmentContent-BQYc8KpE.mjs} +2 -2
  16. package/dist/{attachmentContent-4L9dO8E3.cjs → attachmentContent-CFzzTeV9.cjs} +2 -2
  17. package/dist/{attachmentLimits-BLbji11b.mjs → attachmentLimits-Di1Z93lN.mjs} +1 -1
  18. package/dist/{attachmentLimits-D6bT2jU1.cjs → attachmentLimits-DtFqqiwR.cjs} +1 -1
  19. package/dist/{auth-D1qHU-i_.mjs → auth-B3xMoveE.mjs} +5 -5
  20. package/dist/{auth-PY_HGlzz.mjs → auth-CBkmRIGw.mjs} +8 -8
  21. package/dist/{auth-BGmM3Vlm.cjs → auth-CpO3ZUMz.cjs} +5 -5
  22. package/dist/{auth-BI0CsMcy.cjs → auth-LPvsVriN.cjs} +8 -8
  23. package/dist/{auto-COMphIfD.mjs → auto-DHGch_zK.mjs} +16 -16
  24. package/dist/{auto-DM4_FeKb.cjs → auto-Dm3EIKT7.cjs} +15 -15
  25. package/dist/{bootstrap-DTJ6-vYT.cjs → bootstrap-BboDz_w2.cjs} +2 -2
  26. package/dist/{bootstrap-CWjpC5-J.mjs → bootstrap-CxuBAkJU.mjs} +2 -2
  27. package/dist/{browser-xuW4fiHo.mjs → browser-BvARP-YR.mjs} +1 -1
  28. package/dist/{browser-DmgVoopB.cjs → browser-GQZJxD2n.cjs} +1 -1
  29. package/dist/{claudeLocal-B0P-wVJJ.mjs → claudeLocal-B9EhFmD7.mjs} +6 -6
  30. package/dist/{claudeLocal-CtZVz3ee.cjs → claudeLocal-D-mujSX1.cjs} +5 -5
  31. package/dist/{claudeLocalLauncher-D4vmjI3c.mjs → claudeLocalLauncher-Bdl-9aU_.mjs} +11 -11
  32. package/dist/{claudeLocalLauncher-Dnv4CH8r.cjs → claudeLocalLauncher-Tbrx6TXF.cjs} +10 -10
  33. package/dist/{claudeSessionFork-CxjOBoBh.mjs → claudeSessionFork-D_DKvDKE.mjs} +1 -1
  34. package/dist/{claudeSessionFork-DQk5-dzR.cjs → claudeSessionFork-sOz97qqW.cjs} +1 -1
  35. package/dist/{client-eQjOvC55.mjs → client-Cg6ABRe-.mjs} +3 -3
  36. package/dist/{client-BHZVyQwi.cjs → client-D7sSU04O.cjs} +3 -3
  37. package/dist/{client-BhLhjj_x.cjs → client-D9pEOhn4.cjs} +2 -2
  38. package/dist/{client-C4ddTzrD.mjs → client-Ryu9fllj.mjs} +2 -2
  39. package/dist/codex/happyMcpStdioBridge.cjs +15 -15
  40. package/dist/codex/happyMcpStdioBridge.mjs +15 -15
  41. package/dist/{codexAppServerClient-CppPl_R6.mjs → codexAppServerClient-C70pJ-BB.mjs} +285 -28
  42. package/dist/{codexAppServerClient-D-9z-lWP.cjs → codexAppServerClient-DsIUkVnX.cjs} +281 -24
  43. package/dist/{codexCommand-AgVJYnFU.cjs → codexCommand-Aycux-B7.cjs} +156 -59
  44. package/dist/{codexCommand-BdrBNbZu.mjs → codexCommand-DWbA3pJN.mjs} +157 -60
  45. package/dist/{config-D89sE3wK.cjs → config-BcL0bxO5.cjs} +3 -3
  46. package/dist/{config-Cr3VUzbE.mjs → config-Bztmzu8z.mjs} +3 -3
  47. package/dist/{configuration-BNGPXg07.mjs → configuration-BAwOtWFY.mjs} +1 -1
  48. package/dist/{configuration-UV4EE5ui.cjs → configuration-CpBrilxV.cjs} +1 -1
  49. package/dist/{connect-B35YXbdZ.cjs → connect-BBNCMTi8.cjs} +13 -13
  50. package/dist/{connect-C0iLkCiY.mjs → connect-BeWQ4MMA.mjs} +13 -13
  51. package/dist/{context-BmH2BKip.cjs → context-Hk0j2Y9-.cjs} +1 -1
  52. package/dist/{context-Ptdnlcv6.mjs → context-j114QJre.mjs} +1 -1
  53. package/dist/{controlClient-DqtC0pq1.mjs → controlClient-00KYAjsI.mjs} +3 -3
  54. package/dist/{controlClient-CtsQMw--.cjs → controlClient-bs_YqwDl.cjs} +3 -3
  55. package/dist/{createSessionMetadata-2IuH5nlA.cjs → createSessionMetadata-D4Sj6H95.cjs} +2 -2
  56. package/dist/{createSessionMetadata-CtNMvfth.mjs → createSessionMetadata-xlycGog5.mjs} +2 -2
  57. package/dist/{defaultPermissionMode-DYihjV2g.mjs → defaultPermissionMode-B97ox9p1.mjs} +2 -2
  58. package/dist/{defaultPermissionMode-Bn4HcU8S.cjs → defaultPermissionMode-CMsiaRzr.cjs} +2 -2
  59. package/dist/{deterministicJson-je21npNx.cjs → deterministicJson-aHxtYLha.cjs} +9 -9
  60. package/dist/{deterministicJson-DF4xv6MH.mjs → deterministicJson-ucyv8j6b.mjs} +9 -9
  61. package/dist/{doctor-BXKcYVGU.cjs → doctor-BXkNXcok.cjs} +7 -7
  62. package/dist/{doctor-Ba92L7-b.mjs → doctor-D554c6Bg.mjs} +7 -7
  63. package/dist/{downloadTarget-CUJg8iJV.mjs → downloadTarget-2_zMvt2N.mjs} +6 -6
  64. package/dist/{downloadTarget-JC7FZl7W.cjs → downloadTarget-CmdlljZW.cjs} +6 -6
  65. package/dist/{ensureDaemonRunning-bIp6-vgi.cjs → ensureDaemonRunning-CY7iC--U.cjs} +5 -5
  66. package/dist/{ensureDaemonRunning-JPA9tHNE.mjs → ensureDaemonRunning-DJlziY-m.mjs} +5 -5
  67. package/dist/{handleResumeCommand-B6lE5DtU.mjs → handleResumeCommand-CNTnXBXA.mjs} +5 -5
  68. package/dist/{handleResumeCommand-B6b9kIYf.cjs → handleResumeCommand-lSVnvTNC.cjs} +5 -5
  69. package/dist/{index-CZLwo1FS.mjs → index-59hR7nVz.mjs} +3 -3
  70. package/dist/{index-DW1ONaGc.mjs → index-CxSLrTPA.mjs} +4 -4
  71. package/dist/{index-boE-d8CM.mjs → index-DMy3OCBe.mjs} +8 -1
  72. package/dist/{index-CjE4kBKx.mjs → index-DY3I8j0W.mjs} +37 -37
  73. package/dist/{index-BZdhwBKa.cjs → index-De8L5lFK.cjs} +8 -0
  74. package/dist/{index-B1ABQRrB.cjs → index-DhARRePz.cjs} +4 -4
  75. package/dist/{index-D759ViMU.cjs → index-MwTVbeGW.cjs} +3 -3
  76. package/dist/{index-B2KL0aPc.cjs → index-jeD70GGH.cjs} +36 -36
  77. package/dist/index.cjs +2 -2
  78. package/dist/index.mjs +2 -2
  79. package/dist/{install-KjIsK_EA.cjs → install-DXUEtGfU.cjs} +3 -3
  80. package/dist/{install-CmojqnLK.mjs → install-DytIJ_Ia.mjs} +3 -3
  81. package/dist/lib.cjs +12 -12
  82. package/dist/lib.mjs +12 -12
  83. package/dist/{lidState-CL1NdKfQ.mjs → lidState-CduPmrM0.mjs} +1 -1
  84. package/dist/{lidState-BmJp2pLt.cjs → lidState-UasMvPzw.cjs} +1 -1
  85. package/dist/{localHappyAgentAuth-9SP7hdiw.cjs → localHappyAgentAuth-CA02WOny.cjs} +1 -1
  86. package/dist/{localHappyAgentAuth-B7f4Ysn0.mjs → localHappyAgentAuth-DL8JjHTV.mjs} +1 -1
  87. package/dist/{logger-D5EzMy30.mjs → logger-CihCDWDw.mjs} +2 -2
  88. package/dist/{logger-C7dRaCkE.cjs → logger-zoO54Zsy.cjs} +2 -2
  89. package/dist/{machineMetadata-DYYuK_0c.cjs → machineMetadata-BAKVtr-k.cjs} +3 -3
  90. package/dist/{machineMetadata-DqplCWue.mjs → machineMetadata-DEZcQ_CQ.mjs} +3 -3
  91. package/dist/{main-kgCQgknK.cjs → main-BIvxyX71.cjs} +44 -44
  92. package/dist/{main-CnV62agu.mjs → main-DyJfNlL_.mjs} +44 -44
  93. package/dist/{manager-BEsI4qt3.mjs → manager-2Il8XJVq.mjs} +1 -1
  94. package/dist/{mcp-BV0vxHtz.cjs → mcp-Dd11vHij.cjs} +14 -14
  95. package/dist/{mcp-bDPaj-tM.mjs → mcp-yoIdGe6C.mjs} +14 -14
  96. package/dist/{mirrorProtocol-ClKhNXYe.mjs → mirrorProtocol-BukXB5s3.mjs} +3 -3
  97. package/dist/{mirrorProtocol-BSHVZ8Nf.cjs → mirrorProtocol-D-hF_SE5.cjs} +3 -3
  98. package/dist/{package-VqWv7EI5.cjs → package-A7zOGx8B.cjs} +7 -7
  99. package/dist/{package-D0dxZ-W8.mjs → package-ayqGDKSp.mjs} +7 -7
  100. package/dist/{peerTools-B_eiNB3P.mjs → peerTools-DDMSViPu.mjs} +4 -4
  101. package/dist/{peerTools-BktGmlpd.cjs → peerTools-dPc9hRC5.cjs} +4 -4
  102. package/dist/{persistence-DweHi8xa.cjs → persistence-Cih2AWml.cjs} +2 -2
  103. package/dist/{persistence-CIIhP0Uw.mjs → persistence-Dy3lmall.mjs} +2 -2
  104. package/dist/{piRunnerArgs-BNzWTNRV.cjs → piRunnerArgs-BuJgnUI5.cjs} +1 -1
  105. package/dist/{piRunnerArgs-cQafsadv.mjs → piRunnerArgs-D3z3-1VJ.mjs} +1 -1
  106. package/dist/{piRuntime-VZLSwW-4.cjs → piRuntime-B-SPcWIr.cjs} +1 -1
  107. package/dist/{piRuntime-Bel5lOLb.mjs → piRuntime-kVGue-_5.mjs} +1 -1
  108. package/dist/{piTerminal-DkR8sPv-.cjs → piTerminal-DSxK5aAm.cjs} +16 -16
  109. package/dist/{piTerminal-CS5SDi_H.mjs → piTerminal-aEtVdCJ2.mjs} +16 -16
  110. package/dist/{rateLimitWindows-Bp4T21RI.cjs → rateLimitWindows-82izLQy8.cjs} +1 -1
  111. package/dist/{rateLimitWindows-Bo6XVnie.mjs → rateLimitWindows-E5DRjfE6.mjs} +1 -1
  112. package/dist/{registerCommonHandlers-CR5jpiSx.mjs → registerCommonHandlers-Bm7CMqMv.mjs} +2 -2
  113. package/dist/{registerCommonHandlers-B7QZxkCL.cjs → registerCommonHandlers-CqO075-X.cjs} +2 -2
  114. package/dist/{registerKillSessionHandler-DLiu24CQ.mjs → registerKillSessionHandler-D02OY4vi.mjs} +6 -6
  115. package/dist/{registerKillSessionHandler-CcX84g-T.cjs → registerKillSessionHandler-WQra3T9B.cjs} +6 -6
  116. package/dist/{remoteSessionClient-CUjw1COc.mjs → remoteSessionClient-Buh6NejV.mjs} +5 -5
  117. package/dist/{remoteSessionClient-CL3akj0K.cjs → remoteSessionClient-f3DYorl8.cjs} +5 -5
  118. package/dist/{reportProgressTool-DzMi4mvH.cjs → reportProgressTool-C2gn_HWD.cjs} +2 -2
  119. package/dist/{reportProgressTool-BLLwMQrN.mjs → reportProgressTool-C5aSoKYX.mjs} +2 -2
  120. package/dist/{run-5pmOElaW.cjs → run-CDEmq6Zs.cjs} +34 -34
  121. package/dist/{run-DGokR_6q.mjs → run-Drxogp0j.mjs} +33 -33
  122. package/dist/{runClaude-BFlpZQds.mjs → runClaude-BF6U2Js7.mjs} +21 -21
  123. package/dist/{runClaude-EnYNvkV0.cjs → runClaude-yEcZTCt_.cjs} +21 -21
  124. package/dist/{runClaudeDeps-D1M1dzlZ.mjs → runClaudeDeps-Bl4ndq7N.mjs} +40 -40
  125. package/dist/{runClaudeDeps-CUDebE9e.cjs → runClaudeDeps-CnNNFjlI.cjs} +35 -35
  126. package/dist/{runGemini-Bub8T5cM.mjs → runGemini-C3wt7iv7.mjs} +32 -32
  127. package/dist/{runGemini-Bu69Zu1u.cjs → runGemini-DDVDRNg4.cjs} +32 -32
  128. package/dist/{runOpenClaw-Cob5F3FC.cjs → runOpenClaw-BzlVA_9Q.cjs} +18 -18
  129. package/dist/{runOpenClaw-DVu73F_i.mjs → runOpenClaw-CY6YHAvj.mjs} +18 -18
  130. package/dist/{sandbox-GDqMagSF.cjs → sandbox-0UNHR3hP.cjs} +4 -4
  131. package/dist/{sandbox-9EKOFyQF.mjs → sandbox-CX_wLwpq.mjs} +4 -4
  132. package/dist/selfCheck-ClVv8NK3.mjs +84 -0
  133. package/dist/{selfCheck-DiNo34da.cjs → selfCheck-FNwMFY8p.cjs} +34 -34
  134. package/dist/{send-ThC80164.cjs → send-BQkl25g0.cjs} +8 -8
  135. package/dist/{send-wgtHphq8.mjs → send-CpEGYict.mjs} +8 -8
  136. package/dist/{server-bidHnstE.cjs → server-BodFZ5sW.cjs} +6 -6
  137. package/dist/{server-Bb8v2fOj.mjs → server-DnINX_Lm.mjs} +4 -4
  138. package/dist/{sessionLock-BWBcBZKh.cjs → sessionLock-DOj6mMXn.cjs} +3 -3
  139. package/dist/{sessionLock-gb32sVPR.mjs → sessionLock-Ddn-fhZ0.mjs} +3 -3
  140. package/dist/{sessionModeFile-C-fr1M1h.mjs → sessionModeFile-DDbonFR_.mjs} +1 -1
  141. package/dist/{sessionModeFile-DhuTNcJr.cjs → sessionModeFile-DVukoSp7.cjs} +1 -1
  142. package/dist/{sessionOps-ByZJbkMq.mjs → sessionOps-B1vQ25GS.mjs} +4 -4
  143. package/dist/{sessionOps-9MChM9Op.cjs → sessionOps-Nryt1DZt.cjs} +4 -4
  144. package/dist/{sessionScanner-BpegdnXK.cjs → sessionScanner-D1h-cdte.cjs} +3 -3
  145. package/dist/{sessionScanner-CxXPAVyS.mjs → sessionScanner-DCr3ofhR.mjs} +3 -3
  146. package/dist/{sessions-C1X4z_Lm.cjs → sessions-D2HsTbLf.cjs} +9 -9
  147. package/dist/{sessions-l-UgJGjV.mjs → sessions-DpAN6Ft9.mjs} +9 -9
  148. package/dist/{setupOfflineReconnection-CS_8Da8R.cjs → setupOfflineReconnection-B9Tw1Ouj.cjs} +2 -2
  149. package/dist/{setupOfflineReconnection-CgtXlV74.mjs → setupOfflineReconnection-DQHEp330.mjs} +2 -2
  150. package/dist/{spawn-FyoHqYWo.mjs → spawn-CNjm1yOi.mjs} +14 -14
  151. package/dist/{spawn-D2BlNdZu.cjs → spawn-CvDZ38hi.cjs} +13 -13
  152. package/dist/{spawnAgents-BhsbJ253.mjs → spawnAgents-BjtmjBvP.mjs} +1 -1
  153. package/dist/{spawnAgents-CgMKuOhZ.cjs → spawnAgents-CCjJifAW.cjs} +1 -1
  154. package/dist/{spawnHappyCLI-DsC256j_.mjs → spawnHappyCLI-C8Vl56wB.mjs} +1 -1
  155. package/dist/{spawnHappyCLI-DByQcqEN.cjs → spawnHappyCLI-ahi4j6Mh.cjs} +1 -1
  156. package/dist/{specialCommands-DGUeZqdm.cjs → specialCommands-BpqnGrOP.cjs} +3 -3
  157. package/dist/{specialCommands-DUUBqzvd.mjs → specialCommands-DfVMGXTl.mjs} +3 -3
  158. package/dist/{startFileWatcher-CaYRObJu.mjs → startFileWatcher-DXJXY4AE.mjs} +1 -1
  159. package/dist/{startFileWatcher-BtBaahTn.cjs → startFileWatcher-Ddn3L0u3.cjs} +1 -1
  160. package/dist/{streamRelay-DqPFsCgx.cjs → streamRelay-Cx01enfe.cjs} +1 -1
  161. package/dist/{streamRelay-C8zI7OnR.mjs → streamRelay-_qCd873P.mjs} +1 -1
  162. package/dist/{sync-D5YqUVjS.mjs → sync-BKvgkhPs.mjs} +1 -1
  163. package/dist/{sync-BK-IBkuB.cjs → sync-BgZuthoS.cjs} +1 -1
  164. package/dist/{systemPrompt-DaTKLEb-.cjs → systemPrompt-C6O1cHUg.cjs} +2 -2
  165. package/dist/{systemPrompt-e-qeag_h.mjs → systemPrompt-DuPem6c9.mjs} +2 -2
  166. package/dist/{teams-ClrppvKu.mjs → teams-CffMBBfU.mjs} +6 -6
  167. package/dist/{teams-D9xwa_d3.cjs → teams-DifEhhmk.cjs} +6 -6
  168. package/dist/{time-CvrpeD3S.mjs → time-DxCTiteK.mjs} +1 -1
  169. package/dist/{time-0szhiPo4.cjs → time-s8CaneqW.cjs} +1 -1
  170. package/dist/{titleGenerator-BZ5770wq.mjs → titleGenerator-B5T7QSzu.mjs} +1 -1
  171. package/dist/{titleGenerator-Dz5P7sE1.cjs → titleGenerator-CXr7t6cf.cjs} +2 -2
  172. package/dist/{todo-CkmNJQey.cjs → todo-B41GKMcI.cjs} +6 -6
  173. package/dist/{todo-o-miKcN2.mjs → todo-DNO7s8td.mjs} +6 -6
  174. package/dist/{tools-Cp0qJeBq.mjs → tools-697R1uqn.mjs} +1 -1
  175. package/dist/{tools-C77-Ssan.cjs → tools-lotMyxIE.cjs} +1 -1
  176. package/dist/{uninstall-DGUPERDX.cjs → uninstall-CRu96len.cjs} +3 -3
  177. package/dist/{uninstall-jNJDCLD_.mjs → uninstall-CYO7EDjO.mjs} +3 -3
  178. package/package.json +7 -7
  179. package/dist/selfCheck-CNo4uzGB.mjs +0 -84
@@ -3,12 +3,100 @@
3
3
  var node_child_process = require('node:child_process');
4
4
  var spawn = require('cross-spawn');
5
5
  var node_readline = require('node:readline');
6
- var logger = require('./logger-C7dRaCkE.cjs');
6
+ var logger = require('./logger-zoO54Zsy.cjs');
7
7
  var contentLogMetadata = require('./contentLogMetadata-ZSFk_NjQ.cjs');
8
8
  var manager = require('./manager-HrEj442o.cjs');
9
- var _package = require('./package-VqWv7EI5.cjs');
10
- var rateLimitWindows = require('./rateLimitWindows-Bp4T21RI.cjs');
9
+ var _package = require('./package-A7zOGx8B.cjs');
10
+ var rateLimitWindows = require('./rateLimitWindows-82izLQy8.cjs');
11
11
 
12
+ const CODEX_HELPER_LABEL_MAX_CHARS = 80;
13
+ function codexHelperLabel(prompt) {
14
+ if (typeof prompt !== "string") return null;
15
+ const collapsed = prompt.replace(/\s+/g, " ").trim();
16
+ if (collapsed.length === 0) return null;
17
+ if (collapsed.length <= CODEX_HELPER_LABEL_MAX_CHARS) return collapsed;
18
+ const keep = CODEX_HELPER_LABEL_MAX_CHARS - 1;
19
+ const last = collapsed.charCodeAt(keep - 1);
20
+ const end = last >= 55296 && last <= 56319 ? keep - 1 : keep;
21
+ return `${collapsed.slice(0, end)}\u2026`;
22
+ }
23
+ function codexAgentPathSegments(agentPath) {
24
+ if (typeof agentPath !== "string") return [];
25
+ return agentPath.split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
26
+ }
27
+ function isRootAgentPath(segments) {
28
+ return segments.length === 1 && segments[0] === "root";
29
+ }
30
+ function codexChildAnnouncements(item) {
31
+ if (item.type === "subAgentActivity") {
32
+ const threadId = item.agentThreadId;
33
+ if (typeof threadId !== "string" || threadId.length === 0) return [];
34
+ const segments = codexAgentPathSegments(item.agentPath);
35
+ if (isRootAgentPath(segments)) return [];
36
+ const leaf = segments.at(-1);
37
+ return [{ threadId, label: leaf && leaf.length > 0 ? leaf : null }];
38
+ }
39
+ if (item.type === "collabAgentToolCall") {
40
+ const receivers = Array.isArray(item.receiverThreadIds) ? item.receiverThreadIds.filter((id) => typeof id === "string" && id.length > 0) : [];
41
+ const label = item.tool === "spawnAgent" ? codexHelperLabel(item.prompt) : null;
42
+ return [...new Set(receivers)].map((threadId) => ({ threadId, label }));
43
+ }
44
+ return [];
45
+ }
46
+
47
+ function stopCodexProcess(proc, deps = {}) {
48
+ const platform = deps.platform ?? process.platform;
49
+ try {
50
+ proc.stdin?.end();
51
+ } catch {
52
+ }
53
+ if (platform === "win32") return;
54
+ try {
55
+ proc.kill("SIGTERM");
56
+ } catch {
57
+ }
58
+ }
59
+ function killCodexProcessTree(proc, deps = {}) {
60
+ if (proc.exitCode != null || proc.signalCode != null) return;
61
+ const killRoot = () => {
62
+ try {
63
+ proc.kill("SIGKILL");
64
+ } catch {
65
+ }
66
+ };
67
+ const pid = proc.pid;
68
+ if (!pid || !("exitCode" in proc)) {
69
+ killRoot();
70
+ return;
71
+ }
72
+ const platform = deps.platform ?? process.platform;
73
+ const spawn = deps.spawn ?? ((command, args, options) => node_child_process.spawn(command, args, options));
74
+ if (platform === "win32") {
75
+ try {
76
+ const killer = spawn("taskkill", ["/pid", String(pid), "/t", "/f"], { stdio: "ignore", windowsHide: true });
77
+ killer.on("error", killRoot);
78
+ killer.on("exit", (code) => {
79
+ if (code !== 0) killRoot();
80
+ });
81
+ killer.unref();
82
+ } catch {
83
+ killRoot();
84
+ }
85
+ return;
86
+ }
87
+ try {
88
+ const reaper = spawn("pkill", ["-KILL", "-P", String(pid)], { stdio: "ignore", windowsHide: true });
89
+ reaper.on("error", () => void 0);
90
+ reaper.unref();
91
+ } catch {
92
+ }
93
+ killRoot();
94
+ }
95
+
96
+ function jsonRpcErrorCodeOf(error) {
97
+ const code = error?.jsonRpcCode;
98
+ return typeof code === "number" ? code : null;
99
+ }
12
100
  function isAppServerAvailable() {
13
101
  try {
14
102
  const version = node_child_process.execSync("codex --version", { encoding: "utf8", windowsHide: true }).trim();
@@ -123,6 +211,18 @@ class CodexAppServerClient {
123
211
  // Approval / elicitation requests we are still answering: a human may take
124
212
  // longer than the watchdog to decide, and that is not Codex going silent.
125
213
  inflightServerRequests = 0;
214
+ // B-628: `turn/steer` — a message sent into the running turn (approach from Orca,
215
+ // src/main/codex/codex-structured-turn-start.ts). This app-server has no such
216
+ // method (-32601) until it is respawned; a refusal is per call (the turn it named
217
+ // ended or changed meanwhile, a review/compact turn).
218
+ steerUnsupported = false;
219
+ /** Steered inputs Codex has not echoed back as a `userMessage` item yet: clientId → turnId. */
220
+ steeredAwaitingEcho = /* @__PURE__ */ new Map();
221
+ /** Waiters for the pending turn to open (steerTurn); released when it opens or ends. */
222
+ turnOpenWaiters = [];
223
+ /** B-628: the names Codex gave the child threads it spawned (see codexChildThreads.ts). */
224
+ childThreadLabels = /* @__PURE__ */ new Map();
225
+ static MAX_CHILD_LABELS = 128;
126
226
  // Handlers set by the consumer (runCodex.ts)
127
227
  eventHandler = null;
128
228
  approvalHandler = null;
@@ -193,6 +293,58 @@ class CodexAppServerClient {
193
293
  const threadId = this.extractThreadId(params);
194
294
  return threadId === null || this._threadId === null || threadId === this._threadId;
195
295
  }
296
+ /** B-628: the child thread a frame belongs to, or null for the session's own. */
297
+ childThreadIdOf(params) {
298
+ return this.isOwnThreadFrame(params) ? null : this.extractThreadId(params);
299
+ }
300
+ /**
301
+ * B-628: what a child thread's item carries so the mapper files it under the child's
302
+ * card (`subagent` → the session protocol's sub-agent envelope, as a Claude Task's
303
+ * children are) instead of in the main conversation as the session's own work.
304
+ */
305
+ childItemFields(params) {
306
+ const child = this.childThreadIdOf(params);
307
+ if (!child) return {};
308
+ const label = this.childThreadLabels.get(child);
309
+ return { subagent: child, ...label ? { subagent_label: label } : {} };
310
+ }
311
+ rememberChildLabels(item) {
312
+ for (const { threadId, label } of codexChildAnnouncements(item)) {
313
+ if (!label || this.childThreadLabels.has(threadId)) continue;
314
+ if (this.childThreadLabels.size >= CodexAppServerClient.MAX_CHILD_LABELS) {
315
+ const oldest = this.childThreadLabels.keys().next().value;
316
+ if (oldest !== void 0) this.childThreadLabels.delete(oldest);
317
+ }
318
+ this.childThreadLabels.set(threadId, label);
319
+ }
320
+ }
321
+ /**
322
+ * B-628: steered inputs the ended turn never echoed. `report` = the turn did not complete
323
+ * (interrupted, failed, app-server gone, given up): Codex never read them, tell the runner.
324
+ * A turn that *completed* drains its pending input before it ends (core/src/session/turn.rs),
325
+ * so an unechoed input there is a codex that accepted the steer but echoes no `clientId` —
326
+ * forgotten silently, because a false「not delivered」on a message the model did read would
327
+ * be worse than today's silence.
328
+ */
329
+ dropUnechoedSteers(turnId, report) {
330
+ const dropped = [];
331
+ for (const [clientId, steeredTurn] of this.steeredAwaitingEcho) {
332
+ if (turnId === null || steeredTurn === turnId) {
333
+ dropped.push(clientId);
334
+ this.steeredAwaitingEcho.delete(clientId);
335
+ }
336
+ }
337
+ if (dropped.length === 0) return;
338
+ if (!report) {
339
+ logger.logger.debug(`[CodexAppServer] ${dropped.length} steered message(s) completed without an echo; not reported`);
340
+ return;
341
+ }
342
+ this.eventHandler?.({
343
+ type: "steer_dropped",
344
+ client_ids: dropped,
345
+ ...turnId ? { turn_id: turnId } : {}
346
+ });
347
+ }
196
348
  /** Codex's last stderr lines, one line, for a message a person reads. */
197
349
  stderrTail() {
198
350
  return this.stderrRing.replace(/\x1b\[[0-9;]*m/g, "").replace(/\s+/g, " ").trim();
@@ -227,6 +379,7 @@ class CodexAppServerClient {
227
379
  this.completedTurnIds.add(turnId);
228
380
  if (failed) this.failedTurnIds.add(turnId);
229
381
  }
382
+ this.dropUnechoedSteers(turnId, aborted || failed);
230
383
  if (aborted) {
231
384
  this.eventHandler?.({
232
385
  type: "turn_aborted",
@@ -266,6 +419,11 @@ class CodexAppServerClient {
266
419
  if (method === "turn/completed") {
267
420
  if (!this.isOwnThreadFrame(params)) {
268
421
  logger.logger.debug(`[CodexAppServer] Child thread ${this.extractThreadId(params)} ended a turn`);
422
+ this.eventHandler?.({
423
+ type: "subagent_turn_end",
424
+ ...this.childItemFields(params),
425
+ status: this.extractTurnStatus(params)
426
+ });
269
427
  return true;
270
428
  }
271
429
  this.emitRawTurnCompletion(
@@ -298,6 +456,7 @@ class CodexAppServerClient {
298
456
  return true;
299
457
  }
300
458
  if (method === "thread/tokenUsage/updated") {
459
+ if (!this.isOwnThreadFrame(params)) return true;
301
460
  const tokenUsage = params?.tokenUsage;
302
461
  if (tokenUsage && typeof tokenUsage === "object") {
303
462
  this.eventHandler?.({
@@ -311,8 +470,15 @@ class CodexAppServerClient {
311
470
  if (!item || typeof item !== "object") {
312
471
  return method.startsWith("item/");
313
472
  }
473
+ const child = this.childItemFields(params);
314
474
  if ((method === "item/started" || method === "item/completed") && (item.type === "collabAgentToolCall" || item.type === "subAgentActivity")) {
315
- this.eventHandler?.({ type: "collab_agent_item", item });
475
+ this.rememberChildLabels(item);
476
+ this.eventHandler?.({ type: "collab_agent_item", item, ...child });
477
+ return true;
478
+ }
479
+ if (method === "item/completed" && item.type === "userMessage") {
480
+ const clientId = typeof item.clientId === "string" ? item.clientId : null;
481
+ if (clientId && !child.subagent) this.steeredAwaitingEcho.delete(clientId);
316
482
  return true;
317
483
  }
318
484
  if (method === "item/started" && item.type === "commandExecution") {
@@ -323,7 +489,8 @@ class CodexAppServerClient {
323
489
  callId,
324
490
  command: item.command,
325
491
  cwd: item.cwd,
326
- description: item.command
492
+ description: item.command,
493
+ ...child
327
494
  });
328
495
  return true;
329
496
  }
@@ -338,7 +505,8 @@ class CodexAppServerClient {
338
505
  duration_ms: item.durationMs ?? null,
339
506
  status: item.status,
340
507
  cwd: item.cwd,
341
- command: item.command
508
+ command: item.command,
509
+ ...child
342
510
  });
343
511
  return true;
344
512
  }
@@ -353,7 +521,8 @@ class CodexAppServerClient {
353
521
  type: "patch_apply_begin",
354
522
  call_id: callId,
355
523
  callId,
356
- changes: changes ?? {}
524
+ changes: changes ?? {},
525
+ ...child
357
526
  });
358
527
  return true;
359
528
  }
@@ -362,7 +531,8 @@ class CodexAppServerClient {
362
531
  type: "patch_apply_end",
363
532
  call_id: callId,
364
533
  callId,
365
- status: item.status
534
+ status: item.status,
535
+ ...child
366
536
  });
367
537
  if (callId && (item.status === "completed" || item.status === "failed" || item.status === "declined")) {
368
538
  this.rawFileChangesByItemId.delete(callId);
@@ -377,7 +547,8 @@ class CodexAppServerClient {
377
547
  type: "agent_message",
378
548
  message: text,
379
549
  item_id: item.id,
380
- phase: item.phase
550
+ phase: item.phase,
551
+ ...child
381
552
  });
382
553
  }
383
554
  return true;
@@ -450,6 +621,7 @@ class CodexAppServerClient {
450
621
  }
451
622
  if (this.pendingTurnCompletion) {
452
623
  const turnId = this.pendingTurnCompletion.turnId ?? this._turnId;
624
+ this.dropUnechoedSteers(null, true);
453
625
  this.eventHandler?.({
454
626
  type: "turn_aborted",
455
627
  reason: "process-exit",
@@ -460,6 +632,9 @@ class CodexAppServerClient {
460
632
  this.resolvePendingTurn(true);
461
633
  });
462
634
  this.stderrRing = "";
635
+ this.steerUnsupported = false;
636
+ this.steeredAwaitingEcho.clear();
637
+ this.childThreadLabels.clear();
463
638
  proc.stderr?.on("data", (chunk) => {
464
639
  if (this.process !== proc || this.processEpoch !== epoch) return;
465
640
  const text = chunk.toString().trim();
@@ -498,20 +673,12 @@ ${text}`.slice(-400);
498
673
  logger.logger.debug(`[CodexAppServer] Disconnecting; pid=${pid ?? "none"}`);
499
674
  this.readline?.close();
500
675
  this.readline = null;
501
- try {
502
- proc?.stdin?.end();
503
- proc?.kill("SIGTERM");
504
- } catch {
505
- }
506
- if (pid) {
507
- const killTimer = setTimeout(() => {
508
- try {
509
- process.kill(pid, 0);
510
- process.kill(pid, "SIGKILL");
511
- } catch {
512
- }
513
- }, 2e3);
514
- killTimer.unref();
676
+ if (proc) {
677
+ stopCodexProcess(proc);
678
+ if (pid) {
679
+ const killTimer = setTimeout(() => killCodexProcessTree(proc), CodexAppServerClient.FORCE_KILL_AFTER_MS);
680
+ killTimer.unref();
681
+ }
515
682
  }
516
683
  this.process = null;
517
684
  this.connected = false;
@@ -530,6 +697,7 @@ ${text}`.slice(-400);
530
697
  req.reject(new Error(`Codex process disconnected while waiting for ${req.method}`));
531
698
  this.pending.delete(id);
532
699
  }
700
+ this.dropUnechoedSteers(null, true);
533
701
  this.resolvePendingTurn(true);
534
702
  if (this.sandboxCleanup) {
535
703
  try {
@@ -733,6 +901,8 @@ ${text}`.slice(-400);
733
901
  // ─── Turn management ────────────────────────────────────────
734
902
  /** Default grace period after interrupt before forcing a restart (ms). */
735
903
  static ABORT_GRACE_MS = 3e3;
904
+ /** How long the graceful stop gets before the process tree is killed (disconnectInternal). */
905
+ static FORCE_KILL_AFTER_MS = 2e3;
736
906
  hasPendingTurnCompletion() {
737
907
  return this.pendingTurnCompletion !== null;
738
908
  }
@@ -742,6 +912,7 @@ ${text}`.slice(-400);
742
912
  this.clearThreadStopGrace();
743
913
  this.pendingTurnCompletion.resolve(aborted);
744
914
  this.pendingTurnCompletion = null;
915
+ this.releaseTurnOpenWaiters();
745
916
  }
746
917
  markPendingTurnStarted(turnId) {
747
918
  if (!this.pendingTurnCompletion) return;
@@ -749,6 +920,86 @@ ${text}`.slice(-400);
749
920
  if (turnId) {
750
921
  this.pendingTurnCompletion.turnId = turnId;
751
922
  }
923
+ this.releaseTurnOpenWaiters();
924
+ }
925
+ // ─── B-628: steering the running turn ───────────────────────
926
+ /** How long a steer waits for the pending turn to open before the message is queued instead. */
927
+ static STEER_OPEN_WAIT_MS = 5e3;
928
+ /** A turn Codex has reported running, under an id `turn/steer` can name. */
929
+ turnIsOpen() {
930
+ return this.pendingTurnCompletion?.opened === true && this._turnId !== null;
931
+ }
932
+ releaseTurnOpenWaiters() {
933
+ const waiters = this.turnOpenWaiters;
934
+ this.turnOpenWaiters = [];
935
+ for (const release of waiters) release();
936
+ }
937
+ /**
938
+ * Waits for the pending turn to open — `turn/start` is in flight, or the runner is still
939
+ * bringing a released app-server back before sending it (B-461) — as Orca's send does
940
+ * (codex-structured-turn-open-wait.ts, 5 s). Resolves early when the turn ends instead.
941
+ */
942
+ async waitForTurnOpen(timeoutMs) {
943
+ if (this.turnIsOpen()) return true;
944
+ if (timeoutMs <= 0) return false;
945
+ await new Promise((resolve) => {
946
+ const release = () => {
947
+ clearTimeout(timer);
948
+ resolve();
949
+ };
950
+ const timer = setTimeout(release, timeoutMs);
951
+ timer.unref();
952
+ this.turnOpenWaiters.push(release);
953
+ });
954
+ return this.turnIsOpen();
955
+ }
956
+ /**
957
+ * B-628: send a message into the turn running right now (`turn/steer`, codex ≥ 0.148 /
958
+ * app-server-protocol v2 `TurnSteerParams`). Codex appends it to that turn's pending input
959
+ * and the model reads it before its next call; the turn keeps its own model, approval
960
+ * policy and sandbox — the runner applies any change on the next `turn/start`. Codex
961
+ * refuses before taking any input (expectedTurnId is a precondition), so a non-`steered`
962
+ * outcome always means "queue it for the next turn as before": `no-turn` (nothing running,
963
+ * or it ended while we waited), `unsupported` (this app-server has no `turn/steer`,
964
+ * remembered until it is respawned), `refused` (Codex declined this one), `failed`
965
+ * (transport — the turn itself is reported through its own events).
966
+ */
967
+ async steerTurn(input, opts) {
968
+ if (this.steerUnsupported) return "unsupported";
969
+ if (this.pendingInterrupt) return "no-turn";
970
+ const opened = await this.waitForTurnOpen(opts?.waitForTurnMs ?? CodexAppServerClient.STEER_OPEN_WAIT_MS);
971
+ const threadId = this._threadId;
972
+ const turnId = this._turnId;
973
+ if (!opened || !threadId || !turnId || !this.connected || this.pendingInterrupt) return "no-turn";
974
+ const params = {
975
+ threadId,
976
+ expectedTurnId: turnId,
977
+ ...input.clientId ? { clientUserMessageId: input.clientId } : {},
978
+ input: [
979
+ { type: "text", text: input.text },
980
+ ...(input.images ?? []).map((path) => ({ type: "localImage", path }))
981
+ ]
982
+ };
983
+ try {
984
+ const result = await this.request("turn/steer", params);
985
+ const steeredTurnId = typeof result?.turnId === "string" && result.turnId.length > 0 ? result.turnId : turnId;
986
+ if (input.clientId) this.steeredAwaitingEcho.set(input.clientId, steeredTurnId);
987
+ logger.logger.debug(`[CodexAppServer] Steered a message into turn ${steeredTurnId}`);
988
+ return "steered";
989
+ } catch (error) {
990
+ const code = jsonRpcErrorCodeOf(error);
991
+ if (code === -32601) {
992
+ this.steerUnsupported = true;
993
+ logger.logger.debug("[CodexAppServer] turn/steer is not supported by this codex; queuing instead");
994
+ return "unsupported";
995
+ }
996
+ if (code !== null) {
997
+ logger.logger.debug("[CodexAppServer] turn/steer refused:", contentLogMetadata.errorLogMetadata(error));
998
+ return "refused";
999
+ }
1000
+ logger.logger.debug("[CodexAppServer] turn/steer failed:", contentLogMetadata.errorLogMetadata(error));
1001
+ return "failed";
1002
+ }
752
1003
  }
753
1004
  /** Default wait for Codex's `turn/completed` after its thread reported idle/systemError. */
754
1005
  static THREAD_STOP_GRACE_MS = 1500;
@@ -911,6 +1162,7 @@ ${text}`.slice(-400);
911
1162
  } catch (err) {
912
1163
  this.clearTurnWatchdog();
913
1164
  this.pendingTurnCompletion = null;
1165
+ this.releaseTurnOpenWaiters();
914
1166
  throw err;
915
1167
  }
916
1168
  const aborted = await completion;
@@ -928,6 +1180,7 @@ ${text}`.slice(-400);
928
1180
  }
929
1181
  logger.logger.warn(`[CodexAppServer] No notification from Codex for ${timeoutMs}ms \u2014 giving the turn up as aborted`);
930
1182
  const turnId = this.pendingTurnCompletion.turnId ?? this._turnId;
1183
+ this.dropUnechoedSteers(turnId, true);
931
1184
  this.eventHandler?.({
932
1185
  type: "turn_aborted",
933
1186
  reason: "timeout",
@@ -978,6 +1231,7 @@ ${text}`.slice(-400);
978
1231
  logger.logger.debug(
979
1232
  `[CodexAppServer] Clearing thread state: thread=${this._threadId ?? "none"} turn=${this._turnId ?? "none"}`
980
1233
  );
1234
+ this.dropUnechoedSteers(null, true);
981
1235
  this.resolvePendingTurn(true);
982
1236
  this._threadId = null;
983
1237
  this._turnId = null;
@@ -986,6 +1240,7 @@ ${text}`.slice(-400);
986
1240
  this.failedTurnIds.clear();
987
1241
  this.lastTurnError = null;
988
1242
  this.rawFileChangesByItemId.clear();
1243
+ this.childThreadLabels.clear();
989
1244
  }
990
1245
  // ─── JSON-RPC transport ─────────────────────────────────────
991
1246
  /** Default timeout for RPC requests (ms). */
@@ -1066,7 +1321,9 @@ ${text}`.slice(-400);
1066
1321
  }
1067
1322
  this.pending.delete(msg.id);
1068
1323
  if (msg.error) {
1069
- pending.reject(new Error(`${pending.method}: ${msg.error.message} (code=${msg.error.code})`));
1324
+ const error = new Error(`${pending.method}: ${msg.error.message} (code=${msg.error.code})`);
1325
+ if (typeof msg.error.code === "number") error.jsonRpcCode = msg.error.code;
1326
+ pending.reject(error);
1070
1327
  } else {
1071
1328
  pending.resolve(msg.result);
1072
1329
  }