very-happy-cli 0.2.158 → 0.2.160

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 (258) hide show
  1. package/dist/{AcpBackend-DIDRig5G.cjs → AcpBackend-Bm2rdke8.cjs} +78 -76
  2. package/dist/{AcpBackend-vDVLHuYJ.mjs → AcpBackend-mzv8Dhba.mjs} +4 -2
  3. package/dist/{AcpSessionManager-C44U99CC.cjs → AcpSessionManager-BAY1Pggx.cjs} +9 -9
  4. package/dist/{AcpSessionManager-CmRjfhn3.mjs → AcpSessionManager-CoMWFVw3.mjs} +1 -1
  5. package/dist/BasePermissionHandler-CFHAxumV.cjs +157 -0
  6. package/dist/BasePermissionHandler-m3WVholL.mjs +155 -0
  7. package/dist/BaseReasoningProcessor-BFa9_rZA.cjs +200 -0
  8. package/dist/BaseReasoningProcessor-CYrKBXGm.mjs +198 -0
  9. package/dist/RemoteModeDisplay-D-HewyXg.mjs +150 -0
  10. package/dist/RemoteModeDisplay-NC1gPHtj.cjs +153 -0
  11. package/dist/agentAttachments-Dbw8iMCZ.cjs +20 -0
  12. package/dist/agentAttachments-M_B5qEF2.mjs +18 -0
  13. package/dist/agentGuidance-B5NATuFa.cjs +28 -0
  14. package/dist/agentGuidance-CQuNlNx8.mjs +20 -0
  15. package/dist/{agentHome-Dw8Jx_CJ.cjs → agentHome-CboCeKWq.cjs} +14 -28
  16. package/dist/{agentHome-CyLmGH5L.mjs → agentHome-Dj1C43aJ.mjs} +8 -22
  17. package/dist/api-CLMUr-SX.mjs +3339 -0
  18. package/dist/api-CgundNNX.cjs +3346 -0
  19. package/dist/{types-DIBF4U0Y.mjs → apiMachine-B9dLW_p5.mjs} +9116 -16015
  20. package/dist/{types-DnrPeN80.cjs → apiMachine-Bn8482VM.cjs} +9104 -16057
  21. package/dist/assistantTools-BTqPnlFl.cjs +380 -0
  22. package/dist/assistantTools-D6tuc6o4.mjs +376 -0
  23. package/dist/attachmentContent-DpiTJZb4.cjs +88 -0
  24. package/dist/attachmentContent-_kxRznNf.mjs +82 -0
  25. package/dist/attachmentLimits-CzVrqgLR.cjs +354 -0
  26. package/dist/attachmentLimits-yba1uHFO.mjs +348 -0
  27. package/dist/auth-BDOVh5h5.cjs +220 -0
  28. package/dist/auth-Cwutmdsa.mjs +225 -0
  29. package/dist/auth-PYHZQNPp.mjs +218 -0
  30. package/dist/auth-ba4WMYrN.cjs +227 -0
  31. package/dist/authRelay-BdYkC1Po.cjs +156 -0
  32. package/dist/authRelay-DSAvg1uv.mjs +143 -0
  33. package/dist/{auto-DZbNcTXx.cjs → auto-BOX_fgmR.cjs} +70 -79
  34. package/dist/{auto-BlMZPwOk.mjs → auto-BXu14yP_.mjs} +27 -36
  35. package/dist/backgroundTaskActivity-8PdPxrvy.mjs +149 -0
  36. package/dist/backgroundTaskActivity-CBvUdj39.cjs +157 -0
  37. package/dist/bootstrap-B5G1TijC.cjs +116 -0
  38. package/dist/bootstrap-hxXPCFMx.mjs +112 -0
  39. package/dist/browser-Y6Bl8L_O.cjs +22 -0
  40. package/dist/browser-jh2P0UVZ.mjs +20 -0
  41. package/dist/claudeCliPath-BqkaH2oR.mjs +8 -0
  42. package/dist/claudeCliPath-U4HHmV4r.cjs +10 -0
  43. package/dist/claudeLocal-BaY4fZKi.mjs +339 -0
  44. package/dist/claudeLocal-CRGG4Pea.cjs +343 -0
  45. package/dist/claudeLocalLauncher-D4T7MTqd.mjs +152 -0
  46. package/dist/claudeLocalLauncher-DyEbVzUN.cjs +154 -0
  47. package/dist/cliUpdate-DsKXPFYp.cjs +120 -0
  48. package/dist/cliUpdate-Y34VGe9Y.mjs +112 -0
  49. package/dist/client-3Ac-O4pw.cjs +104 -0
  50. package/dist/client-BPNbmtvO.cjs +119 -0
  51. package/dist/client-CeGKqqcJ.mjs +100 -0
  52. package/dist/client-ClR0K8zX.mjs +112 -0
  53. package/dist/codex/happyMcpStdioBridge.cjs +33 -14
  54. package/dist/codex/happyMcpStdioBridge.mjs +26 -7
  55. package/dist/codexAppServerClient-I3teiV-N.mjs +1088 -0
  56. package/dist/codexAppServerClient-q2FjnRcK.cjs +1090 -0
  57. package/dist/codexCommand-4zcccIoq.cjs +2088 -0
  58. package/dist/codexCommand-Cc9gcbdX.mjs +2086 -0
  59. package/dist/codexThreadFork-BH9IZPqD.cjs +350 -0
  60. package/dist/codexThreadFork-slzAseLx.mjs +338 -0
  61. package/dist/{config-BtPArqRH.mjs → config-CTx_jb-C.mjs} +7 -40
  62. package/dist/{config-DG84bjwF.cjs → config-Ci9Kpgwa.cjs} +26 -59
  63. package/dist/configuration-BSYpcPwE.cjs +181 -0
  64. package/dist/configuration-RfeNjFmd.mjs +170 -0
  65. package/dist/connect-BpOdzNbE.mjs +682 -0
  66. package/dist/connect-C2CiOUFs.cjs +684 -0
  67. package/dist/constants-BC4St0xd.mjs +11 -0
  68. package/dist/constants-VJ0N6WuG.cjs +17 -0
  69. package/dist/contentLogMetadata-BlWI0egu.mjs +51 -0
  70. package/dist/contentLogMetadata-ZSFk_NjQ.cjs +54 -0
  71. package/dist/context-DsDr6E2t.cjs +69 -0
  72. package/dist/context-H0Bcb9S_.mjs +65 -0
  73. package/dist/controlClient-BGbDcgWS.mjs +260 -0
  74. package/dist/controlClient-Bcwv3D21.cjs +279 -0
  75. package/dist/createSessionMetadata-BJxEnM-o.cjs +58 -0
  76. package/dist/createSessionMetadata-CVVkGjxV.mjs +54 -0
  77. package/dist/defaultPermissionMode-BnxJPVHT.mjs +4 -0
  78. package/dist/defaultPermissionMode-CxmTXUQR.cjs +7 -0
  79. package/dist/detectCLI-CSGMlV51.mjs +58 -0
  80. package/dist/detectCLI-DR9ZaN6B.cjs +61 -0
  81. package/dist/deterministicJson-C5CYTVpm.cjs +507 -0
  82. package/dist/deterministicJson-CzkFJWw1.mjs +502 -0
  83. package/dist/doctor-BPkYWSuq.mjs +75 -0
  84. package/dist/doctor-D2YJ-Yn2.cjs +395 -0
  85. package/dist/doctor-DOvByjbk.mjs +391 -0
  86. package/dist/doctor-u46qYYKX.cjs +79 -0
  87. package/dist/doctorReadiness-BCZGcN0a.cjs +151 -0
  88. package/dist/doctorReadiness-C208SMN9.mjs +142 -0
  89. package/dist/editPaths-BVfS_FFL.mjs +68 -0
  90. package/dist/editPaths-Bqp4OFPw.cjs +73 -0
  91. package/dist/ensureDaemonRunning-BCwNrMyv.cjs +64 -0
  92. package/dist/ensureDaemonRunning-Dqa2pOjY.mjs +61 -0
  93. package/dist/handleResumeCommand-BvXYf5El.mjs +240 -0
  94. package/dist/handleResumeCommand-C2cKchpX.cjs +245 -0
  95. package/dist/ids-B6ZC0HGt.cjs +13 -0
  96. package/dist/ids-DU6sLx4C.mjs +10 -0
  97. package/dist/index-B6UGRQ7h.mjs +102 -0
  98. package/dist/{index-DPCsWlWK.cjs → index-B6pAdvJx.cjs} +131 -91
  99. package/dist/index-Bu5Zi_a9.cjs +182 -0
  100. package/dist/index-D3kI0hDR.cjs +107 -0
  101. package/dist/index-DA7yINuk.cjs +994 -0
  102. package/dist/index-DDeHXrIX.cjs +71 -0
  103. package/dist/index-DKLU_fD0.mjs +158 -0
  104. package/dist/{index-ZChGsuB7.mjs → index-DMZqWwsP.mjs} +79 -39
  105. package/dist/index-DVkMGPyS.mjs +68 -0
  106. package/dist/index-qdS1friN.mjs +949 -0
  107. package/dist/index.cjs +5 -46
  108. package/dist/index.mjs +5 -46
  109. package/dist/{install-DarS_Wco.mjs → install-BO_W7VhL.mjs} +37 -37
  110. package/dist/install-BgoC2e_2.cjs +88 -0
  111. package/dist/install-CFY3tYtJ.mjs +86 -0
  112. package/dist/{install-wKQGgXvN.cjs → install-Cs5qAPrB.cjs} +38 -38
  113. package/dist/{installPiTools-DuZ6jZvX.cjs → installPiTools-BKnXjrVu.cjs} +2 -3
  114. package/dist/{installPiTools-Cj7yU9Fc.mjs → installPiTools-B_CdM5_2.mjs} +1 -2
  115. package/dist/{installTerminalHooks-DcQfee_O.cjs → installTerminalHooks-BQZbvxsZ.cjs} +5 -40
  116. package/dist/{installTerminalHooks-CpNbRFPz.mjs → installTerminalHooks-By7gBMEF.mjs} +3 -38
  117. package/dist/lib.cjs +28 -19
  118. package/dist/lib.d.cts +126 -2
  119. package/dist/lib.d.mts +126 -2
  120. package/dist/lib.mjs +23 -14
  121. package/dist/lidState-BeDfxxEX.cjs +305 -0
  122. package/dist/lidState-CeEt442o.mjs +297 -0
  123. package/dist/limits-C-a7gr04.cjs +43 -0
  124. package/dist/limits-DIo7rEBR.mjs +36 -0
  125. package/dist/localHappyAgentAuth-C-HQyiv6.mjs +82 -0
  126. package/dist/localHappyAgentAuth-D6rFhaoc.cjs +86 -0
  127. package/dist/logger-6HYUEXNk.mjs +271 -0
  128. package/dist/logger-CS0mw3fa.cjs +275 -0
  129. package/dist/loginShellEnv-BkuYtExZ.cjs +182 -0
  130. package/dist/loginShellEnv-Dw8M7tkI.mjs +167 -0
  131. package/dist/machineMetadata-DyDbODYd.cjs +41 -0
  132. package/dist/machineMetadata-oOzBfDfs.mjs +38 -0
  133. package/dist/main-BkxJP6JQ.cjs +941 -0
  134. package/dist/main-BwNIAI1A.mjs +939 -0
  135. package/dist/manager-BQ4flvQZ.mjs +101 -0
  136. package/dist/manager-Cly8xVIR.cjs +105 -0
  137. package/dist/{mcp-BN6bKIGb.mjs → mcp-B1A4I3TK.mjs} +27 -33
  138. package/dist/{mcp-DGdeUUDJ.cjs → mcp-Hszd7qpS.cjs} +42 -48
  139. package/dist/messageBuffer-BWlGgR3A.mjs +71 -0
  140. package/dist/messageBuffer-fJMH6uY8.cjs +73 -0
  141. package/dist/mirrorProtocol-BNLtoWjO.mjs +170 -0
  142. package/dist/mirrorProtocol-BUtmg1ws.cjs +186 -0
  143. package/dist/oneShotPrompts-CL0dip9C.cjs +16 -0
  144. package/dist/oneShotPrompts-DT4p6RNd.mjs +12 -0
  145. package/dist/package-BhaKlnxz.mjs +171 -0
  146. package/dist/package-BwMrPwqH.cjs +173 -0
  147. package/dist/path-B7zW-WwE.cjs +18 -0
  148. package/dist/path-D2wdaNSk.mjs +15 -0
  149. package/dist/peerTools-BTqw97Gb.mjs +272 -0
  150. package/dist/peerTools-BvKtHXj8.cjs +283 -0
  151. package/dist/permissionMode-Cr5JCbB7.mjs +80 -0
  152. package/dist/permissionMode-CrV-XuMs.cjs +87 -0
  153. package/dist/persistence-HGW_ZVs9.mjs +372 -0
  154. package/dist/persistence-yKTH3-5X.cjs +414 -0
  155. package/dist/piExtension.mjs +2 -1
  156. package/dist/piRunnerArgs-BNloJCCg.cjs +66 -0
  157. package/dist/piRunnerArgs-BuX1UFWy.mjs +59 -0
  158. package/dist/{piRuntime-bkw2NAZU.mjs → piRuntime-CSGkwCKQ.mjs} +2 -2
  159. package/dist/{piRuntime-3qtbKujX.cjs → piRuntime-C_H7MJCM.cjs} +4 -4
  160. package/dist/{piTerminal-DilKwM7B.mjs → piTerminal-C8a1OrNQ.mjs} +32 -35
  161. package/dist/{piTerminal-BYxp3LMr.cjs → piTerminal-DNCZ6yTM.cjs} +32 -35
  162. package/dist/previewPath-B0rBdhy1.cjs +83 -0
  163. package/dist/previewPath-CXN4Vag0.mjs +81 -0
  164. package/dist/projectPath-BTBIMB57.mjs +10 -0
  165. package/dist/projectPath-ChLhdOyt.cjs +13 -0
  166. package/dist/registerCommonHandlers-Ccvsz7Ou.mjs +536 -0
  167. package/dist/registerCommonHandlers-DskirN-_.cjs +538 -0
  168. package/dist/registerKillSessionHandler-DZeLXWcB.cjs +361 -0
  169. package/dist/registerKillSessionHandler-GYvHdipX.mjs +358 -0
  170. package/dist/remoteSessionClient-B0LraSB9.cjs +634 -0
  171. package/dist/remoteSessionClient-CYnXRynE.mjs +612 -0
  172. package/dist/resources-BdFBQi8r.mjs +117 -0
  173. package/dist/resources-JDPugcDq.cjs +120 -0
  174. package/dist/run-CJzxoHVh.cjs +5762 -0
  175. package/dist/run-D3ifupU3.mjs +5739 -0
  176. package/dist/runClaude-Ba01qT-u.mjs +848 -0
  177. package/dist/runClaude-Da3RirzE.cjs +850 -0
  178. package/dist/runClaudeDeps-DOt79DjU.mjs +3624 -0
  179. package/dist/runClaudeDeps-DOzEBMls.cjs +3649 -0
  180. package/dist/{runGemini-Cjii069p.mjs → runGemini-BGeTz57m.mjs} +58 -31
  181. package/dist/{runGemini-28O2sqyI.cjs → runGemini-DSr9LIxL.cjs} +202 -175
  182. package/dist/{runOpenClaw-CiMZad-H.cjs → runOpenClaw-B1mTxN35.cjs} +64 -65
  183. package/dist/{runOpenClaw-jaLr7KF1.mjs → runOpenClaw-CogSedIc.mjs} +31 -32
  184. package/dist/sandbox-CG7IyDTU.cjs +187 -0
  185. package/dist/sandbox-DTe6d54R.mjs +180 -0
  186. package/dist/selfCheck-C9mVrQwf.mjs +84 -0
  187. package/dist/selfCheck-Dc-mNSLb.cjs +87 -0
  188. package/dist/{send-D5ejHPXG.cjs → send-B7J_eaG3.cjs} +16 -9
  189. package/dist/{send-C9mOtChi.mjs → send-CBXJKc6O.mjs} +12 -5
  190. package/dist/server-CZTP_iOn.cjs +407 -0
  191. package/dist/server-DcVBv04l.mjs +404 -0
  192. package/dist/sessionLock-Bys1PNSo.cjs +205 -0
  193. package/dist/sessionLock-D-EG2CfG.mjs +197 -0
  194. package/dist/sessionModeFile-DMl3dw3r.mjs +32 -0
  195. package/dist/sessionModeFile-RSm0NQkH.cjs +36 -0
  196. package/dist/sessionOps-Dn8z85h_.cjs +783 -0
  197. package/dist/sessionOps-SuHW8Dfe.mjs +760 -0
  198. package/dist/sessionScanner-BOrGjMXL.cjs +209 -0
  199. package/dist/sessionScanner-CX3onqXh.mjs +206 -0
  200. package/dist/{sessions-W6771g3X.mjs → sessions-BEG_HTSi.mjs} +17 -8
  201. package/dist/{sessions-BNMPQoLE.cjs → sessions-D74aJbhL.cjs} +37 -28
  202. package/dist/setupOfflineReconnection-ByElY60m.cjs +74 -0
  203. package/dist/setupOfflineReconnection-DpvWTt69.mjs +72 -0
  204. package/dist/smallFastModel-BLNgMrwR.mjs +18 -0
  205. package/dist/smallFastModel-D_uxGMo3.cjs +21 -0
  206. package/dist/{spawn-D0QVhzRb.mjs → spawn-B7yro0b2.mjs} +26 -38
  207. package/dist/{spawn-Ddtom1cb.cjs → spawn-DgR0RKRs.cjs} +52 -64
  208. package/dist/spawnAgents-BGQiEF-w.cjs +52 -0
  209. package/dist/spawnAgents-DZzZ9jMI.mjs +45 -0
  210. package/dist/spawnHappyCLI-B2H5s4B_.mjs +64 -0
  211. package/dist/spawnHappyCLI-DBhwZT7O.cjs +66 -0
  212. package/dist/specialCommands-BSqhYg5X.mjs +52 -0
  213. package/dist/specialCommands-DSsTeRej.cjs +54 -0
  214. package/dist/startFileWatcher-B4VsLgjD.cjs +71 -0
  215. package/dist/startFileWatcher-DErVWZE4.mjs +69 -0
  216. package/dist/startupPlan-BLMbfQIH.cjs +12 -0
  217. package/dist/startupPlan-DFMyNgAs.mjs +10 -0
  218. package/dist/streamRelay-BiKw59Cc.cjs +233 -0
  219. package/dist/streamRelay-FPVbHpbM.mjs +231 -0
  220. package/dist/sync-C8gyQFMc.mjs +69 -0
  221. package/dist/sync-DccIKZ5_.cjs +71 -0
  222. package/dist/systemPrompt-BwTPWfMu.cjs +97 -0
  223. package/dist/systemPrompt-DX521JJz.mjs +94 -0
  224. package/dist/{teams-CqSwtw2O.mjs → teams-C32F1hqd.mjs} +9 -40
  225. package/dist/{teams-BZ1tayg_.cjs → teams-Dl8g8kTI.cjs} +14 -45
  226. package/dist/template-BaHAmH2K.cjs +129 -0
  227. package/dist/template-CiOPa2rd.mjs +121 -0
  228. package/dist/{terminalTitleSuggest-DKgX3osW.mjs → terminalTitleSuggest-CeKsX_V6.mjs} +1 -9
  229. package/dist/{terminalTitleSuggest-Dji8I0Jy.cjs → terminalTitleSuggest-DhvRFX3H.cjs} +0 -10
  230. package/dist/terminals-B_bfC9c2.cjs +250 -0
  231. package/dist/terminals-Dlg0x3nY.mjs +235 -0
  232. package/dist/time-D0XyHOid.mjs +38 -0
  233. package/dist/time-DCuTyook.cjs +42 -0
  234. package/dist/titleGenerator-CQ8CoGhg.mjs +166 -0
  235. package/dist/titleGenerator-ChzMJsyg.cjs +172 -0
  236. package/dist/tmuxSocket-B8Yx20sT.mjs +19 -0
  237. package/dist/tmuxSocket-D-Xt6Vn-.cjs +24 -0
  238. package/dist/{todo-BYMg0fR0.cjs → todo-BvUOTa8G.cjs} +15 -12
  239. package/dist/{todo-BbusB1zM.mjs → todo-CZ6cFrrn.mjs} +11 -8
  240. package/dist/tools-BZtHF_qQ.mjs +177 -0
  241. package/dist/tools-Be3AoAwu.cjs +63 -0
  242. package/dist/tools-DQj0AeLk.cjs +180 -0
  243. package/dist/tools-DkluDcG4.mjs +60 -0
  244. package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
  245. package/dist/trimIdent-BAjmv_TG.mjs +20 -0
  246. package/dist/types-CRS-srZK.cjs +66 -0
  247. package/dist/types-CkqAACXx.mjs +64 -0
  248. package/dist/uninstall-BkLzaJ6I.mjs +47 -0
  249. package/dist/uninstall-x-TUtf5H.cjs +49 -0
  250. package/package.json +7 -7
  251. package/dist/agentGuidance-CrR9l62U.mjs +0 -2145
  252. package/dist/agentGuidance-DwOWbX55.cjs +0 -2217
  253. package/dist/index-BG932eCh.cjs +0 -19655
  254. package/dist/index-CVCt3kSt.mjs +0 -19591
  255. package/dist/index-D5ScEErM.cjs +0 -58
  256. package/dist/index-DgO0FHOx.mjs +0 -52
  257. package/dist/limits-D2uN090G.mjs +0 -2528
  258. package/dist/limits-kqFqhfsh.cjs +0 -2652
@@ -0,0 +1,2088 @@
1
+ 'use strict';
2
+
3
+ var auth = require('./auth-ba4WMYrN.cjs');
4
+ var index = require('./index-DA7yINuk.cjs');
5
+ var node_crypto = require('node:crypto');
6
+ var cuid2 = require('@paralleldrive/cuid2');
7
+ var agentAttachments = require('./agentAttachments-Dbw8iMCZ.cjs');
8
+ var attachmentContent = require('./attachmentContent-DpiTJZb4.cjs');
9
+ var ink = require('ink');
10
+ var sessionLock = require('./sessionLock-Bys1PNSo.cjs');
11
+ var React = require('react');
12
+ var api = require('./api-CgundNNX.cjs');
13
+ var codexAppServerClient = require('./codexAppServerClient-q2FjnRcK.cjs');
14
+ var logger = require('./logger-CS0mw3fa.cjs');
15
+ var BasePermissionHandler = require('./BasePermissionHandler-CFHAxumV.cjs');
16
+ var BaseReasoningProcessor = require('./BaseReasoningProcessor-BFa9_rZA.cjs');
17
+ var node_child_process = require('node:child_process');
18
+ var persistence = require('./persistence-yKTH3-5X.cjs');
19
+ var machineMetadata = require('./machineMetadata-DyDbODYd.cjs');
20
+ var configuration = require('./configuration-BSYpcPwE.cjs');
21
+ var registerKillSessionHandler = require('./registerKillSessionHandler-DZeLXWcB.cjs');
22
+ var projectPath = require('./projectPath-ChLhdOyt.cjs');
23
+ var path = require('node:path');
24
+ var createSessionMetadata = require('./createSessionMetadata-BJxEnM-o.cjs');
25
+ var deterministicJson = require('./deterministicJson-C5CYTVpm.cjs');
26
+ var messageBuffer = require('./messageBuffer-fJMH6uY8.cjs');
27
+ var controlClient = require('./controlClient-Bcwv3D21.cjs');
28
+ var authRelay = require('./authRelay-BdYkC1Po.cjs');
29
+ var setupOfflineReconnection = require('./setupOfflineReconnection-ByElY60m.cjs');
30
+ var trimIdent = require('./trimIdent-4gvk9Wk6.cjs');
31
+ var specialCommands = require('./specialCommands-DSsTeRej.cjs');
32
+ var constants = require('./constants-VJ0N6WuG.cjs');
33
+ var defaultPermissionMode = require('./defaultPermissionMode-CxmTXUQR.cjs');
34
+ var editPaths = require('./editPaths-Bqp4OFPw.cjs');
35
+ var ensureDaemonRunning = require('./ensureDaemonRunning-BCwNrMyv.cjs');
36
+ require('tweetnacl');
37
+ require('axios');
38
+ require('./time-DCuTyook.cjs');
39
+ require('./browser-Y6Bl8L_O.cjs');
40
+ require('open');
41
+ require('zod');
42
+ require('node:fs/promises');
43
+ require('./attachmentLimits-CzVrqgLR.cjs');
44
+ require('node:fs');
45
+ require('node:events');
46
+ require('socket.io-client');
47
+ require('./limits-C-a7gr04.cjs');
48
+ require('./lidState-BeDfxxEX.cjs');
49
+ require('os');
50
+ require('child_process');
51
+ require('./registerCommonHandlers-DskirN-_.cjs');
52
+ require('util');
53
+ require('fs/promises');
54
+ require('crypto');
55
+ require('path');
56
+ require('cross-spawn');
57
+ require('./sync-DccIKZ5_.cjs');
58
+ require('./backgroundTaskActivity-CBvUdj39.cjs');
59
+ require('./contentLogMetadata-ZSFk_NjQ.cjs');
60
+ require('chalk');
61
+ require('node:readline');
62
+ require('./manager-Cly8xVIR.cjs');
63
+ require('@anthropic-ai/sandbox-runtime');
64
+ require('node:os');
65
+ require('./package-BwMrPwqH.cjs');
66
+ require('node:util');
67
+ require('./detectCLI-DR9ZaN6B.cjs');
68
+ require('fs');
69
+ require('./localHappyAgentAuth-D6rFhaoc.cjs');
70
+ require('./types-CRS-srZK.cjs');
71
+ require('url');
72
+ require('./client-3Ac-O4pw.cjs');
73
+ require('./context-DsDr6E2t.cjs');
74
+ require('./sessionOps-Dn8z85h_.cjs');
75
+ require('./resources-JDPugcDq.cjs');
76
+ require('./tools-Be3AoAwu.cjs');
77
+ require('./tools-DQj0AeLk.cjs');
78
+ require('./client-BPNbmtvO.cjs');
79
+ require('./peerTools-BvKtHXj8.cjs');
80
+ require('./ids-B6ZC0HGt.cjs');
81
+ require('./remoteSessionClient-B0LraSB9.cjs');
82
+ require('@modelcontextprotocol/sdk/server/mcp.js');
83
+ require('node:http');
84
+ require('@modelcontextprotocol/sdk/server/streamableHttp.js');
85
+ require('./assistantTools-BTqPnlFl.cjs');
86
+ require('./terminals-B_bfC9c2.cjs');
87
+ require('./terminalTitleSuggest-DhvRFX3H.cjs');
88
+ require('./tmuxSocket-D-Xt6Vn-.cjs');
89
+ require('./bootstrap-B5G1TijC.cjs');
90
+ require('./agentGuidance-B5NATuFa.cjs');
91
+ require('./previewPath-B0rBdhy1.cjs');
92
+ require('./spawnHappyCLI-DBhwZT7O.cjs');
93
+ require('./doctorReadiness-BCZGcN0a.cjs');
94
+
95
+ function getStartedSubagents(state) {
96
+ return state.startedSubagents ?? /* @__PURE__ */ new Set();
97
+ }
98
+ function getActiveSubagents(state) {
99
+ return state.activeSubagents ?? /* @__PURE__ */ new Set();
100
+ }
101
+ function getProviderSubagentToSessionSubagent(state) {
102
+ return state.providerSubagentToSessionSubagent ?? /* @__PURE__ */ new Map();
103
+ }
104
+ function maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes) {
105
+ if (!subagent || startedSubagents.has(subagent)) {
106
+ return;
107
+ }
108
+ envelopes.push(index.createEnvelope("agent", { t: "start" }, { ...opts, subagent }));
109
+ startedSubagents.add(subagent);
110
+ activeSubagents.add(subagent);
111
+ }
112
+ function emitSubagentStops(opts, startedSubagents, activeSubagents) {
113
+ const envelopes = [];
114
+ for (const subagent of activeSubagents) {
115
+ envelopes.push(index.createEnvelope("agent", { t: "stop" }, { ...opts, subagent }));
116
+ }
117
+ activeSubagents.clear();
118
+ startedSubagents.clear();
119
+ return envelopes;
120
+ }
121
+ function buildEnvelopeOptions(currentTurnId, subagent) {
122
+ return {
123
+ ...currentTurnId ? { turn: currentTurnId } : {},
124
+ ...subagent ? { subagent } : {}
125
+ };
126
+ }
127
+ function pickProviderSubagent(message) {
128
+ const candidates = [message.subagent, message.parent_call_id, message.parentCallId];
129
+ for (const candidate of candidates) {
130
+ if (typeof candidate === "string" && candidate.length > 0) {
131
+ return candidate;
132
+ }
133
+ }
134
+ return void 0;
135
+ }
136
+ function resolveSessionSubagent(message, providerSubagentToSessionSubagent) {
137
+ const providerSubagent = pickProviderSubagent(message);
138
+ if (!providerSubagent) {
139
+ return void 0;
140
+ }
141
+ const existing = providerSubagentToSessionSubagent.get(providerSubagent);
142
+ if (existing) {
143
+ return existing;
144
+ }
145
+ const created = cuid2.createId();
146
+ providerSubagentToSessionSubagent.set(providerSubagent, created);
147
+ return created;
148
+ }
149
+ function pickCallId(message) {
150
+ const callId = message.call_id ?? message.callId;
151
+ if (typeof callId === "string" && callId.length > 0) {
152
+ return callId;
153
+ }
154
+ return node_crypto.randomUUID();
155
+ }
156
+ function summarizeCommand(command) {
157
+ if (typeof command === "string" && command.trim().length > 0) {
158
+ return command;
159
+ }
160
+ if (Array.isArray(command)) {
161
+ const cmd = command.map((v) => String(v)).join(" ").trim();
162
+ return cmd.length > 0 ? cmd : null;
163
+ }
164
+ return null;
165
+ }
166
+ function commandToTitle(command) {
167
+ if (!command) {
168
+ return "Run command";
169
+ }
170
+ const short = command.length > 80 ? `${command.slice(0, 77)}...` : command;
171
+ return `Run \`${short}\``;
172
+ }
173
+ function turnTimestampMs(turn) {
174
+ const seconds = turn.startedAt ?? turn.completedAt;
175
+ return typeof seconds === "number" && Number.isFinite(seconds) ? seconds * 1e3 : Date.now();
176
+ }
177
+ function completedTimestampMs(turn) {
178
+ const seconds = turn.completedAt ?? turn.startedAt;
179
+ return typeof seconds === "number" && Number.isFinite(seconds) ? seconds * 1e3 : Date.now();
180
+ }
181
+ function textFromInputItems(items) {
182
+ if (!Array.isArray(items)) {
183
+ return null;
184
+ }
185
+ const text = items.filter((item) => Boolean(item) && typeof item === "object" && item.type === "text" && typeof item.text === "string").map((item) => item.text).join("\n").trim();
186
+ return text.length > 0 ? text : null;
187
+ }
188
+ function reasoningText(item) {
189
+ const summary = item.summary;
190
+ const content = item.content;
191
+ const parts = [
192
+ ...Array.isArray(summary) ? summary : [],
193
+ ...Array.isArray(content) ? content : []
194
+ ].filter((value) => typeof value === "string" && value.trim().length > 0);
195
+ const text = parts.join("\n").trim();
196
+ return text.length > 0 ? text : null;
197
+ }
198
+ function turnStatus(turn) {
199
+ const status = typeof turn.status === "string" ? turn.status : null;
200
+ if (status === "failed") {
201
+ return "failed";
202
+ }
203
+ if (status === "cancelled" || status === "canceled" || status === "aborted" || status === "interrupted") {
204
+ return "cancelled";
205
+ }
206
+ return "completed";
207
+ }
208
+ function emitHistoricalToolCall(envelopes, turn, item, name, title, args, output) {
209
+ const time = turnTimestampMs(turn);
210
+ const opts = { turn: turn.id, time, codexItemId: item.id };
211
+ envelopes.push(index.createEnvelope("agent", {
212
+ t: "tool-call-start",
213
+ call: item.id,
214
+ name,
215
+ title,
216
+ description: title,
217
+ args
218
+ }, {
219
+ ...opts,
220
+ id: `${item.id}:start`
221
+ }));
222
+ if (output && output.trim().length > 0) {
223
+ envelopes.push(index.createEnvelope("agent", {
224
+ t: "text",
225
+ text: output,
226
+ thinking: true
227
+ }, {
228
+ ...opts,
229
+ id: `${item.id}:output`
230
+ }));
231
+ }
232
+ if ("status" in item && (item.status === "inProgress" || item.status === "running")) return;
233
+ envelopes.push(index.createEnvelope("agent", {
234
+ t: "tool-call-end",
235
+ call: item.id
236
+ }, {
237
+ ...opts,
238
+ id: `${item.id}:end`,
239
+ time: completedTimestampMs(turn)
240
+ }));
241
+ }
242
+ function mapCodexCollaborationItem(item, opts = {}, source = "history") {
243
+ if (item.type === "subAgentActivity" && typeof item.agentThreadId === "string") {
244
+ item = { ...item, type: "collabAgentToolCall", tool: item.kind, status: "completed", receiverThreadIds: [item.agentThreadId] };
245
+ }
246
+ if (item.type !== "collabAgentToolCall" || typeof item.id !== "string" || typeof item.tool !== "string") return [];
247
+ const args = {
248
+ operation: item.tool,
249
+ ...typeof item.prompt === "string" ? { prompt: item.prompt } : {},
250
+ ...typeof item.model === "string" ? { model: item.model } : {},
251
+ receiverThreadIds: Array.isArray(item.receiverThreadIds) ? item.receiverThreadIds : [],
252
+ agentsStates: item.agentsStates ?? {}
253
+ };
254
+ const startId = source === "live" ? `${item.id}:${item.status ?? "unknown"}:start` : `${item.id}:start`;
255
+ const envelopes = [index.createEnvelope("agent", {
256
+ t: "tool-call-start",
257
+ call: item.id,
258
+ name: "CodexCollaboration",
259
+ title: `Codex \xB7 ${item.tool}`,
260
+ description: `Codex \xB7 ${item.tool}`,
261
+ args
262
+ }, { ...opts, id: startId })];
263
+ if (item.status === "completed" || item.status === "failed" || item.status === "interrupted") {
264
+ envelopes.push(index.createEnvelope("agent", {
265
+ t: "tool-call-end",
266
+ call: item.id,
267
+ result: { text: JSON.stringify(args, null, 2), isError: item.status !== "completed" }
268
+ }, { ...opts, id: `${item.id}:end` }));
269
+ }
270
+ return envelopes;
271
+ }
272
+ function mapCodexThreadToSessionEnvelopes(thread) {
273
+ const envelopes = [];
274
+ for (const turn of thread.turns ?? []) {
275
+ const startedAt = turnTimestampMs(turn);
276
+ const completedAt = completedTimestampMs(turn);
277
+ envelopes.push(index.createEnvelope("agent", { t: "turn-start" }, {
278
+ id: `${turn.id}:start`,
279
+ turn: turn.id,
280
+ time: startedAt
281
+ }));
282
+ for (const item of turn.items ?? []) {
283
+ switch (item.type) {
284
+ case "subAgentActivity":
285
+ case "collabAgentToolCall": {
286
+ envelopes.push(...mapCodexCollaborationItem(item, { turn: turn.id, time: startedAt, codexItemId: item.id }));
287
+ break;
288
+ }
289
+ case "userMessage": {
290
+ const text = textFromInputItems(item.content);
291
+ if (text) {
292
+ envelopes.push(index.createEnvelope("user", { t: "text", text }, {
293
+ id: item.id,
294
+ time: startedAt,
295
+ codexItemId: item.id
296
+ }));
297
+ }
298
+ break;
299
+ }
300
+ case "agentMessage": {
301
+ const text = typeof item.text === "string" ? item.text.trim() : "";
302
+ if (text.length > 0) {
303
+ envelopes.push(index.createEnvelope("agent", { t: "text", text }, {
304
+ id: item.id,
305
+ turn: turn.id,
306
+ time: completedAt,
307
+ codexItemId: item.id
308
+ }));
309
+ }
310
+ break;
311
+ }
312
+ case "reasoning": {
313
+ const text = reasoningText(item);
314
+ if (text) {
315
+ envelopes.push(index.createEnvelope("agent", { t: "text", text, thinking: true }, {
316
+ id: item.id,
317
+ turn: turn.id,
318
+ time: startedAt,
319
+ codexItemId: item.id
320
+ }));
321
+ }
322
+ break;
323
+ }
324
+ case "commandExecution": {
325
+ const command = typeof item.command === "string" ? item.command : "";
326
+ emitHistoricalToolCall(
327
+ envelopes,
328
+ turn,
329
+ item,
330
+ "CodexBash",
331
+ commandToTitle(command),
332
+ { command, cwd: item.cwd },
333
+ typeof item.aggregatedOutput === "string" ? item.aggregatedOutput : null
334
+ );
335
+ break;
336
+ }
337
+ case "fileChange": {
338
+ const title = "Apply patch";
339
+ emitHistoricalToolCall(
340
+ envelopes,
341
+ turn,
342
+ item,
343
+ "CodexPatch",
344
+ title,
345
+ { changes: item.changes, status: item.status },
346
+ null
347
+ );
348
+ break;
349
+ }
350
+ case "mcpToolCall": {
351
+ const title = `${item.server}.${item.tool}`;
352
+ const output = item.error !== void 0 && item.error !== null ? String(item.error) : item.result !== void 0 && item.result !== null ? String(item.result) : null;
353
+ emitHistoricalToolCall(
354
+ envelopes,
355
+ turn,
356
+ item,
357
+ "McpTool",
358
+ title,
359
+ {
360
+ server: item.server,
361
+ tool: item.tool,
362
+ arguments: item.arguments
363
+ },
364
+ output
365
+ );
366
+ break;
367
+ }
368
+ }
369
+ }
370
+ envelopes.push(index.createEnvelope("agent", { t: "turn-end", status: turnStatus(turn) }, {
371
+ id: `${turn.id}:end`,
372
+ turn: turn.id,
373
+ time: completedAt
374
+ }));
375
+ }
376
+ return envelopes;
377
+ }
378
+ function patchDescription(changes) {
379
+ if (!changes || typeof changes !== "object") {
380
+ return "Applying patch";
381
+ }
382
+ const fileCount = Object.keys(changes).length;
383
+ if (fileCount === 1) {
384
+ return "Applying patch to 1 file";
385
+ }
386
+ return `Applying patch to ${fileCount} files`;
387
+ }
388
+ function pickTurnEndStatus(message, type) {
389
+ const rawStatus = message.status;
390
+ if (rawStatus === "completed" || rawStatus === "failed" || rawStatus === "cancelled") {
391
+ return rawStatus;
392
+ }
393
+ if (rawStatus === "canceled") {
394
+ return "cancelled";
395
+ }
396
+ if (type === "turn_aborted") {
397
+ const reason = message.reason;
398
+ const error = message.error;
399
+ if (typeof reason === "string" && /(fail|error)/i.test(reason) || typeof error === "string" && error.length > 0 || error !== void 0 && error !== null && typeof error === "object") {
400
+ return "failed";
401
+ }
402
+ return "cancelled";
403
+ }
404
+ if (message.error !== void 0 && message.error !== null) {
405
+ return "failed";
406
+ }
407
+ return "completed";
408
+ }
409
+ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
410
+ const type = message.type;
411
+ const startedSubagents = getStartedSubagents(state);
412
+ const activeSubagents = getActiveSubagents(state);
413
+ const providerSubagentToSessionSubagent = getProviderSubagentToSessionSubagent(state);
414
+ if (type === "collab_agent_item") {
415
+ return {
416
+ currentTurnId: state.currentTurnId,
417
+ startedSubagents,
418
+ activeSubagents,
419
+ providerSubagentToSessionSubagent,
420
+ envelopes: mapCodexCollaborationItem(message.item, buildEnvelopeOptions(state.currentTurnId), "live")
421
+ };
422
+ }
423
+ if (type === "task_started") {
424
+ const turnId = cuid2.createId();
425
+ const turnStart = index.createEnvelope("agent", { t: "turn-start" }, { turn: turnId });
426
+ startedSubagents.clear();
427
+ activeSubagents.clear();
428
+ providerSubagentToSessionSubagent.clear();
429
+ return {
430
+ currentTurnId: turnId,
431
+ startedSubagents,
432
+ activeSubagents,
433
+ providerSubagentToSessionSubagent,
434
+ envelopes: [turnStart]
435
+ };
436
+ }
437
+ if (type === "task_complete" || type === "turn_aborted") {
438
+ if (!state.currentTurnId) {
439
+ return {
440
+ currentTurnId: null,
441
+ startedSubagents,
442
+ activeSubagents,
443
+ providerSubagentToSessionSubagent,
444
+ envelopes: []
445
+ };
446
+ }
447
+ const lifecycleOpts = { turn: state.currentTurnId };
448
+ providerSubagentToSessionSubagent.clear();
449
+ return {
450
+ currentTurnId: null,
451
+ startedSubagents,
452
+ activeSubagents,
453
+ providerSubagentToSessionSubagent,
454
+ envelopes: [
455
+ ...emitSubagentStops(lifecycleOpts, startedSubagents, activeSubagents),
456
+ index.createEnvelope("agent", {
457
+ t: "turn-end",
458
+ status: pickTurnEndStatus(message, type)
459
+ }, lifecycleOpts)
460
+ ]
461
+ };
462
+ }
463
+ if (type === "token_count") {
464
+ return {
465
+ currentTurnId: state.currentTurnId,
466
+ startedSubagents,
467
+ activeSubagents,
468
+ providerSubagentToSessionSubagent,
469
+ envelopes: []
470
+ };
471
+ }
472
+ const subagent = resolveSessionSubagent(message, providerSubagentToSessionSubagent);
473
+ const opts = buildEnvelopeOptions(state.currentTurnId, subagent);
474
+ if (type === "agent_message") {
475
+ if (typeof message.message !== "string") {
476
+ return {
477
+ currentTurnId: state.currentTurnId,
478
+ startedSubagents,
479
+ activeSubagents,
480
+ providerSubagentToSessionSubagent,
481
+ envelopes: []
482
+ };
483
+ }
484
+ const envelopes = [];
485
+ maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
486
+ envelopes.push(index.createEnvelope("agent", { t: "text", text: message.message }, opts));
487
+ return {
488
+ currentTurnId: state.currentTurnId,
489
+ startedSubagents,
490
+ activeSubagents,
491
+ providerSubagentToSessionSubagent,
492
+ envelopes
493
+ };
494
+ }
495
+ if (type === "agent_reasoning" || type === "agent_reasoning_delta") {
496
+ const text = typeof message.text === "string" ? message.text : typeof message.delta === "string" ? message.delta : null;
497
+ if (!text) {
498
+ return {
499
+ currentTurnId: state.currentTurnId,
500
+ startedSubagents,
501
+ activeSubagents,
502
+ providerSubagentToSessionSubagent,
503
+ envelopes: []
504
+ };
505
+ }
506
+ const envelopes = [];
507
+ maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
508
+ envelopes.push(index.createEnvelope("agent", { t: "text", text, thinking: true }, opts));
509
+ return {
510
+ currentTurnId: state.currentTurnId,
511
+ startedSubagents,
512
+ activeSubagents,
513
+ providerSubagentToSessionSubagent,
514
+ envelopes
515
+ };
516
+ }
517
+ if (type === "exec_command_begin") {
518
+ const call = pickCallId(message);
519
+ const { call_id: _callIdSnake, callId: _callIdCamel, type: _type, ...args } = message;
520
+ const command = summarizeCommand(args.command);
521
+ const description = typeof args.description === "string" ? args.description : command ?? "Execute command";
522
+ const envelopes = [];
523
+ maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
524
+ envelopes.push(
525
+ index.createEnvelope("agent", {
526
+ t: "tool-call-start",
527
+ call,
528
+ name: "CodexBash",
529
+ title: commandToTitle(command),
530
+ description,
531
+ args
532
+ }, opts)
533
+ );
534
+ return {
535
+ currentTurnId: state.currentTurnId,
536
+ startedSubagents,
537
+ activeSubagents,
538
+ providerSubagentToSessionSubagent,
539
+ envelopes
540
+ };
541
+ }
542
+ if (type === "exec_command_end") {
543
+ const call = pickCallId(message);
544
+ const envelopes = [];
545
+ maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
546
+ envelopes.push(index.createEnvelope("agent", { t: "tool-call-end", call }, opts));
547
+ return {
548
+ currentTurnId: state.currentTurnId,
549
+ startedSubagents,
550
+ activeSubagents,
551
+ providerSubagentToSessionSubagent,
552
+ envelopes
553
+ };
554
+ }
555
+ if (type === "patch_apply_begin") {
556
+ const call = pickCallId(message);
557
+ const autoApproved = message.auto_approved;
558
+ const changes = message.changes;
559
+ const envelopes = [];
560
+ maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
561
+ envelopes.push(
562
+ index.createEnvelope("agent", {
563
+ t: "tool-call-start",
564
+ call,
565
+ name: "CodexPatch",
566
+ title: "Apply patch",
567
+ description: patchDescription(changes),
568
+ args: {
569
+ auto_approved: autoApproved,
570
+ changes
571
+ }
572
+ }, opts)
573
+ );
574
+ return {
575
+ currentTurnId: state.currentTurnId,
576
+ startedSubagents,
577
+ activeSubagents,
578
+ providerSubagentToSessionSubagent,
579
+ envelopes
580
+ };
581
+ }
582
+ if (type === "patch_apply_end") {
583
+ const call = pickCallId(message);
584
+ const envelopes = [];
585
+ maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
586
+ envelopes.push(index.createEnvelope("agent", { t: "tool-call-end", call }, opts));
587
+ return {
588
+ currentTurnId: state.currentTurnId,
589
+ startedSubagents,
590
+ activeSubagents,
591
+ providerSubagentToSessionSubagent,
592
+ envelopes
593
+ };
594
+ }
595
+ return {
596
+ currentTurnId: state.currentTurnId,
597
+ startedSubagents,
598
+ activeSubagents,
599
+ providerSubagentToSessionSubagent,
600
+ envelopes: []
601
+ };
602
+ }
603
+ function mapCodexProcessorMessageToSessionEnvelopes(message, state) {
604
+ const toolLikeMessage = message;
605
+ const opts = buildEnvelopeOptions(state.currentTurnId);
606
+ if (message.type === "reasoning") {
607
+ return [index.createEnvelope("agent", {
608
+ t: "text",
609
+ text: message.message,
610
+ thinking: true
611
+ }, opts)];
612
+ }
613
+ if (message.type === "tool-call") {
614
+ const title = typeof toolLikeMessage.input?.title === "string" ? toolLikeMessage.input.title : `${toolLikeMessage.name || "Tool"} call`;
615
+ return [index.createEnvelope("agent", {
616
+ t: "tool-call-start",
617
+ call: toolLikeMessage.callId,
618
+ name: toolLikeMessage.name || "unknown",
619
+ title,
620
+ description: title,
621
+ args: toolLikeMessage.input && typeof toolLikeMessage.input === "object" ? toolLikeMessage.input : {}
622
+ }, opts)];
623
+ }
624
+ if (message.type === "tool-call-result") {
625
+ const envelopes = [];
626
+ const content = toolLikeMessage.output?.content;
627
+ if (typeof content === "string" && content.trim().length > 0) {
628
+ envelopes.push(index.createEnvelope("agent", {
629
+ t: "text",
630
+ text: content,
631
+ thinking: true
632
+ }, opts));
633
+ }
634
+ envelopes.push(index.createEnvelope("agent", {
635
+ t: "tool-call-end",
636
+ call: toolLikeMessage.callId
637
+ }, opts));
638
+ return envelopes;
639
+ }
640
+ return [];
641
+ }
642
+
643
+ async function readChildThread(client, childId) {
644
+ if (!client.threadId || typeof childId !== "string" || !childId) throw new Error("Invalid child thread");
645
+ const parentId = client.threadId;
646
+ const { thread: parent } = await client.readThread({ threadId: parentId, includeTurns: true });
647
+ const belongs = parent.id === parentId && parent.turns?.some((turn) => turn.items.some((item) => item.type === "collabAgentToolCall" && Array.isArray(item.receiverThreadIds) && item.receiverThreadIds.includes(childId) || item.type === "subAgentActivity" && item.agentThreadId === childId));
648
+ if (!belongs) throw new Error("Thread is not a child of this session");
649
+ const { thread } = await client.readThread({ threadId: childId, includeTurns: true });
650
+ if (thread.id !== childId) throw new Error("Child thread mismatch");
651
+ return { envelopes: mapCodexThreadToSessionEnvelopes(thread) };
652
+ }
653
+
654
+ class CodexPermissionHandler extends BasePermissionHandler.BasePermissionHandler {
655
+ // Exact tool names that should always be auto-approved. Include the bare
656
+ // form (used by Codex elicitation messages like `tool "change_title"`)
657
+ // and the MCP-qualified form for defense in depth.
658
+ static ALWAYS_AUTO_APPROVE_NAMES = /* @__PURE__ */ new Set([
659
+ "change_title",
660
+ "mcp__happy__change_title"
661
+ ]);
662
+ // Tool-call IDs that should auto-approve when they exactly match one of
663
+ // these values or start with `<name>-` (e.g. `change_title-1765385846663`).
664
+ // Substring matching was a bypass vector — any tool whose ID happened to
665
+ // contain `change_title` as a substring would be silently approved.
666
+ static ALWAYS_AUTO_APPROVE_ID_PREFIXES = [
667
+ "change_title"
668
+ ];
669
+ constructor(session) {
670
+ super(session);
671
+ }
672
+ getLogPrefix() {
673
+ return "[Codex]";
674
+ }
675
+ shouldAutoApprove(toolName, toolCallId) {
676
+ if (CodexPermissionHandler.ALWAYS_AUTO_APPROVE_NAMES.has(toolName)) {
677
+ return true;
678
+ }
679
+ for (const prefix of CodexPermissionHandler.ALWAYS_AUTO_APPROVE_ID_PREFIXES) {
680
+ if (toolCallId === prefix || toolCallId.startsWith(`${prefix}-`)) {
681
+ return true;
682
+ }
683
+ }
684
+ return false;
685
+ }
686
+ /**
687
+ * Handle a tool permission request
688
+ * @param toolCallId - The unique ID of the tool call
689
+ * @param toolName - The name of the tool being called
690
+ * @param input - The input parameters for the tool
691
+ * @returns Promise resolving to permission result
692
+ */
693
+ async handleToolCall(toolCallId, toolName, input) {
694
+ if (this.shouldAutoApprove(toolName, toolCallId)) {
695
+ logger.logger.debug(`${this.getLogPrefix()} Auto-approving tool ${toolName} (${toolCallId})`);
696
+ this.session.updateAgentState((currentState) => ({
697
+ ...currentState,
698
+ completedRequests: {
699
+ ...currentState.completedRequests,
700
+ [toolCallId]: {
701
+ tool: toolName,
702
+ arguments: input,
703
+ createdAt: Date.now(),
704
+ completedAt: Date.now(),
705
+ status: "approved",
706
+ decision: "approved"
707
+ }
708
+ }
709
+ }));
710
+ return { decision: "approved" };
711
+ }
712
+ return new Promise((resolve, reject) => {
713
+ this.pendingRequests.set(toolCallId, {
714
+ resolve,
715
+ reject,
716
+ toolName,
717
+ input
718
+ });
719
+ this.addPendingRequestToState(toolCallId, toolName, input);
720
+ logger.logger.debug(`${this.getLogPrefix()} Permission request sent for tool: ${toolName} (${toolCallId})`);
721
+ });
722
+ }
723
+ }
724
+
725
+ class ReasoningProcessor extends BaseReasoningProcessor.BaseReasoningProcessor {
726
+ getToolName() {
727
+ return "CodexReasoning";
728
+ }
729
+ getLogPrefix() {
730
+ return "[ReasoningProcessor]";
731
+ }
732
+ /**
733
+ * Process a reasoning delta and accumulate content.
734
+ */
735
+ processDelta(delta) {
736
+ this.processInput(delta);
737
+ }
738
+ /**
739
+ * Complete the reasoning section with final text.
740
+ */
741
+ complete(fullText) {
742
+ this.completeReasoning(fullText);
743
+ }
744
+ }
745
+
746
+ class DiffProcessor {
747
+ previousDiff = null;
748
+ onMessage = null;
749
+ constructor(onMessage) {
750
+ this.onMessage = onMessage || null;
751
+ }
752
+ /**
753
+ * Process a turn_diff message and check if the unified_diff has changed
754
+ */
755
+ processDiff(unifiedDiff) {
756
+ if (this.previousDiff !== unifiedDiff) {
757
+ logger.logger.debug("[DiffProcessor] Unified diff changed, sending CodexDiff tool call");
758
+ const callId = node_crypto.randomUUID();
759
+ const toolCall = {
760
+ type: "tool-call",
761
+ name: "CodexDiff",
762
+ callId,
763
+ input: {
764
+ unified_diff: unifiedDiff
765
+ },
766
+ id: node_crypto.randomUUID()
767
+ };
768
+ this.onMessage?.(toolCall);
769
+ const toolResult = {
770
+ type: "tool-call-result",
771
+ callId,
772
+ output: {
773
+ status: "completed"
774
+ },
775
+ id: node_crypto.randomUUID()
776
+ };
777
+ this.onMessage?.(toolResult);
778
+ }
779
+ this.previousDiff = unifiedDiff;
780
+ logger.logger.debug("[DiffProcessor] Updated stored diff");
781
+ }
782
+ /**
783
+ * Reset the processor state (called on task_complete or turn_aborted)
784
+ */
785
+ reset() {
786
+ logger.logger.debug("[DiffProcessor] Resetting diff state");
787
+ this.previousDiff = null;
788
+ }
789
+ /**
790
+ * Set the message callback for sending messages directly
791
+ */
792
+ setMessageCallback(callback) {
793
+ this.onMessage = callback;
794
+ }
795
+ /**
796
+ * Get the current diff value
797
+ */
798
+ getCurrentDiff() {
799
+ return this.previousDiff;
800
+ }
801
+ }
802
+
803
+ const CodexDisplay = ({ messageBuffer, logPath, onExit }) => {
804
+ const [messages, setMessages] = React.useState([]);
805
+ const [confirmationMode, setConfirmationMode] = React.useState(false);
806
+ const [actionInProgress, setActionInProgress] = React.useState(false);
807
+ const confirmationTimeoutRef = React.useRef(null);
808
+ const { stdout } = ink.useStdout();
809
+ const terminalWidth = stdout.columns || 80;
810
+ const terminalHeight = stdout.rows || 24;
811
+ React.useEffect(() => {
812
+ setMessages(messageBuffer.getMessages());
813
+ const unsubscribe = messageBuffer.onUpdate((newMessages) => {
814
+ setMessages(newMessages);
815
+ });
816
+ return () => {
817
+ unsubscribe();
818
+ if (confirmationTimeoutRef.current) {
819
+ clearTimeout(confirmationTimeoutRef.current);
820
+ }
821
+ };
822
+ }, [messageBuffer]);
823
+ const resetConfirmation = React.useCallback(() => {
824
+ setConfirmationMode(false);
825
+ if (confirmationTimeoutRef.current) {
826
+ clearTimeout(confirmationTimeoutRef.current);
827
+ confirmationTimeoutRef.current = null;
828
+ }
829
+ }, []);
830
+ const setConfirmationWithTimeout = React.useCallback(() => {
831
+ setConfirmationMode(true);
832
+ if (confirmationTimeoutRef.current) {
833
+ clearTimeout(confirmationTimeoutRef.current);
834
+ }
835
+ confirmationTimeoutRef.current = setTimeout(() => {
836
+ resetConfirmation();
837
+ }, 15e3);
838
+ }, [resetConfirmation]);
839
+ ink.useInput(React.useCallback(async (input, key) => {
840
+ if (actionInProgress) return;
841
+ if (key.ctrl && input === "c") {
842
+ if (confirmationMode) {
843
+ resetConfirmation();
844
+ setActionInProgress(true);
845
+ await new Promise((resolve) => setTimeout(resolve, 100));
846
+ onExit?.();
847
+ } else {
848
+ setConfirmationWithTimeout();
849
+ }
850
+ return;
851
+ }
852
+ if (confirmationMode) {
853
+ resetConfirmation();
854
+ }
855
+ }, [confirmationMode, actionInProgress, onExit, setConfirmationWithTimeout, resetConfirmation]));
856
+ const getMessageColor = (type) => {
857
+ switch (type) {
858
+ case "user":
859
+ return "magenta";
860
+ case "assistant":
861
+ return "cyan";
862
+ case "system":
863
+ return "blue";
864
+ case "tool":
865
+ return "yellow";
866
+ case "result":
867
+ return "green";
868
+ case "status":
869
+ return "gray";
870
+ default:
871
+ return "white";
872
+ }
873
+ };
874
+ const formatMessage = (msg) => {
875
+ const lines = msg.content.split("\n");
876
+ const maxLineLength = terminalWidth - 10;
877
+ return lines.map((line) => {
878
+ if (line.length <= maxLineLength) return line;
879
+ const chunks = [];
880
+ for (let i = 0; i < line.length; i += maxLineLength) {
881
+ chunks.push(line.slice(i, i + maxLineLength));
882
+ }
883
+ return chunks.join("\n");
884
+ }).join("\n");
885
+ };
886
+ return /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", width: terminalWidth, height: terminalHeight }, /* @__PURE__ */ React.createElement(
887
+ ink.Box,
888
+ {
889
+ flexDirection: "column",
890
+ width: terminalWidth,
891
+ height: terminalHeight - 4,
892
+ borderStyle: "round",
893
+ borderColor: "gray",
894
+ paddingX: 1,
895
+ overflow: "hidden"
896
+ },
897
+ /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", bold: true }, "\u{1F916} Codex Agent Messages"), /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", dimColor: true }, "\u2500".repeat(Math.min(terminalWidth - 4, 60)))),
898
+ /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", height: terminalHeight - 10, overflow: "hidden" }, messages.length === 0 ? /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", dimColor: true }, "Waiting for messages...") : (
899
+ // Show only the last messages that fit in the available space
900
+ messages.slice(-Math.max(1, terminalHeight - 10)).map((msg) => /* @__PURE__ */ React.createElement(ink.Box, { key: msg.id, flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(ink.Text, { color: getMessageColor(msg.type), dimColor: true }, formatMessage(msg))))
901
+ ))
902
+ ), /* @__PURE__ */ React.createElement(
903
+ ink.Box,
904
+ {
905
+ width: terminalWidth,
906
+ borderStyle: "round",
907
+ borderColor: actionInProgress ? "gray" : confirmationMode ? "red" : "green",
908
+ paddingX: 2,
909
+ justifyContent: "center",
910
+ alignItems: "center",
911
+ flexDirection: "column"
912
+ },
913
+ /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", alignItems: "center" }, actionInProgress ? /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", bold: true }, "Exiting agent...") : confirmationMode ? /* @__PURE__ */ React.createElement(ink.Text, { color: "red", bold: true }, "\u26A0\uFE0F Press Ctrl-C again to exit the agent") : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ink.Text, { color: "green", bold: true }, "\u{1F916} Codex Agent Running \u2022 Ctrl-C to exit")), process.env.DEBUG && logPath && /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", dimColor: true }, "Debug logs: ", logPath))
914
+ ));
915
+ };
916
+
917
+ function resolveCodexExecutionPolicy(permissionMode, sandboxManagedByHappy) {
918
+ if (sandboxManagedByHappy) {
919
+ return {
920
+ approvalPolicy: "never",
921
+ sandbox: "danger-full-access"
922
+ };
923
+ }
924
+ const approvalPolicy = (() => {
925
+ switch (permissionMode) {
926
+ // Codex native modes
927
+ case "default":
928
+ return "untrusted";
929
+ // Ask for non-trusted commands
930
+ case "read-only":
931
+ return "never";
932
+ // Never ask, read-only enforced by sandbox
933
+ case "safe-yolo":
934
+ return "on-request";
935
+ // Workspace auto-run; request approval for escalation (0.153 removed on-failure)
936
+ case "yolo":
937
+ return "never";
938
+ // Full YOLO: never interrupt for approvals
939
+ // Defensive fallback for Claude-specific modes (backward compatibility)
940
+ case "bypassPermissions":
941
+ return "never";
942
+ // Full access: map to yolo behavior
943
+ case "acceptEdits":
944
+ return "on-request";
945
+ // Let model decide (closest to auto-approve edits)
946
+ case "plan":
947
+ return "untrusted";
948
+ // Conservative: ask for non-trusted
949
+ default:
950
+ return "untrusted";
951
+ }
952
+ })();
953
+ const sandbox = (() => {
954
+ switch (permissionMode) {
955
+ // Codex native modes
956
+ case "default":
957
+ return "workspace-write";
958
+ // Can write in workspace
959
+ case "read-only":
960
+ return "read-only";
961
+ // Read-only filesystem
962
+ case "safe-yolo":
963
+ return "workspace-write";
964
+ // Can write in workspace
965
+ case "yolo":
966
+ return "danger-full-access";
967
+ // Full system access
968
+ // Defensive fallback for Claude-specific modes
969
+ case "bypassPermissions":
970
+ return "danger-full-access";
971
+ // Full access: map to yolo
972
+ case "acceptEdits":
973
+ return "workspace-write";
974
+ // Can edit files in workspace
975
+ case "plan":
976
+ return "workspace-write";
977
+ // Can write for planning
978
+ default:
979
+ return "workspace-write";
980
+ }
981
+ })();
982
+ return { approvalPolicy, sandbox };
983
+ }
984
+
985
+ function unsupportedEffortReason(catalog, model, effort) {
986
+ if (!effort) return null;
987
+ const selected = catalog.find((entry) => model ? entry.model === model : entry.isDefault);
988
+ if (!selected) return null;
989
+ if (selected.supportedReasoningEfforts.some((option) => option.reasoningEffort === effort)) return null;
990
+ return `Reasoning effort "${effort}" is not supported by ${model ?? "the default model"}. Choose a supported level.`;
991
+ }
992
+
993
+ function readableCodexErrorText(text) {
994
+ const trimmed = text.trim();
995
+ if (!trimmed.startsWith("{")) return trimmed;
996
+ try {
997
+ const body = JSON.parse(trimmed);
998
+ const inner = typeof body.error === "object" && body.error ? body.error.message : void 0;
999
+ const message = typeof inner === "string" && inner.trim() ? inner : typeof body.error === "string" && body.error.trim() ? body.error : typeof body.message === "string" && body.message.trim() ? body.message : null;
1000
+ return message ? message.trim() : trimmed;
1001
+ } catch {
1002
+ return trimmed;
1003
+ }
1004
+ }
1005
+ function describeCodexFailure(msg) {
1006
+ const hasFailure = msg?.status === "failed" || msg?.error !== void 0 && msg?.error !== null;
1007
+ if (!hasFailure) return null;
1008
+ const err = msg.error;
1009
+ if (typeof err === "string" && err.length > 0) return readableCodexErrorText(err);
1010
+ if (err && typeof err === "object" && typeof err.message === "string" && err.message.length > 0) {
1011
+ return readableCodexErrorText(err.message);
1012
+ }
1013
+ return "Unknown error";
1014
+ }
1015
+ const TRANSPORT_LOSS = /^Codex process (exited|disconnected)\b|stdin not writable| timed out after \d+ms/;
1016
+ function describeThrownTurnError(error) {
1017
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
1018
+ if (!message.trim() || TRANSPORT_LOSS.test(message)) return null;
1019
+ return readableCodexErrorText(message);
1020
+ }
1021
+
1022
+ async function resumeExistingThread(opts) {
1023
+ try {
1024
+ const resumedThread = await opts.client.resumeThread({
1025
+ threadId: opts.threadId,
1026
+ cwd: opts.cwd,
1027
+ mcpServers: opts.mcpServers
1028
+ });
1029
+ opts.session.updateMetadata((currentMetadata) => ({
1030
+ ...currentMetadata,
1031
+ codexThreadId: resumedThread.threadId
1032
+ }));
1033
+ opts.messageBuffer.addMessage(`Resumed thread ${trimIdent.trimIdent(resumedThread.threadId)}`, "status");
1034
+ opts.session.sendSessionEvent({
1035
+ type: "message",
1036
+ message: `Resumed Codex thread ${resumedThread.threadId}`
1037
+ });
1038
+ return resumedThread;
1039
+ } catch (error) {
1040
+ const reason = error instanceof Error ? error.message : String(error);
1041
+ throw new Error(`Failed to resume Codex thread ${opts.threadId}: ${reason}`);
1042
+ }
1043
+ }
1044
+
1045
+ const IMPORT_CODEX_THREAD_ENV = "HAPPY_IMPORT_CODEX_THREAD_ID";
1046
+ async function importCodexThread(opts) {
1047
+ let forked;
1048
+ try {
1049
+ forked = await opts.client.forkThread({
1050
+ threadId: opts.threadId,
1051
+ cwd: opts.cwd,
1052
+ mcpServers: opts.mcpServers
1053
+ });
1054
+ } catch (error) {
1055
+ const reason = error instanceof Error ? error.message : String(error);
1056
+ throw new Error(`Failed to import Codex thread ${opts.threadId}: ${reason}`);
1057
+ }
1058
+ if (!forked.threadId || forked.threadId === opts.threadId) {
1059
+ throw new Error(`Failed to import Codex thread ${opts.threadId}: Codex did not create an independent copy`);
1060
+ }
1061
+ opts.session.updateMetadata((currentMetadata) => ({
1062
+ ...currentMetadata,
1063
+ codexThreadId: forked.threadId,
1064
+ importedFromCodexThreadId: opts.threadId
1065
+ }));
1066
+ let thread = forked.thread;
1067
+ if (!Array.isArray(thread?.turns)) {
1068
+ thread = (await opts.client.readThread({ threadId: forked.threadId, includeTurns: true })).thread;
1069
+ }
1070
+ const envelopes = mapCodexThreadToSessionEnvelopes(thread);
1071
+ for (const envelope of envelopes) {
1072
+ opts.session.sendSessionProtocolMessage(envelope);
1073
+ }
1074
+ opts.messageBuffer.addMessage(`Imported thread ${trimIdent.trimIdent(opts.threadId)} as ${trimIdent.trimIdent(forked.threadId)}`, "status");
1075
+ opts.session.sendSessionEvent({
1076
+ type: "message",
1077
+ message: `Imported Codex thread ${opts.threadId} (continuing as ${forked.threadId})`
1078
+ });
1079
+ return { threadId: forked.threadId, model: forked.model, replayed: envelopes.length };
1080
+ }
1081
+
1082
+ function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, notify }) {
1083
+ if (shouldExit) {
1084
+ return false;
1085
+ }
1086
+ if (pending) {
1087
+ return false;
1088
+ }
1089
+ if (queueSize() > 0) {
1090
+ return false;
1091
+ }
1092
+ sendReady();
1093
+ notify?.();
1094
+ return true;
1095
+ }
1096
+
1097
+ const DEFAULT_CODEX_IDLE_RELEASE_MS = 5 * 60 * 1e3;
1098
+ const CODEX_IDLE_RELEASE_ENV = "HAPPY_CODEX_IDLE_RELEASE_MS";
1099
+ function resolveCodexIdleReleaseMs(raw) {
1100
+ if (raw === void 0 || raw.trim() === "") return DEFAULT_CODEX_IDLE_RELEASE_MS;
1101
+ const parsed = Number(raw);
1102
+ if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_CODEX_IDLE_RELEASE_MS;
1103
+ return Math.floor(parsed);
1104
+ }
1105
+ function shouldReleaseIdleCodex(state) {
1106
+ if (state.shouldExit) return false;
1107
+ if (state.turnActive) return false;
1108
+ if (state.abortInProgress) return false;
1109
+ if (state.queueSize > 0) return false;
1110
+ return true;
1111
+ }
1112
+ class CodexIdleReleaseTimer {
1113
+ constructor(opts) {
1114
+ this.opts = opts;
1115
+ }
1116
+ timer = null;
1117
+ releasing = null;
1118
+ get enabled() {
1119
+ return this.opts.delayMs > 0;
1120
+ }
1121
+ get armed() {
1122
+ return this.timer !== null;
1123
+ }
1124
+ arm() {
1125
+ this.cancel();
1126
+ if (!this.enabled) return;
1127
+ const timer = setTimeout(() => {
1128
+ if (this.timer !== timer) return;
1129
+ this.timer = null;
1130
+ void this.fire();
1131
+ }, this.opts.delayMs);
1132
+ timer.unref?.();
1133
+ this.timer = timer;
1134
+ }
1135
+ cancel() {
1136
+ if (this.timer) {
1137
+ clearTimeout(this.timer);
1138
+ this.timer = null;
1139
+ }
1140
+ }
1141
+ /** Resolves once an in-flight release (if any) has finished. Test hook. */
1142
+ async settle() {
1143
+ await this.releasing;
1144
+ }
1145
+ async fire() {
1146
+ if (!this.opts.isIdle()) return;
1147
+ const run = (async () => {
1148
+ try {
1149
+ await this.opts.release();
1150
+ } catch (error) {
1151
+ this.opts.onError?.(error);
1152
+ }
1153
+ })();
1154
+ this.releasing = run;
1155
+ try {
1156
+ await run;
1157
+ } finally {
1158
+ if (this.releasing === run) this.releasing = null;
1159
+ }
1160
+ }
1161
+ }
1162
+
1163
+ function isCodexClearText(text) {
1164
+ return specialCommands.parseSpecialCommand(text).type === "clear";
1165
+ }
1166
+ function enqueueCodexUserText(opts) {
1167
+ if (isCodexClearText(opts.text)) {
1168
+ opts.queue.pushIsolateAndClear(opts.text, opts.mode, opts.attachments, opts.sourceId);
1169
+ return "clear";
1170
+ }
1171
+ opts.queue.push(opts.text, opts.mode, opts.attachments, opts.sourceId);
1172
+ return "queued";
1173
+ }
1174
+
1175
+ function hashCodexEnhancedMode(mode) {
1176
+ return deterministicJson.hashObject({
1177
+ permissionMode: mode.permissionMode,
1178
+ model: mode.model,
1179
+ appendSystemPrompt: mode.appendSystemPrompt,
1180
+ effort: mode.effort
1181
+ });
1182
+ }
1183
+ function buildCodexTurnPrompt(opts) {
1184
+ const parts = [];
1185
+ if (opts.includeAppendSystemPrompt && opts.mode.appendSystemPrompt) {
1186
+ parts.push(opts.mode.appendSystemPrompt);
1187
+ }
1188
+ parts.push(opts.message);
1189
+ if (opts.includeTitleInstruction) {
1190
+ parts.push(constants.CHANGE_TITLE_INSTRUCTION);
1191
+ parts.push(index.BUILTIN_TODO_DISCOVERY);
1192
+ }
1193
+ return parts.join("\n\n");
1194
+ }
1195
+
1196
+ function byteLength(value) {
1197
+ return Buffer.byteLength(value, "utf8");
1198
+ }
1199
+ function safeTypeToken(value) {
1200
+ if (typeof value !== "string") return typeof value;
1201
+ return /^[a-z][a-z0-9_.-]{0,63}$/i.test(value) ? value : "unknown";
1202
+ }
1203
+ function logValueMetadata(value) {
1204
+ return typeof value === "string" ? { valueType: "string", valueBytes: byteLength(value) } : { valueType: value === null ? "null" : typeof value };
1205
+ }
1206
+ function codexEventLogMetadata(value) {
1207
+ const event = value && typeof value === "object" ? value : {};
1208
+ let payloadBytes;
1209
+ try {
1210
+ const encoded = JSON.stringify(value);
1211
+ if (encoded !== void 0) payloadBytes = byteLength(encoded);
1212
+ } catch {
1213
+ }
1214
+ return {
1215
+ eventType: safeTypeToken(event.type),
1216
+ ...payloadBytes === void 0 ? {} : { payloadBytes },
1217
+ hasId: typeof event.id === "string" || typeof event.turn_id === "string" || typeof event.callId === "string"
1218
+ };
1219
+ }
1220
+ function safeCodexErrorMetadata(value) {
1221
+ if (!value || typeof value !== "object") return { errorType: typeof value };
1222
+ const error = value;
1223
+ const status = error.status ?? error.response?.status;
1224
+ const safeCode = typeof error.code === "string" && /^[a-z0-9_.-]{1,64}$/i.test(error.code) ? { code: error.code } : typeof error.code === "number" ? { code: error.code } : typeof error.code === "string" ? { codeBytes: byteLength(error.code) } : {};
1225
+ return {
1226
+ errorType: safeTypeToken(error.name ?? value.constructor?.name),
1227
+ ...safeCode,
1228
+ ...typeof status === "number" ? { status } : {}
1229
+ };
1230
+ }
1231
+
1232
+ const DEFAULT_CODEX_MODEL = "gpt-5.5";
1233
+ const DEFAULT_CODEX_EFFORT = "medium";
1234
+ async function runCodex(opts) {
1235
+ try {
1236
+ node_child_process.execSync("codex --version", { encoding: "utf8", stdio: "pipe", windowsHide: true });
1237
+ } catch {
1238
+ console.error("\n\x1B[1m\x1B[33mCodex CLI is not installed\x1B[0m\n");
1239
+ console.error("Please install Codex CLI using one of these methods:\n");
1240
+ console.error("\x1B[1mOption 1 - npm (recommended):\x1B[0m");
1241
+ console.error(" \x1B[36mnpm install -g @openai/codex\x1B[0m\n");
1242
+ console.error("\x1B[1mOption 2 - Homebrew (macOS):\x1B[0m");
1243
+ console.error(" \x1B[36mbrew install --cask codex\x1B[0m\n");
1244
+ console.error("Alternatively, use Claude Code:");
1245
+ console.error(" \x1B[36mvery-happy claude\x1B[0m\n");
1246
+ process.exit(1);
1247
+ }
1248
+ const sessionTag = node_crypto.randomUUID();
1249
+ api.connectionState.setBackend("Codex");
1250
+ const api$1 = await api.ApiClient.create(opts.credentials);
1251
+ logger.logger.debug(`[codex] Starting with options: startedBy=${opts.startedBy || "terminal"}`);
1252
+ const settings = await persistence.readSettings();
1253
+ let machineId = settings?.machineId;
1254
+ const sandboxConfig = opts.noSandbox ? void 0 : settings?.sandboxConfig;
1255
+ if (!machineId) {
1256
+ console.error(`[START] No machine ID found in settings, which is unexpected since authAndSetupMachineIfNeeded should have created it. Please report this issue on https://github.com/Mereithhh/very-happy/issues`);
1257
+ process.exit(1);
1258
+ }
1259
+ logger.logger.debug(`Using machineId: ${machineId}`);
1260
+ await api$1.getOrCreateMachine({
1261
+ machineId,
1262
+ metadata: machineMetadata.getInitialMachineMetadata()
1263
+ });
1264
+ const initialPermissionMode = opts.permissionMode ?? defaultPermissionMode.DEFAULT_CODEX_PERMISSION_MODE;
1265
+ const forkedFromSessionId = process.env.HAPPY_FORKED_FROM_SESSION_ID;
1266
+ const forkedFromMessageId = process.env.HAPPY_FORKED_FROM_MESSAGE_ID;
1267
+ const { state, metadata } = createSessionMetadata.createSessionMetadata({
1268
+ flavor: "codex",
1269
+ ...process.env.VH_TEAM_OPERATION_ID ? { teamOperationId: process.env.VH_TEAM_OPERATION_ID } : {},
1270
+ machineId,
1271
+ startedBy: opts.startedBy,
1272
+ sandbox: sandboxConfig,
1273
+ dangerouslySkipPermissions: initialPermissionMode === "yolo" || initialPermissionMode === "bypassPermissions",
1274
+ ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
1275
+ ...forkedFromMessageId ? { forkedFromMessageId } : {},
1276
+ capabilities: [index.PROMPT_QUEUE_CAPABILITY]
1277
+ });
1278
+ metadata.attachmentKinds = [...attachmentContent.CLAUDE_ATTACHMENT_KINDS];
1279
+ const importCodexThreadId = process.env[IMPORT_CODEX_THREAD_ENV];
1280
+ if (importCodexThreadId) {
1281
+ metadata.importedFromCodexThreadId = importCodexThreadId;
1282
+ const importTitle = process.env.HAPPY_IMPORT_TITLE;
1283
+ if (importTitle) metadata.summary = { text: importTitle, updatedAt: Date.now() };
1284
+ }
1285
+ const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
1286
+ const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
1287
+ const reconnectVariant = process.env.HAPPY_RECONNECT_ENCRYPTION_VARIANT;
1288
+ const reconnectSeq = process.env.HAPPY_RECONNECT_SEQ;
1289
+ const reconnectMetadataVersion = process.env.HAPPY_RECONNECT_METADATA_VERSION;
1290
+ const reconnectAgentStateVersion = process.env.HAPPY_RECONNECT_AGENT_STATE_VERSION;
1291
+ let response;
1292
+ if (reconnectSessionId && reconnectKeyBase64 && reconnectVariant) {
1293
+ logger.logger.debug(`[START] Reconnecting to existing session ${reconnectSessionId}`);
1294
+ response = {
1295
+ id: reconnectSessionId,
1296
+ seq: parseInt(reconnectSeq || "0", 10),
1297
+ encryptionKey: authRelay.decodeBase64(reconnectKeyBase64),
1298
+ encryptionVariant: reconnectVariant,
1299
+ metadata,
1300
+ metadataVersion: parseInt(reconnectMetadataVersion || "0", 10),
1301
+ agentState: state,
1302
+ agentStateVersion: parseInt(reconnectAgentStateVersion || "0", 10)
1303
+ };
1304
+ } else {
1305
+ response = await api$1.getOrCreateSession({ tag: sessionTag, metadata, state });
1306
+ }
1307
+ if (response) {
1308
+ await sessionLock.claimSessionOrExit(response.id, { takeover: !!reconnectSessionId, flavor: "codex" });
1309
+ }
1310
+ if (reconnectSessionId && response && !await api$1.reactivateSession(response.id)) {
1311
+ throw new Error(`Failed to reactivate archived session ${response.id}`);
1312
+ }
1313
+ let reconnectSeeded = false;
1314
+ if (reconnectSessionId && response) {
1315
+ const snapshot = await api$1.getSession(response.id, response.encryptionKey, response.encryptionVariant);
1316
+ if (snapshot.ok) {
1317
+ response = sessionLock.applyServerSnapshot(response, snapshot.session);
1318
+ reconnectSeeded = true;
1319
+ logger.logger.debug(`[START] Reconnect seeded from server: seq=${snapshot.session.seq} metadataVersion=${snapshot.session.metadataVersion}`);
1320
+ } else {
1321
+ response = sessionLock.withoutServerSnapshot(response);
1322
+ logger.logger.debug(`[START] Reconnect without server snapshot (${snapshot.reason}); skipping existing messages`);
1323
+ }
1324
+ }
1325
+ let session;
1326
+ let permissionHandler;
1327
+ let client;
1328
+ let reasoningProcessor;
1329
+ let abortInProgress = null;
1330
+ let turnActive = false;
1331
+ const { session: initialSession, reconnectionHandle } = setupOfflineReconnection.setupOfflineReconnection({
1332
+ api: api$1,
1333
+ sessionTag,
1334
+ metadata,
1335
+ state,
1336
+ response,
1337
+ sessionClientOptions: reconnectSeeded && response ? { initialSeq: response.seq } : void 0,
1338
+ onSessionSwap: (newSession) => {
1339
+ session = newSession;
1340
+ if (permissionHandler) {
1341
+ permissionHandler.updateSession(newSession);
1342
+ }
1343
+ attachPromptQueueDrain(newSession);
1344
+ }
1345
+ });
1346
+ session = initialSession;
1347
+ if (reconnectSessionId) {
1348
+ session.suppressNextArchiveSignal();
1349
+ if (!reconnectSeeded) session.skipExistingMessages();
1350
+ void session.cancelUndeliveredQueuedInputs();
1351
+ session.updateMetadata((meta) => sessionLock.mergeReconnectMetadata(meta, metadata, Date.now()));
1352
+ }
1353
+ if (response) {
1354
+ try {
1355
+ logger.logger.debug(`[START] Reporting session ${response.id} to daemon`);
1356
+ const result = await controlClient.notifyDaemonSessionStarted(response.id, metadata, {
1357
+ encryptionKey: authRelay.encodeBase64(response.encryptionKey),
1358
+ encryptionVariant: response.encryptionVariant,
1359
+ seq: response.seq,
1360
+ metadataVersion: response.metadataVersion,
1361
+ agentStateVersion: response.agentStateVersion
1362
+ });
1363
+ if (result.error) {
1364
+ logger.logger.debug("[START] Failed to report to daemon (may not be running)", safeCodexErrorMetadata(result.error));
1365
+ } else {
1366
+ logger.logger.debug(`[START] Reported session ${response.id} to daemon`);
1367
+ }
1368
+ } catch (error) {
1369
+ logger.logger.debug("[START] Failed to report to daemon (may not be running)", safeCodexErrorMetadata(error));
1370
+ }
1371
+ }
1372
+ const messageQueue = new registerKillSessionHandler.MessageQueue2(hashCodexEnhancedMode);
1373
+ function attachPromptQueueDrain(client2) {
1374
+ const drain = client2.attachPromptQueueDrain({
1375
+ isIdle: () => messageQueue.size() === 0 && messageQueue.isWaiting()
1376
+ });
1377
+ messageQueue.setOnWait(() => drain.onIdle());
1378
+ }
1379
+ attachPromptQueueDrain(session);
1380
+ messageQueue.setOnDiscard((entries) => {
1381
+ const keys = entries.map((entry) => entry.sourceId).filter((key) => typeof key === "string");
1382
+ if (keys.length > 0) session.sendQueueCancelReason(keys, entries[0].reason);
1383
+ });
1384
+ let currentPermissionMode = initialPermissionMode;
1385
+ let currentModel = DEFAULT_CODEX_MODEL;
1386
+ let currentEffort = DEFAULT_CODEX_EFFORT;
1387
+ let currentAppendSystemPrompt = void 0;
1388
+ const resetCurrentModeDefaults = () => {
1389
+ currentPermissionMode = defaultPermissionMode.DEFAULT_CODEX_PERMISSION_MODE;
1390
+ currentModel = DEFAULT_CODEX_MODEL;
1391
+ currentEffort = DEFAULT_CODEX_EFFORT;
1392
+ currentAppendSystemPrompt = void 0;
1393
+ logger.logger.debug("[Codex] Reset current mode defaults after abort");
1394
+ };
1395
+ const VALID_REMOTE_PERMISSION_MODES = [
1396
+ "default",
1397
+ "read-only",
1398
+ "safe-yolo",
1399
+ "yolo"
1400
+ ];
1401
+ let discoveredModels = [];
1402
+ agentAttachments.registerAgentAttachmentDownloads(session);
1403
+ let userMessageDelivery = Promise.resolve();
1404
+ session.onUserMessage((message) => {
1405
+ const downloads = session.drainAttachmentsForUserMessage();
1406
+ userMessageDelivery = userMessageDelivery.then(async () => {
1407
+ const attachments = await downloads;
1408
+ let messagePermissionMode = currentPermissionMode;
1409
+ if (message.meta?.permissionMode) {
1410
+ const incoming = message.meta.permissionMode;
1411
+ if (VALID_REMOTE_PERMISSION_MODES.includes(incoming)) {
1412
+ messagePermissionMode = incoming;
1413
+ currentPermissionMode = messagePermissionMode;
1414
+ logger.logger.debug("[Codex] Valid permission mode override applied");
1415
+ } else {
1416
+ logger.logger.debug("[Codex] Ignoring invalid permission mode override", logValueMetadata(message.meta.permissionMode));
1417
+ }
1418
+ } else {
1419
+ logger.logger.debug("[Codex] User message received without a permission mode override");
1420
+ }
1421
+ let messageModel = currentModel;
1422
+ if (message.meta?.hasOwnProperty("model")) {
1423
+ messageModel = message.meta.model || void 0;
1424
+ currentModel = messageModel;
1425
+ logger.logger.debug("[Codex] Model override updated", logValueMetadata(message.meta.model));
1426
+ } else {
1427
+ logger.logger.debug("[Codex] User message received without a model override");
1428
+ }
1429
+ let messageEffort = currentEffort;
1430
+ if (message.meta?.hasOwnProperty("effort")) {
1431
+ const incoming = message.meta.effort;
1432
+ if (incoming === null || incoming === void 0) {
1433
+ messageEffort = void 0;
1434
+ currentEffort = void 0;
1435
+ logger.logger.debug(`[Codex] Effort reset to default`);
1436
+ } else if (typeof incoming === "string") {
1437
+ messageEffort = incoming;
1438
+ currentEffort = messageEffort;
1439
+ logger.logger.debug("[Codex] Valid effort override applied");
1440
+ } else {
1441
+ logger.logger.debug("[Codex] Ignoring invalid effort override", logValueMetadata(incoming));
1442
+ }
1443
+ } else {
1444
+ logger.logger.debug("[Codex] User message received without an effort override");
1445
+ }
1446
+ let messageAppendSystemPrompt = currentAppendSystemPrompt;
1447
+ if (message.meta?.hasOwnProperty("appendSystemPrompt")) {
1448
+ messageAppendSystemPrompt = message.meta.appendSystemPrompt || void 0;
1449
+ currentAppendSystemPrompt = messageAppendSystemPrompt;
1450
+ logger.logger.debug("[Codex] Append system prompt override updated", logValueMetadata(message.meta.appendSystemPrompt));
1451
+ } else {
1452
+ logger.logger.debug("[Codex] User message received without an append system prompt override");
1453
+ }
1454
+ const enhancedMode = {
1455
+ permissionMode: messagePermissionMode || "default",
1456
+ model: messageModel,
1457
+ appendSystemPrompt: messageAppendSystemPrompt,
1458
+ effort: messageEffort
1459
+ };
1460
+ const enqueueResult = enqueueCodexUserText({
1461
+ text: message.content.text,
1462
+ mode: enhancedMode,
1463
+ queue: messageQueue,
1464
+ attachments,
1465
+ sourceId: message.localKey
1466
+ });
1467
+ if (enqueueResult === "clear") {
1468
+ logger.logger.debug("[Codex] /clear command pushed to isolated queue");
1469
+ }
1470
+ }).catch((error) => {
1471
+ logger.logger.warn("[Codex] Failed to prepare user attachments", safeCodexErrorMetadata(error));
1472
+ session.sendSessionEvent({ type: "message", message: "Could not prepare this message. Please send it again." });
1473
+ });
1474
+ });
1475
+ let thinking = false;
1476
+ let currentTurnId = null;
1477
+ let codexStartedSubagents = /* @__PURE__ */ new Set();
1478
+ let codexActiveSubagents = /* @__PURE__ */ new Set();
1479
+ let codexProviderSubagentToSessionSubagent = /* @__PURE__ */ new Map();
1480
+ session.keepAlive(thinking, "remote");
1481
+ const keepAliveInterval = setInterval(() => {
1482
+ session.keepAlive(thinking, "remote");
1483
+ }, 2e3);
1484
+ const sendReady = () => {
1485
+ session.sendSessionEvent({ type: "ready" });
1486
+ try {
1487
+ api$1.push().sendSessionNotification({
1488
+ kind: "done",
1489
+ metadata: session.getMetadata(),
1490
+ data: {
1491
+ sessionId: session.sessionId,
1492
+ type: "ready",
1493
+ provider: "codex"
1494
+ }
1495
+ });
1496
+ } catch (pushError) {
1497
+ logger.logger.debug("[Codex] Failed to send ready push", safeCodexErrorMetadata(pushError));
1498
+ }
1499
+ };
1500
+ function logActiveHandles(tag) {
1501
+ if (!process.env.DEBUG) return;
1502
+ const anyProc = process;
1503
+ const handles = typeof anyProc._getActiveHandles === "function" ? anyProc._getActiveHandles() : [];
1504
+ const requests = typeof anyProc._getActiveRequests === "function" ? anyProc._getActiveRequests() : [];
1505
+ logger.logger.debug(`[codex][handles] ${tag}: handles=${handles.length} requests=${requests.length}`);
1506
+ try {
1507
+ const kinds = handles.map((h) => h && h.constructor ? h.constructor.name : typeof h);
1508
+ logger.logger.debug(`[codex][handles] kinds=${JSON.stringify(kinds)}`);
1509
+ } catch {
1510
+ }
1511
+ }
1512
+ let abortController = new AbortController();
1513
+ let shouldExit = false;
1514
+ async function handleAbort() {
1515
+ if (abortInProgress) {
1516
+ await abortInProgress;
1517
+ return;
1518
+ }
1519
+ logger.logger.debug("[Codex] Abort requested - stopping current task");
1520
+ abortInProgress = (async () => {
1521
+ try {
1522
+ if (permissionHandler) {
1523
+ permissionHandler.abortAll();
1524
+ }
1525
+ if (client) {
1526
+ const abortResult = await client.abortTurnWithFallback({
1527
+ gracePeriodMs: 3e3,
1528
+ forceRestartOnTimeout: true
1529
+ });
1530
+ if (abortResult.forcedRestart) {
1531
+ logger.logger.warn("[Codex] Forced app-server restart after interrupt timeout");
1532
+ session.sendSessionEvent({
1533
+ type: "message",
1534
+ message: abortResult.resumedThread ? "Force-stopped active task after interrupt timeout. Codex backend was restarted and the previous thread was resumed." : "Force-stopped active task after interrupt timeout. Codex backend was restarted, but the previous thread could not be resumed."
1535
+ });
1536
+ }
1537
+ }
1538
+ if (reasoningProcessor) {
1539
+ reasoningProcessor.abort();
1540
+ }
1541
+ logger.logger.debug("[Codex] Abort completed - session remains active");
1542
+ } catch (error) {
1543
+ logger.logger.debug("[Codex] Error during abort", safeCodexErrorMetadata(error));
1544
+ } finally {
1545
+ resetCurrentModeDefaults();
1546
+ abortController.abort();
1547
+ abortController = new AbortController();
1548
+ }
1549
+ })();
1550
+ await abortInProgress;
1551
+ abortInProgress = null;
1552
+ }
1553
+ const handleKillSession = async () => {
1554
+ logger.logger.debug("[Codex] Kill session requested - terminating process");
1555
+ await handleAbort();
1556
+ logger.logger.debug("[Codex] Abort completed, proceeding with termination");
1557
+ try {
1558
+ if (session) {
1559
+ session.updateMetadata((currentMetadata) => ({
1560
+ ...currentMetadata,
1561
+ lifecycleState: "archived",
1562
+ lifecycleStateSince: Date.now(),
1563
+ archivedBy: "cli",
1564
+ archiveReason: "User terminated"
1565
+ }));
1566
+ session.sendSessionDeath();
1567
+ await session.flush();
1568
+ await session.close();
1569
+ }
1570
+ try {
1571
+ await client.disconnect();
1572
+ } catch (e) {
1573
+ logger.logger.debug("[Codex] Error disconnecting Codex during termination", safeCodexErrorMetadata(e));
1574
+ }
1575
+ happyServer.stop();
1576
+ logger.logger.debug("[Codex] Session termination complete, exiting");
1577
+ process.exit(0);
1578
+ } catch (error) {
1579
+ logger.logger.debug("[Codex] Error during session termination", safeCodexErrorMetadata(error));
1580
+ process.exit(1);
1581
+ }
1582
+ };
1583
+ session.rpcHandlerManager.registerHandler("codex-child-read", async (args) => {
1584
+ try {
1585
+ return await readChildThread(client, args?.threadId);
1586
+ } catch (error) {
1587
+ return { error: error instanceof Error ? error.message : "Child read failed" };
1588
+ }
1589
+ });
1590
+ session.rpcHandlerManager.registerHandler("abort", handleAbort);
1591
+ const disposeTermination = registerKillSessionHandler.registerKillSessionHandler(session.rpcHandlerManager, handleKillSession, session, { processSignals: true });
1592
+ const messageBuffer$1 = new messageBuffer.MessageBuffer();
1593
+ const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
1594
+ let inkInstance = null;
1595
+ if (hasTTY) {
1596
+ console.clear();
1597
+ inkInstance = ink.render(React.createElement(CodexDisplay, {
1598
+ messageBuffer: messageBuffer$1,
1599
+ logPath: process.env.DEBUG ? logger.logger.getLogPath() : void 0,
1600
+ onExit: async () => {
1601
+ logger.logger.debug("[codex]: Exiting agent via Ctrl-C");
1602
+ shouldExit = true;
1603
+ await handleAbort();
1604
+ }
1605
+ }), {
1606
+ exitOnCtrlC: false,
1607
+ patchConsole: false
1608
+ });
1609
+ }
1610
+ if (hasTTY) {
1611
+ process.stdin.resume();
1612
+ if (process.stdin.isTTY) {
1613
+ process.stdin.setRawMode(true);
1614
+ }
1615
+ process.stdin.setEncoding("utf8");
1616
+ }
1617
+ client = new codexAppServerClient.CodexAppServerClient(sandboxConfig);
1618
+ const idleRelease = new CodexIdleReleaseTimer({
1619
+ delayMs: resolveCodexIdleReleaseMs(process.env[CODEX_IDLE_RELEASE_ENV]),
1620
+ isIdle: () => shouldReleaseIdleCodex({
1621
+ turnActive,
1622
+ queueSize: messageQueue.size(),
1623
+ shouldExit,
1624
+ abortInProgress: abortInProgress !== null
1625
+ }),
1626
+ release: async () => {
1627
+ const released = await client.releaseIdleProcess();
1628
+ if (released) {
1629
+ logger.logger.debug("[Codex] Released idle app-server; thread kept for resume on next message");
1630
+ }
1631
+ },
1632
+ onError: (error) => logger.logger.debug("[Codex] Idle app-server release failed", safeCodexErrorMetadata(error))
1633
+ });
1634
+ permissionHandler = new CodexPermissionHandler(session);
1635
+ permissionHandler.reset("Previous CLI process exited before responding");
1636
+ reasoningProcessor = new ReasoningProcessor((message) => {
1637
+ const envelopes = mapCodexProcessorMessageToSessionEnvelopes(message, { currentTurnId });
1638
+ for (const envelope of envelopes) {
1639
+ session.sendSessionProtocolMessage(envelope);
1640
+ }
1641
+ });
1642
+ const diffProcessor = new DiffProcessor((message) => {
1643
+ const envelopes = mapCodexProcessorMessageToSessionEnvelopes(message, { currentTurnId });
1644
+ for (const envelope of envelopes) {
1645
+ session.sendSessionProtocolMessage(envelope);
1646
+ }
1647
+ });
1648
+ client.setApprovalHandler(async (params) => {
1649
+ const toolName = params.type === "exec" ? "CodexBash" : params.type === "patch" ? "CodexPatch" : params.toolName ?? "McpTool";
1650
+ const input = params.type === "exec" ? { command: params.command, cwd: params.cwd } : params.type === "patch" ? { changes: params.fileChanges } : params.input ?? {};
1651
+ try {
1652
+ const result = await permissionHandler.handleToolCall(params.callId, toolName, input);
1653
+ logger.logger.debug("[Codex] Permission request resolved");
1654
+ return result.decision;
1655
+ } catch (error) {
1656
+ logger.logger.debug("[Codex] Error handling permission", safeCodexErrorMetadata(error));
1657
+ return "denied";
1658
+ }
1659
+ });
1660
+ const editThrottle = new editPaths.EditReportThrottle();
1661
+ client.setEventHandler((msg) => {
1662
+ if (msg.type === "token_count") {
1663
+ session.sendAgentUsageSnapshot("codex", msg);
1664
+ }
1665
+ logger.logger.debug("[Codex] Event metadata", codexEventLogMetadata(msg));
1666
+ if (msg.type === "agent_message") {
1667
+ messageBuffer$1.addMessage(msg.message, "assistant");
1668
+ } else if (msg.type === "agent_reasoning_delta") ; else if (msg.type === "agent_reasoning") {
1669
+ messageBuffer$1.addMessage(`[Thinking] ${msg.text.substring(0, 100)}...`, "system");
1670
+ } else if (msg.type === "exec_command_begin") {
1671
+ messageBuffer$1.addMessage(`Executing: ${msg.command}`, "tool");
1672
+ } else if (msg.type === "exec_command_end") {
1673
+ const output = msg.output || msg.error || "Command completed";
1674
+ const truncatedOutput = output.substring(0, 200);
1675
+ messageBuffer$1.addMessage(
1676
+ `Result: ${truncatedOutput}${output.length > 200 ? "..." : ""}`,
1677
+ "result"
1678
+ );
1679
+ } else if (msg.type === "task_started") {
1680
+ messageBuffer$1.addMessage("Starting task...", "status");
1681
+ } else if (msg.type === "task_complete") {
1682
+ const failure = describeCodexFailure(msg);
1683
+ if (failure) {
1684
+ messageBuffer$1.addMessage(`Task failed: ${failure}`, "status");
1685
+ session.sendSessionEvent({ type: "message", message: `Codex error: ${failure}` });
1686
+ } else {
1687
+ messageBuffer$1.addMessage("Task completed", "status");
1688
+ }
1689
+ } else if (msg.type === "turn_aborted") {
1690
+ const failure = describeCodexFailure(msg);
1691
+ if (failure) {
1692
+ messageBuffer$1.addMessage(`Turn aborted: ${failure}`, "status");
1693
+ session.sendSessionEvent({ type: "message", message: `Codex error: ${failure}` });
1694
+ } else {
1695
+ messageBuffer$1.addMessage("Turn aborted", "status");
1696
+ }
1697
+ }
1698
+ if (msg.type === "task_started") {
1699
+ if (!thinking) {
1700
+ logger.logger.debug("thinking started");
1701
+ thinking = true;
1702
+ session.keepAlive(thinking, "remote");
1703
+ }
1704
+ }
1705
+ if (msg.type === "task_complete" || msg.type === "turn_aborted") {
1706
+ if (thinking) {
1707
+ logger.logger.debug("thinking completed");
1708
+ thinking = false;
1709
+ session.keepAlive(thinking, "remote");
1710
+ }
1711
+ diffProcessor.reset();
1712
+ }
1713
+ if (msg.type === "agent_reasoning_section_break") {
1714
+ reasoningProcessor.handleSectionBreak();
1715
+ }
1716
+ if (msg.type === "agent_reasoning_delta") {
1717
+ reasoningProcessor.processDelta(msg.delta);
1718
+ }
1719
+ if (msg.type === "agent_reasoning") {
1720
+ reasoningProcessor.complete(msg.text);
1721
+ }
1722
+ if (msg.type === "patch_apply_begin") {
1723
+ const { changes } = msg;
1724
+ for (const edit of editThrottle.take(editPaths.extractCodexPatchPaths(changes))) {
1725
+ controlClient.reportSessionEditToDaemon({ sessionId: session.sessionId, path: edit.path, tool: edit.tool, cwd: process.cwd() });
1726
+ }
1727
+ const changeCount = Object.keys(changes).length;
1728
+ const filesMsg = changeCount === 1 ? "1 file" : `${changeCount} files`;
1729
+ messageBuffer$1.addMessage(`Modifying ${filesMsg}...`, "tool");
1730
+ }
1731
+ if (msg.type === "patch_apply_end") {
1732
+ const { stdout, stderr, success } = msg;
1733
+ if (success) {
1734
+ const message = stdout || "Files modified successfully";
1735
+ messageBuffer$1.addMessage(message.substring(0, 200), "result");
1736
+ } else {
1737
+ const errorMsg = stderr || "Failed to modify files";
1738
+ messageBuffer$1.addMessage(`Error: ${errorMsg.substring(0, 200)}`, "result");
1739
+ }
1740
+ }
1741
+ if (msg.type === "turn_diff") {
1742
+ if (msg.unified_diff) {
1743
+ diffProcessor.processDiff(msg.unified_diff);
1744
+ }
1745
+ }
1746
+ if (msg.type !== "agent_reasoning_delta" && msg.type !== "agent_reasoning" && msg.type !== "agent_reasoning_section_break" && msg.type !== "turn_diff") {
1747
+ const mapped = mapCodexMcpMessageToSessionEnvelopes(msg, {
1748
+ currentTurnId,
1749
+ startedSubagents: codexStartedSubagents,
1750
+ activeSubagents: codexActiveSubagents,
1751
+ providerSubagentToSessionSubagent: codexProviderSubagentToSessionSubagent
1752
+ });
1753
+ currentTurnId = mapped.currentTurnId;
1754
+ codexStartedSubagents = mapped.startedSubagents;
1755
+ codexActiveSubagents = mapped.activeSubagents;
1756
+ codexProviderSubagentToSessionSubagent = mapped.providerSubagentToSessionSubagent;
1757
+ for (const envelope of mapped.envelopes) {
1758
+ session.sendSessionProtocolMessage(envelope);
1759
+ }
1760
+ }
1761
+ });
1762
+ const happyServer = await deterministicJson.startHappyServer(session);
1763
+ const bridgeEntrypoint = path.join(projectPath.projectPath(), "bin", "very-happy-mcp.mjs");
1764
+ const mcpServers = {
1765
+ happy: {
1766
+ command: process.execPath,
1767
+ args: ["--no-warnings", "--no-deprecation", bridgeEntrypoint, "--url", happyServer.url]
1768
+ }
1769
+ };
1770
+ let first = true;
1771
+ let appendSystemPromptInjected = false;
1772
+ process.env.VH_PEER_SESSION_ID = session.sessionId;
1773
+ try {
1774
+ logger.logger.debug("[codex]: client.connect begin");
1775
+ await client.connect();
1776
+ logger.logger.debug("[codex]: client.connect done");
1777
+ try {
1778
+ discoveredModels = await client.listModels();
1779
+ if (discoveredModels.length > 0) {
1780
+ session.updateMetadata((metadata2) => ({
1781
+ ...metadata2,
1782
+ models: discoveredModels.map((model) => ({
1783
+ code: model.model,
1784
+ value: model.displayName,
1785
+ description: model.description,
1786
+ reasoningEfforts: model.supportedReasoningEfforts.map((option) => option.reasoningEffort),
1787
+ defaultReasoningEffort: model.defaultReasoningEffort
1788
+ })),
1789
+ defaultModelCode: discoveredModels.find((model) => model.isDefault)?.model
1790
+ }));
1791
+ }
1792
+ } catch (error) {
1793
+ logger.logger.debug("[Codex] Model discovery unavailable; using compatibility fallback", safeCodexErrorMetadata(error));
1794
+ }
1795
+ if (opts.resumeThreadId) {
1796
+ await resumeExistingThread({
1797
+ client,
1798
+ session,
1799
+ messageBuffer: messageBuffer$1,
1800
+ threadId: opts.resumeThreadId,
1801
+ cwd: process.cwd(),
1802
+ mcpServers
1803
+ });
1804
+ first = false;
1805
+ appendSystemPromptInjected = true;
1806
+ }
1807
+ if (!reconnectSessionId && !opts.resumeThreadId && importCodexThreadId) {
1808
+ await importCodexThread({
1809
+ client,
1810
+ session,
1811
+ messageBuffer: messageBuffer$1,
1812
+ threadId: importCodexThreadId,
1813
+ cwd: process.cwd(),
1814
+ mcpServers
1815
+ });
1816
+ first = false;
1817
+ appendSystemPromptInjected = true;
1818
+ }
1819
+ const forkCodexThreadId = process.env.HAPPY_FORK_CODEX_THREAD_ID;
1820
+ if (!reconnectSessionId && forkCodexThreadId) {
1821
+ try {
1822
+ const { thread } = await client.readThread({
1823
+ threadId: forkCodexThreadId,
1824
+ includeTurns: true
1825
+ });
1826
+ const envelopes = mapCodexThreadToSessionEnvelopes(thread);
1827
+ for (const envelope of envelopes) {
1828
+ session.sendSessionProtocolMessage(envelope);
1829
+ }
1830
+ session.updateMetadata((currentMetadata) => ({
1831
+ ...currentMetadata,
1832
+ codexThreadId: forkCodexThreadId
1833
+ }));
1834
+ logger.logger.debug(`[CODEX FORK BACKFILL] Replayed ${envelopes.length} historical envelopes from thread ${forkCodexThreadId}`);
1835
+ } catch (error) {
1836
+ logger.logger.debug(`[CODEX FORK BACKFILL] Failed to read thread ${forkCodexThreadId}`, safeCodexErrorMetadata(error));
1837
+ }
1838
+ }
1839
+ let pending = null;
1840
+ idleRelease.arm();
1841
+ while (!shouldExit) {
1842
+ logActiveHandles("loop-top");
1843
+ let message = pending;
1844
+ pending = null;
1845
+ if (!message) {
1846
+ const waitSignal = abortController.signal;
1847
+ const batch = await messageQueue.waitForMessagesAndGetAsString(waitSignal);
1848
+ if (!batch) {
1849
+ if (waitSignal.aborted && !shouldExit) {
1850
+ logger.logger.debug("[codex]: Wait aborted while idle; ignoring and continuing");
1851
+ continue;
1852
+ }
1853
+ logger.logger.debug(`[codex]: batch=${!!batch}, shouldExit=${shouldExit}`);
1854
+ break;
1855
+ }
1856
+ message = batch;
1857
+ }
1858
+ if (!message) {
1859
+ break;
1860
+ }
1861
+ idleRelease.cancel();
1862
+ turnActive = true;
1863
+ if (isCodexClearText(message.message)) {
1864
+ logger.logger.debug("[Codex] Handling /clear command - resetting Codex thread state");
1865
+ client.clearThreadState();
1866
+ currentTurnId = null;
1867
+ codexStartedSubagents = /* @__PURE__ */ new Set();
1868
+ codexActiveSubagents = /* @__PURE__ */ new Set();
1869
+ codexProviderSubagentToSessionSubagent = /* @__PURE__ */ new Map();
1870
+ permissionHandler.reset();
1871
+ reasoningProcessor.abort();
1872
+ diffProcessor.reset();
1873
+ appendSystemPromptInjected = false;
1874
+ thinking = false;
1875
+ session.keepAlive(thinking, "remote");
1876
+ messageBuffer$1.addMessage("Context was reset", "status");
1877
+ session.sendSessionEvent({ type: "message", message: "Context was reset" });
1878
+ session.updateMetadata((currentMetadata) => {
1879
+ const nextMetadata = { ...currentMetadata };
1880
+ delete nextMetadata.codexThreadId;
1881
+ return nextMetadata;
1882
+ });
1883
+ emitReadyIfIdle({
1884
+ pending,
1885
+ // B-509: server-queued prompts count as pending input (no ready/push per item).
1886
+ queueSize: () => messageQueue.size() + (session.promptQueueHasPending() ? 1 : 0),
1887
+ shouldExit,
1888
+ sendReady
1889
+ });
1890
+ turnActive = false;
1891
+ idleRelease.arm();
1892
+ continue;
1893
+ }
1894
+ messageBuffer$1.addMessage(message.message, "user");
1895
+ try {
1896
+ await client.ensureConnected();
1897
+ const sandboxManagedByHappy = client.sandboxEnabled;
1898
+ const executionPolicy = resolveCodexExecutionPolicy(
1899
+ message.mode.permissionMode,
1900
+ sandboxManagedByHappy
1901
+ );
1902
+ const effortRefusal = unsupportedEffortReason(discoveredModels, message.mode.model, message.mode.effort);
1903
+ if (effortRefusal) {
1904
+ throw new Error(effortRefusal);
1905
+ }
1906
+ if (!client.hasActiveThread()) {
1907
+ const startedThread = await client.startThread({
1908
+ model: message.mode.model,
1909
+ cwd: process.cwd(),
1910
+ approvalPolicy: executionPolicy.approvalPolicy,
1911
+ sandbox: executionPolicy.sandbox,
1912
+ mcpServers
1913
+ });
1914
+ session.updateMetadata((currentMetadata) => ({
1915
+ ...currentMetadata,
1916
+ codexThreadId: startedThread.threadId
1917
+ }));
1918
+ }
1919
+ const includeAppendSystemPrompt = Boolean(
1920
+ message.mode.appendSystemPrompt && !appendSystemPromptInjected
1921
+ );
1922
+ const turnPrompt = buildCodexTurnPrompt({
1923
+ message: message.message,
1924
+ mode: message.mode,
1925
+ includeAppendSystemPrompt,
1926
+ includeTitleInstruction: first
1927
+ });
1928
+ const staged = message.attachments?.length ? await attachmentContent.stageClaudeAttachments(message.attachments, {
1929
+ happyHomeDir: configuration.configuration.happyHomeDir,
1930
+ sessionId: session.sessionId
1931
+ }) : [];
1932
+ const result = await client.sendTurnAndWait(attachmentContent.appendStagedAttachmentsToPrompt(turnPrompt, staged), {
1933
+ images: staged.filter((file) => ["image/jpeg", "image/png", "image/gif", "image/webp"].includes(file.mimeType)).map((file) => file.path),
1934
+ model: message.mode.model,
1935
+ approvalPolicy: executionPolicy.approvalPolicy,
1936
+ sandbox: executionPolicy.sandbox,
1937
+ effort: message.mode.effort
1938
+ });
1939
+ first = false;
1940
+ if (includeAppendSystemPrompt) {
1941
+ appendSystemPromptInjected = true;
1942
+ }
1943
+ if (result.aborted) {
1944
+ logger.logger.debug("[Codex] Turn aborted");
1945
+ }
1946
+ } catch (error) {
1947
+ logger.logger.warn("Error in codex session", safeCodexErrorMetadata(error));
1948
+ const reason = describeThrownTurnError(error);
1949
+ if (reason) {
1950
+ messageBuffer$1.addMessage(`Task failed: ${reason}`, "status");
1951
+ session.sendSessionEvent({ type: "message", message: `Codex error: ${reason}` });
1952
+ } else {
1953
+ messageBuffer$1.addMessage("Process exited unexpectedly", "status");
1954
+ session.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" });
1955
+ }
1956
+ } finally {
1957
+ permissionHandler.reset();
1958
+ reasoningProcessor.abort();
1959
+ diffProcessor.reset();
1960
+ thinking = false;
1961
+ session.keepAlive(thinking, "remote");
1962
+ emitReadyIfIdle({
1963
+ pending,
1964
+ // B-509: server-queued prompts count as pending input (no ready/push per item).
1965
+ queueSize: () => messageQueue.size() + (session.promptQueueHasPending() ? 1 : 0),
1966
+ shouldExit,
1967
+ sendReady
1968
+ });
1969
+ turnActive = false;
1970
+ idleRelease.arm();
1971
+ logActiveHandles("after-turn");
1972
+ }
1973
+ }
1974
+ } finally {
1975
+ disposeTermination?.();
1976
+ session.closePromptQueueDrain();
1977
+ logger.logger.debug("[codex]: Final cleanup start");
1978
+ logActiveHandles("cleanup-start");
1979
+ if (reconnectionHandle) {
1980
+ logger.logger.debug("[codex]: Cancelling offline reconnection");
1981
+ reconnectionHandle.cancel();
1982
+ }
1983
+ try {
1984
+ logger.logger.debug("[codex]: sendSessionDeath");
1985
+ session.sendSessionDeath();
1986
+ logger.logger.debug("[codex]: flush begin");
1987
+ await session.flush();
1988
+ logger.logger.debug("[codex]: flush done");
1989
+ logger.logger.debug("[codex]: session.close begin");
1990
+ await session.close();
1991
+ logger.logger.debug("[codex]: session.close done");
1992
+ } catch (e) {
1993
+ logger.logger.debug("[codex]: Error while closing session", safeCodexErrorMetadata(e));
1994
+ }
1995
+ idleRelease.cancel();
1996
+ logger.logger.debug("[codex]: client.disconnect begin");
1997
+ await client.disconnect();
1998
+ logger.logger.debug("[codex]: client.disconnect done");
1999
+ logger.logger.debug("[codex]: happyServer.stop");
2000
+ happyServer.stop();
2001
+ if (process.stdin.isTTY) {
2002
+ logger.logger.debug("[codex]: setRawMode(false)");
2003
+ try {
2004
+ process.stdin.setRawMode(false);
2005
+ } catch {
2006
+ }
2007
+ }
2008
+ if (hasTTY) {
2009
+ logger.logger.debug("[codex]: stdin.pause()");
2010
+ try {
2011
+ process.stdin.pause();
2012
+ } catch {
2013
+ }
2014
+ }
2015
+ logger.logger.debug("[codex]: clearInterval(keepAlive)");
2016
+ clearInterval(keepAliveInterval);
2017
+ if (inkInstance) {
2018
+ logger.logger.debug("[codex]: inkInstance.unmount()");
2019
+ inkInstance.unmount();
2020
+ }
2021
+ messageBuffer$1.clear();
2022
+ logActiveHandles("cleanup-end");
2023
+ logger.logger.debug("[codex]: Final cleanup completed");
2024
+ }
2025
+ }
2026
+
2027
+ function extractCodexResumeFlag(args) {
2028
+ const remainingArgs = [];
2029
+ let resumeThreadId = null;
2030
+ for (let i = 0; i < args.length; i++) {
2031
+ const arg = args[i];
2032
+ if (arg === "--resume" || arg === "-r") {
2033
+ if (resumeThreadId !== null) {
2034
+ throw new Error("Codex resume flag can only be provided once.");
2035
+ }
2036
+ const nextArg = args[i + 1];
2037
+ if (!nextArg || nextArg.startsWith("-")) {
2038
+ throw new Error("Codex resume requires a thread ID: very-happy codex --resume <thread-id>");
2039
+ }
2040
+ resumeThreadId = nextArg;
2041
+ i++;
2042
+ continue;
2043
+ }
2044
+ if (arg.startsWith("--resume=")) {
2045
+ if (resumeThreadId !== null) {
2046
+ throw new Error("Codex resume flag can only be provided once.");
2047
+ }
2048
+ const value = arg.slice("--resume=".length).trim();
2049
+ if (!value) {
2050
+ throw new Error("Codex resume requires a thread ID: very-happy codex --resume <thread-id>");
2051
+ }
2052
+ resumeThreadId = value;
2053
+ continue;
2054
+ }
2055
+ remainingArgs.push(arg);
2056
+ }
2057
+ return {
2058
+ resumeThreadId,
2059
+ args: remainingArgs
2060
+ };
2061
+ }
2062
+
2063
+ async function handleCodexCommand(args) {
2064
+ let startedBy = void 0;
2065
+ let permissionMode = void 0;
2066
+ const sandboxArgs = ensureDaemonRunning.extractNoSandboxFlag(args);
2067
+ const codexArgs = extractCodexResumeFlag(sandboxArgs.args);
2068
+ for (let i = 0; i < codexArgs.args.length; i++) {
2069
+ if (codexArgs.args[i] === "--started-by") {
2070
+ startedBy = codexArgs.args[++i];
2071
+ } else if (codexArgs.args[i] === "--permission-mode") {
2072
+ permissionMode = codexArgs.args[++i];
2073
+ } else if (codexArgs.args[i] === "--yolo") {
2074
+ permissionMode = "yolo";
2075
+ }
2076
+ }
2077
+ const { credentials } = await auth.authAndSetupMachineIfNeeded();
2078
+ await ensureDaemonRunning.ensureDaemonRunning();
2079
+ await runCodex({
2080
+ credentials,
2081
+ startedBy,
2082
+ noSandbox: sandboxArgs.noSandbox,
2083
+ resumeThreadId: codexArgs.resumeThreadId ?? void 0,
2084
+ permissionMode
2085
+ });
2086
+ }
2087
+
2088
+ exports.handleCodexCommand = handleCodexCommand;