very-happy-cli 0.2.173 → 0.2.175
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.
- package/dist/{AcpBackend-DG5AHZXF.mjs → AcpBackend-BZrLVcHb.mjs} +3 -3
- package/dist/{AcpBackend-ByLLiXvl.cjs → AcpBackend-Sb6N_HcB.cjs} +3 -3
- package/dist/{AcpSessionManager-Zf00QnlL.cjs → AcpSessionManager-C2MqOirs.cjs} +1 -1
- package/dist/{AcpSessionManager-B7FIrsys.mjs → AcpSessionManager-y1Iy1mzc.mjs} +1 -1
- package/dist/{BasePermissionHandler-kD4FK-7K.cjs → BasePermissionHandler-BbLYwd13.cjs} +1 -1
- package/dist/{BasePermissionHandler-CgPa--v2.mjs → BasePermissionHandler-DriZLITp.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-Cnmvd83F.mjs → BaseReasoningProcessor-DnykPlPo.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-CeMRo-8g.cjs → BaseReasoningProcessor-_S1PbSvH.cjs} +1 -1
- package/dist/{agentHome-DVLed_WJ.cjs → agentHome-BoYfpemd.cjs} +4 -4
- package/dist/{agentHome-b9H3fCBZ.mjs → agentHome-BtuRubHG.mjs} +4 -4
- package/dist/{api-DDz_YyoH.mjs → api-D08IEaWa.mjs} +10 -10
- package/dist/{api-BBoamFqd.cjs → api-KZmVqSKO.cjs} +10 -10
- package/dist/{apiMachine-DqQ8WeIe.mjs → apiMachine-Cx9Zn-78.mjs} +14 -14
- package/dist/{apiMachine-DRxPV0j2.cjs → apiMachine-Dct2GDAq.cjs} +14 -14
- package/dist/{attachmentContent-CmR86NxQ.cjs → attachmentContent-4L9dO8E3.cjs} +2 -2
- package/dist/{attachmentContent-DNsACM9b.mjs → attachmentContent-PrNJg8gG.mjs} +2 -2
- package/dist/{attachmentLimits-CxG3T18E.mjs → attachmentLimits-BLbji11b.mjs} +1 -1
- package/dist/{attachmentLimits-BEYEEBm8.cjs → attachmentLimits-D6bT2jU1.cjs} +1 -1
- package/dist/{auth-3UXAs__6.cjs → auth-BGmM3Vlm.cjs} +5 -5
- package/dist/{auth-BF8QvXR1.cjs → auth-BI0CsMcy.cjs} +8 -8
- package/dist/{auth-DvB0u-4H.mjs → auth-D1qHU-i_.mjs} +5 -5
- package/dist/{auth-BVqHWH_r.mjs → auth-PY_HGlzz.mjs} +8 -8
- package/dist/{auto-D0Ai-s17.mjs → auto-COMphIfD.mjs} +15 -15
- package/dist/{auto-D3PSMTni.cjs → auto-DM4_FeKb.cjs} +15 -15
- package/dist/{bootstrap-Cg_t3W-0.mjs → bootstrap-CWjpC5-J.mjs} +2 -2
- package/dist/{bootstrap-BsXIVhrG.cjs → bootstrap-DTJ6-vYT.cjs} +2 -2
- package/dist/{browser-Cbyo0qny.cjs → browser-DmgVoopB.cjs} +1 -1
- package/dist/{browser-f6xCPkkN.mjs → browser-xuW4fiHo.mjs} +1 -1
- package/dist/{claudeLocal-DqJUowRE.mjs → claudeLocal-B0P-wVJJ.mjs} +5 -5
- package/dist/{claudeLocal-AByQMi4D.cjs → claudeLocal-CtZVz3ee.cjs} +5 -5
- package/dist/{claudeLocalLauncher-BFxrneBS.mjs → claudeLocalLauncher-D4vmjI3c.mjs} +10 -10
- package/dist/{claudeLocalLauncher-CSnWv8cG.cjs → claudeLocalLauncher-Dnv4CH8r.cjs} +10 -10
- package/dist/{claudeSessionFork-DsmA1Jv6.mjs → claudeSessionFork-CxjOBoBh.mjs} +1 -1
- package/dist/{claudeSessionFork-DEuvbqD3.cjs → claudeSessionFork-DQk5-dzR.cjs} +1 -1
- package/dist/{client-CuadUoga.cjs → client-BHZVyQwi.cjs} +3 -3
- package/dist/{client-W3gPBBN2.cjs → client-BhLhjj_x.cjs} +2 -2
- package/dist/{client-CzNWPOBI.mjs → client-C4ddTzrD.mjs} +2 -2
- package/dist/{client-mnqGeUey.mjs → client-eQjOvC55.mjs} +3 -3
- package/dist/codex/happyMcpStdioBridge.cjs +15 -15
- package/dist/codex/happyMcpStdioBridge.mjs +15 -15
- package/dist/{codexAppServerClient-BCAPEmbn.mjs → codexAppServerClient-CppPl_R6.mjs} +205 -28
- package/dist/{codexAppServerClient-BgNcgkVT.cjs → codexAppServerClient-D-9z-lWP.cjs} +205 -28
- package/dist/{codexCommand-B-xQ7uoD.cjs → codexCommand-AgVJYnFU.cjs} +87 -45
- package/dist/{codexCommand-3ZsmFNCE.mjs → codexCommand-BdrBNbZu.mjs} +87 -45
- package/dist/{config-q8FBDbqS.mjs → config-Cr3VUzbE.mjs} +3 -3
- package/dist/{config-CJTzYT71.cjs → config-D89sE3wK.cjs} +3 -3
- package/dist/{configuration-2Eck1oZf.mjs → configuration-BNGPXg07.mjs} +1 -1
- package/dist/{configuration-C_-2io9T.cjs → configuration-UV4EE5ui.cjs} +1 -1
- package/dist/{connect-ch6-M_fR.cjs → connect-B35YXbdZ.cjs} +13 -13
- package/dist/{connect-CJc2q7Zb.mjs → connect-C0iLkCiY.mjs} +13 -13
- package/dist/{context--xjJuO00.cjs → context-BmH2BKip.cjs} +1 -1
- package/dist/{context-C1tA72Pn.mjs → context-Ptdnlcv6.mjs} +1 -1
- package/dist/{controlClient-DCH7YKU2.cjs → controlClient-CtsQMw--.cjs} +3 -3
- package/dist/{controlClient-Dn0x8DWU.mjs → controlClient-DqtC0pq1.mjs} +3 -3
- package/dist/{createSessionMetadata-BeY_Ct51.cjs → createSessionMetadata-2IuH5nlA.cjs} +2 -2
- package/dist/{createSessionMetadata-IMDmdFLj.mjs → createSessionMetadata-CtNMvfth.mjs} +2 -2
- package/dist/{defaultPermissionMode-CP-RNe7S.cjs → defaultPermissionMode-Bn4HcU8S.cjs} +2 -2
- package/dist/{defaultPermissionMode-C7be9Tg9.mjs → defaultPermissionMode-DYihjV2g.mjs} +2 -2
- package/dist/{deterministicJson-Cun6TLIF.mjs → deterministicJson-DF4xv6MH.mjs} +9 -9
- package/dist/{deterministicJson-3OOoCWI0.cjs → deterministicJson-je21npNx.cjs} +9 -9
- package/dist/{doctor-DE9dpmhV.cjs → doctor-BXKcYVGU.cjs} +7 -7
- package/dist/{doctor-B3krtkx6.mjs → doctor-Ba92L7-b.mjs} +7 -7
- package/dist/{downloadTarget-BBAA6-Wy.mjs → downloadTarget-CUJg8iJV.mjs} +6 -6
- package/dist/{downloadTarget-nKU9KvK-.cjs → downloadTarget-JC7FZl7W.cjs} +6 -6
- package/dist/{ensureDaemonRunning-bshCT05q.mjs → ensureDaemonRunning-JPA9tHNE.mjs} +5 -5
- package/dist/{ensureDaemonRunning-D3F9Wn4o.cjs → ensureDaemonRunning-bIp6-vgi.cjs} +5 -5
- package/dist/{handleResumeCommand-DSYAc7pz.cjs → handleResumeCommand-B6b9kIYf.cjs} +5 -5
- package/dist/{handleResumeCommand-DqQ2rB_w.mjs → handleResumeCommand-B6lE5DtU.mjs} +5 -5
- package/dist/{index-BzM5uj8R.cjs → index-B1ABQRrB.cjs} +4 -4
- package/dist/{index-DzqTd9GX.cjs → index-B2KL0aPc.cjs} +36 -36
- package/dist/{index-C9hI8a10.cjs → index-BZdhwBKa.cjs} +3 -1
- package/dist/{index-C7IYgnoC.mjs → index-CZLwo1FS.mjs} +3 -3
- package/dist/{index-CLTdBqtl.mjs → index-CjE4kBKx.mjs} +37 -37
- package/dist/{index-I6GVU3_G.cjs → index-D759ViMU.cjs} +3 -3
- package/dist/{index-DtDYoGpm.mjs → index-DW1ONaGc.mjs} +4 -4
- package/dist/{index-B0HEEYGh.mjs → index-boE-d8CM.mjs} +3 -1
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-BFd6bwk2.mjs → install-CmojqnLK.mjs} +3 -3
- package/dist/{install-D8XM9y0N.cjs → install-KjIsK_EA.cjs} +3 -3
- package/dist/lib.cjs +12 -12
- package/dist/lib.mjs +12 -12
- package/dist/{lidState-hKB4aKcf.cjs → lidState-BmJp2pLt.cjs} +1 -1
- package/dist/{lidState-B1KB4bLv.mjs → lidState-CL1NdKfQ.mjs} +1 -1
- package/dist/{localHappyAgentAuth-B_ItamJZ.cjs → localHappyAgentAuth-9SP7hdiw.cjs} +1 -1
- package/dist/{localHappyAgentAuth-B94JIex_.mjs → localHappyAgentAuth-B7f4Ysn0.mjs} +1 -1
- package/dist/{logger-DYejzaY9.cjs → logger-C7dRaCkE.cjs} +2 -2
- package/dist/{logger-CKCRe63e.mjs → logger-D5EzMy30.mjs} +2 -2
- package/dist/{machineMetadata-C7Slozib.cjs → machineMetadata-DYYuK_0c.cjs} +3 -3
- package/dist/{machineMetadata-CiemL6uU.mjs → machineMetadata-DqplCWue.mjs} +3 -3
- package/dist/{main-BQBSqrW3.mjs → main-CnV62agu.mjs} +44 -44
- package/dist/{main-CJCss2TE.cjs → main-kgCQgknK.cjs} +44 -44
- package/dist/{mcp-cq0hhROT.cjs → mcp-BV0vxHtz.cjs} +14 -14
- package/dist/{mcp-BRtLFMHZ.mjs → mcp-bDPaj-tM.mjs} +14 -14
- package/dist/{mirrorProtocol-pDuMxeQj.cjs → mirrorProtocol-BSHVZ8Nf.cjs} +3 -3
- package/dist/{mirrorProtocol-hPlbcL2P.mjs → mirrorProtocol-ClKhNXYe.mjs} +3 -3
- package/dist/{package-JFU2Ry9r.mjs → package-D0dxZ-W8.mjs} +7 -7
- package/dist/{package-DwxuhtoO.cjs → package-VqWv7EI5.cjs} +7 -7
- package/dist/{peerTools-D-yf7SlL.mjs → peerTools-B_eiNB3P.mjs} +4 -4
- package/dist/{peerTools-DiBZOaPT.cjs → peerTools-BktGmlpd.cjs} +4 -4
- package/dist/{persistence-CG158J29.mjs → persistence-CIIhP0Uw.mjs} +2 -2
- package/dist/{persistence-Bi1BTtHq.cjs → persistence-DweHi8xa.cjs} +2 -2
- package/dist/{piRunnerArgs-DkCs_Ma1.cjs → piRunnerArgs-BNzWTNRV.cjs} +1 -1
- package/dist/{piRunnerArgs-C-8jIqUE.mjs → piRunnerArgs-cQafsadv.mjs} +1 -1
- package/dist/{piRuntime-C4Ei1y-P.mjs → piRuntime-Bel5lOLb.mjs} +1 -1
- package/dist/{piRuntime-CHsld2lz.cjs → piRuntime-VZLSwW-4.cjs} +1 -1
- package/dist/{piTerminal-yp98lIpx.mjs → piTerminal-CS5SDi_H.mjs} +16 -16
- package/dist/{piTerminal-D4Hy_mmZ.cjs → piTerminal-DkR8sPv-.cjs} +16 -16
- package/dist/{rateLimitWindows-C36y0Ldw.mjs → rateLimitWindows-Bo6XVnie.mjs} +1 -1
- package/dist/{rateLimitWindows-Blhk1RyR.cjs → rateLimitWindows-Bp4T21RI.cjs} +1 -1
- package/dist/{registerCommonHandlers-Ct5XkkNU.cjs → registerCommonHandlers-B7QZxkCL.cjs} +2 -2
- package/dist/{registerCommonHandlers-ni8jeOJc.mjs → registerCommonHandlers-CR5jpiSx.mjs} +2 -2
- package/dist/{registerKillSessionHandler-DoR8z8b6.cjs → registerKillSessionHandler-CcX84g-T.cjs} +6 -6
- package/dist/{registerKillSessionHandler-B0LoAR3_.mjs → registerKillSessionHandler-DLiu24CQ.mjs} +6 -6
- package/dist/{remoteSessionClient-B7YBUGMI.cjs → remoteSessionClient-CL3akj0K.cjs} +5 -5
- package/dist/{remoteSessionClient-B5vn4Ghn.mjs → remoteSessionClient-CUjw1COc.mjs} +5 -5
- package/dist/{reportProgressTool-25DIibtH.mjs → reportProgressTool-BLLwMQrN.mjs} +2 -2
- package/dist/{reportProgressTool-BVTrYVsY.cjs → reportProgressTool-DzMi4mvH.cjs} +2 -2
- package/dist/{run-Buxf1ATU.cjs → run-5pmOElaW.cjs} +34 -34
- package/dist/{run-D4qgzSft.mjs → run-DGokR_6q.mjs} +33 -33
- package/dist/{runClaude-CRkWhQ5T.mjs → runClaude-BFlpZQds.mjs} +21 -21
- package/dist/{runClaude-D4B0SSd5.cjs → runClaude-EnYNvkV0.cjs} +21 -21
- package/dist/{runClaudeDeps-BKYHcQkO.cjs → runClaudeDeps-CUDebE9e.cjs} +35 -35
- package/dist/{runClaudeDeps-CbyQIbNw.mjs → runClaudeDeps-D1M1dzlZ.mjs} +40 -40
- package/dist/{runGemini-OgmDK1Lq.cjs → runGemini-Bu69Zu1u.cjs} +32 -32
- package/dist/{runGemini-Dn6yFpnO.mjs → runGemini-Bub8T5cM.mjs} +32 -32
- package/dist/{runOpenClaw-DFD--ZW9.cjs → runOpenClaw-Cob5F3FC.cjs} +18 -18
- package/dist/{runOpenClaw-CDU1UOZ1.mjs → runOpenClaw-DVu73F_i.mjs} +18 -18
- package/dist/{sandbox-DojsNXsy.mjs → sandbox-9EKOFyQF.mjs} +4 -4
- package/dist/{sandbox-ryBV4t4z.cjs → sandbox-GDqMagSF.cjs} +4 -4
- package/dist/selfCheck-CNo4uzGB.mjs +84 -0
- package/dist/{selfCheck-B69om90v.cjs → selfCheck-DiNo34da.cjs} +34 -34
- package/dist/{send-Bi7MDDHN.cjs → send-ThC80164.cjs} +8 -8
- package/dist/{send-DyRupwU5.mjs → send-wgtHphq8.mjs} +8 -8
- package/dist/{server-B4SxszzQ.mjs → server-Bb8v2fOj.mjs} +4 -4
- package/dist/{server-DpJPHOAb.cjs → server-bidHnstE.cjs} +6 -6
- package/dist/{sessionLock-DdoHaNAf.cjs → sessionLock-BWBcBZKh.cjs} +3 -3
- package/dist/{sessionLock-ZtySCwjt.mjs → sessionLock-gb32sVPR.mjs} +3 -3
- package/dist/{sessionModeFile-B-z4OPU6.mjs → sessionModeFile-C-fr1M1h.mjs} +1 -1
- package/dist/{sessionModeFile-Bkzcsv_J.cjs → sessionModeFile-DhuTNcJr.cjs} +1 -1
- package/dist/{sessionOps-BUzvciA5.cjs → sessionOps-9MChM9Op.cjs} +4 -4
- package/dist/{sessionOps-BtqGzSz1.mjs → sessionOps-ByZJbkMq.mjs} +4 -4
- package/dist/{sessionScanner-DOdHh5CA.cjs → sessionScanner-BpegdnXK.cjs} +3 -3
- package/dist/{sessionScanner-60sqJeks.mjs → sessionScanner-CxXPAVyS.mjs} +3 -3
- package/dist/{sessions-OCFh0naE.cjs → sessions-C1X4z_Lm.cjs} +9 -9
- package/dist/{sessions-AM5DxBgS.mjs → sessions-l-UgJGjV.mjs} +9 -9
- package/dist/{setupOfflineReconnection-BcHl9VGI.cjs → setupOfflineReconnection-CS_8Da8R.cjs} +2 -2
- package/dist/{setupOfflineReconnection-VK1e2LME.mjs → setupOfflineReconnection-CgtXlV74.mjs} +2 -2
- package/dist/{spawn-CjtSsVs5.cjs → spawn-D2BlNdZu.cjs} +13 -13
- package/dist/{spawn-CG1ckxEZ.mjs → spawn-FyoHqYWo.mjs} +13 -13
- package/dist/{spawnAgents-HDaE3C0-.mjs → spawnAgents-BhsbJ253.mjs} +1 -1
- package/dist/{spawnAgents-vglexX9N.cjs → spawnAgents-CgMKuOhZ.cjs} +1 -1
- package/dist/{spawnHappyCLI-A9QYQdFL.cjs → spawnHappyCLI-DByQcqEN.cjs} +1 -1
- package/dist/{spawnHappyCLI-XVh-9eez.mjs → spawnHappyCLI-DsC256j_.mjs} +1 -1
- package/dist/{specialCommands-BK2gc9vz.cjs → specialCommands-DGUeZqdm.cjs} +3 -3
- package/dist/{specialCommands-VaHfF5iC.mjs → specialCommands-DUUBqzvd.mjs} +3 -3
- package/dist/{startFileWatcher-CwkqU0fA.cjs → startFileWatcher-BtBaahTn.cjs} +1 -1
- package/dist/{startFileWatcher-Dls9MDuo.mjs → startFileWatcher-CaYRObJu.mjs} +1 -1
- package/dist/{streamRelay-Iogsh51a.mjs → streamRelay-C8zI7OnR.mjs} +1 -1
- package/dist/{streamRelay-Ce9sgcOV.cjs → streamRelay-DqPFsCgx.cjs} +1 -1
- package/dist/{sync-BN5jPiq4.cjs → sync-BK-IBkuB.cjs} +1 -1
- package/dist/{sync-CU7N-dAQ.mjs → sync-D5YqUVjS.mjs} +1 -1
- package/dist/{systemPrompt-bo6KFoMZ.cjs → systemPrompt-DaTKLEb-.cjs} +2 -2
- package/dist/{systemPrompt-W9opO926.mjs → systemPrompt-e-qeag_h.mjs} +2 -2
- package/dist/{teams-hotQxTHy.mjs → teams-ClrppvKu.mjs} +6 -6
- package/dist/{teams--pI0Ri5A.cjs → teams-D9xwa_d3.cjs} +6 -6
- package/dist/{time-BDZ6VD5o.cjs → time-0szhiPo4.cjs} +1 -1
- package/dist/{time-jR_TKQyj.mjs → time-CvrpeD3S.mjs} +1 -1
- package/dist/{titleGenerator-Dp0eIi1b.mjs → titleGenerator-BZ5770wq.mjs} +1 -1
- package/dist/{titleGenerator-CQ6ZqGb2.cjs → titleGenerator-Dz5P7sE1.cjs} +2 -2
- package/dist/{todo-DVCyX6N9.cjs → todo-CkmNJQey.cjs} +6 -6
- package/dist/{todo-CwW7byJY.mjs → todo-o-miKcN2.mjs} +6 -6
- package/dist/{tools-C5HNddiJ.cjs → tools-C77-Ssan.cjs} +1 -1
- package/dist/{tools-BzD8JYIx.mjs → tools-Cp0qJeBq.mjs} +1 -1
- package/dist/{uninstall-G9lEyEVW.cjs → uninstall-DGUPERDX.cjs} +3 -3
- package/dist/{uninstall-HRcEekvo.mjs → uninstall-jNJDCLD_.mjs} +3 -3
- package/package.json +7 -7
- package/dist/selfCheck-jA7PDBkO.mjs +0 -84
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { spawn } from 'cross-spawn';
|
|
3
3
|
import { createInterface } from 'node:readline';
|
|
4
|
-
import { l as logger } from './logger-
|
|
4
|
+
import { l as logger } from './logger-D5EzMy30.mjs';
|
|
5
5
|
import { e as errorLogMetadata, c as contentLogMetadata } from './contentLogMetadata-BlWI0egu.mjs';
|
|
6
6
|
import { i as initializeSandbox, w as wrapForMcpTransport } from './manager-BEsI4qt3.mjs';
|
|
7
|
-
import { p as packageJson } from './package-
|
|
8
|
-
import { s as shouldReadCodexRateLimits, i as isUnsupportedCodexMethodError } from './rateLimitWindows-
|
|
7
|
+
import { p as packageJson } from './package-D0dxZ-W8.mjs';
|
|
8
|
+
import { s as shouldReadCodexRateLimits, i as isUnsupportedCodexMethodError } from './rateLimitWindows-Bo6XVnie.mjs';
|
|
9
9
|
|
|
10
10
|
function isAppServerAvailable() {
|
|
11
11
|
try {
|
|
@@ -89,7 +89,6 @@ class CodexAppServerClient {
|
|
|
89
89
|
_turnId = null;
|
|
90
90
|
threadDefaults = null;
|
|
91
91
|
// Turn completion tracking for the currently active sendTurnAndWait call.
|
|
92
|
-
// A completion event only resolves once we have seen task_started for this turn.
|
|
93
92
|
pendingTurnCompletion = null;
|
|
94
93
|
// Tracks in-flight interruptTurn() RPCs so sendTurnAndWait can wait for them
|
|
95
94
|
// before starting a new turn (prevents stale turn/interrupt from aborting the next turn).
|
|
@@ -99,7 +98,29 @@ class CodexAppServerClient {
|
|
|
99
98
|
idleRelease = null;
|
|
100
99
|
notificationProtocol = "unknown";
|
|
101
100
|
completedTurnIds = /* @__PURE__ */ new Set();
|
|
101
|
+
/** B-625: turns whose failure has already been forwarded, so a second failed frame is not. */
|
|
102
|
+
failedTurnIds = /* @__PURE__ */ new Set();
|
|
103
|
+
// B-625: the app-server speaks for every thread it hosts — the session's own and the
|
|
104
|
+
// children `spawn_agent` opens — so a lifecycle frame (turn/started, turn/completed,
|
|
105
|
+
// thread/status/changed, error, thread/closed) is the session's only when its `threadId`
|
|
106
|
+
// is ours; a frame naming no thread belongs to the thread it was asked on (Orca's rule,
|
|
107
|
+
// src/main/codex/codex-structured-turn-open-wait.ts). Before this, a child's
|
|
108
|
+
// `turn/completed` ended the parent's turn in the UI and a child's `turn/started`
|
|
109
|
+
// retargeted `turn/interrupt` at the child.
|
|
110
|
+
/** The own thread's last turn-ending `error` (willRetry=false), for a turn end that arrives without a verdict. */
|
|
111
|
+
lastTurnError = null;
|
|
112
|
+
/** Own thread reported idle/systemError while a turn was pending: Codex's `turn/completed`
|
|
113
|
+
* follows within a millisecond; this ends the turn if it does not (see armThreadStopGrace). */
|
|
114
|
+
threadStopGrace = null;
|
|
115
|
+
/** Last few hundred chars of the app-server's stderr: Codex's own last words when it dies. */
|
|
116
|
+
stderrRing = "";
|
|
102
117
|
rawFileChangesByItemId = /* @__PURE__ */ new Map();
|
|
118
|
+
// B-622: inactivity watchdog for the pending turn — re-armed by every
|
|
119
|
+
// notification, never a cap on how long a turn may run (see sendTurnAndWait).
|
|
120
|
+
turnWatchdog = null;
|
|
121
|
+
// Approval / elicitation requests we are still answering: a human may take
|
|
122
|
+
// longer than the watchdog to decide, and that is not Codex going silent.
|
|
123
|
+
inflightServerRequests = 0;
|
|
103
124
|
// Handlers set by the consumer (runCodex.ts)
|
|
104
125
|
eventHandler = null;
|
|
105
126
|
approvalHandler = null;
|
|
@@ -161,8 +182,21 @@ class CodexAppServerClient {
|
|
|
161
182
|
const status = params?.turn?.status ?? params?.status ?? null;
|
|
162
183
|
return typeof status === "string" && status.length > 0 ? status : null;
|
|
163
184
|
}
|
|
185
|
+
extractThreadId(params) {
|
|
186
|
+
const threadId = params?.threadId ?? params?.thread_id ?? params?.thread?.id ?? null;
|
|
187
|
+
return typeof threadId === "string" && threadId.length > 0 ? threadId : null;
|
|
188
|
+
}
|
|
189
|
+
/** B-625: whether a lifecycle frame is about the session's own thread (see the field comment). */
|
|
190
|
+
isOwnThreadFrame(params) {
|
|
191
|
+
const threadId = this.extractThreadId(params);
|
|
192
|
+
return threadId === null || this._threadId === null || threadId === this._threadId;
|
|
193
|
+
}
|
|
194
|
+
/** Codex's last stderr lines, one line, for a message a person reads. */
|
|
195
|
+
stderrTail() {
|
|
196
|
+
return this.stderrRing.replace(/\x1b\[[0-9;]*m/g, "").replace(/\s+/g, " ").trim();
|
|
197
|
+
}
|
|
164
198
|
shouldHandleRawNotification(method) {
|
|
165
|
-
const isRawNotification = method === "thread/started" || method === "turn/started" || method === "turn/completed" || method === "thread/status/changed" || method === "thread/tokenUsage/updated" || method.startsWith("item/");
|
|
199
|
+
const isRawNotification = method === "thread/started" || method === "turn/started" || method === "turn/completed" || method === "thread/status/changed" || method === "thread/closed" || method === "thread/tokenUsage/updated" || method.startsWith("item/");
|
|
166
200
|
if (!isRawNotification) {
|
|
167
201
|
return false;
|
|
168
202
|
}
|
|
@@ -176,14 +210,20 @@ class CodexAppServerClient {
|
|
|
176
210
|
}
|
|
177
211
|
emitRawTurnCompletion(turnId, status, error, source) {
|
|
178
212
|
const aborted = status === "cancelled" || status === "canceled" || status === "aborted" || status === "interrupted";
|
|
213
|
+
const failed = status === "failed" || error !== void 0 && error !== null;
|
|
214
|
+
this.clearThreadStopGrace();
|
|
179
215
|
this.tryResolvePendingTurn(aborted, turnId, source);
|
|
180
216
|
this._turnId = null;
|
|
181
217
|
this.maybeRefreshRateLimits();
|
|
218
|
+
if (this.lastTurnError && (!turnId || !this.lastTurnError.turnId || this.lastTurnError.turnId === turnId)) {
|
|
219
|
+
this.lastTurnError = null;
|
|
220
|
+
}
|
|
182
221
|
if (turnId && this.completedTurnIds.has(turnId)) {
|
|
183
|
-
return;
|
|
222
|
+
if (!failed || this.failedTurnIds.has(turnId)) return;
|
|
184
223
|
}
|
|
185
224
|
if (turnId) {
|
|
186
225
|
this.completedTurnIds.add(turnId);
|
|
226
|
+
if (failed) this.failedTurnIds.add(turnId);
|
|
187
227
|
}
|
|
188
228
|
if (aborted) {
|
|
189
229
|
this.eventHandler?.({
|
|
@@ -206,6 +246,10 @@ class CodexAppServerClient {
|
|
|
206
246
|
return false;
|
|
207
247
|
}
|
|
208
248
|
if (method === "turn/started") {
|
|
249
|
+
if (!this.isOwnThreadFrame(params)) {
|
|
250
|
+
logger.debug(`[CodexAppServer] Child thread ${this.extractThreadId(params)} started a turn`);
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
209
253
|
const turnId = this.extractTurnId(params);
|
|
210
254
|
if (turnId) {
|
|
211
255
|
this._turnId = turnId;
|
|
@@ -218,6 +262,10 @@ class CodexAppServerClient {
|
|
|
218
262
|
return true;
|
|
219
263
|
}
|
|
220
264
|
if (method === "turn/completed") {
|
|
265
|
+
if (!this.isOwnThreadFrame(params)) {
|
|
266
|
+
logger.debug(`[CodexAppServer] Child thread ${this.extractThreadId(params)} ended a turn`);
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
221
269
|
this.emitRawTurnCompletion(
|
|
222
270
|
this.extractTurnId(params),
|
|
223
271
|
this.extractTurnStatus(params),
|
|
@@ -227,9 +275,23 @@ class CodexAppServerClient {
|
|
|
227
275
|
return true;
|
|
228
276
|
}
|
|
229
277
|
if (method === "thread/status/changed") {
|
|
278
|
+
if (!this.isOwnThreadFrame(params)) return true;
|
|
230
279
|
const statusType = params?.status?.type;
|
|
231
|
-
if (statusType === "idle" && this.pendingTurnCompletion) {
|
|
232
|
-
this.
|
|
280
|
+
if ((statusType === "idle" || statusType === "systemError") && this.pendingTurnCompletion?.opened) {
|
|
281
|
+
this.armThreadStopGrace(statusType);
|
|
282
|
+
} else if (statusType === "active") {
|
|
283
|
+
this.clearThreadStopGrace();
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
if (method === "thread/closed") {
|
|
288
|
+
if (this.isOwnThreadFrame(params) && this.pendingTurnCompletion) {
|
|
289
|
+
this.emitRawTurnCompletion(
|
|
290
|
+
this.pendingTurnCompletion.turnId ?? this._turnId,
|
|
291
|
+
"aborted",
|
|
292
|
+
{ message: "Codex closed the thread before the turn ended." },
|
|
293
|
+
method
|
|
294
|
+
);
|
|
233
295
|
}
|
|
234
296
|
return true;
|
|
235
297
|
}
|
|
@@ -316,14 +378,6 @@ class CodexAppServerClient {
|
|
|
316
378
|
phase: item.phase
|
|
317
379
|
});
|
|
318
380
|
}
|
|
319
|
-
if (item.phase === "final_answer" && this.pendingTurnCompletion) {
|
|
320
|
-
this.emitRawTurnCompletion(
|
|
321
|
-
this.extractTurnId(params),
|
|
322
|
-
"completed",
|
|
323
|
-
null,
|
|
324
|
-
`${method}:final_answer`
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
381
|
return true;
|
|
328
382
|
}
|
|
329
383
|
return method.startsWith("item/");
|
|
@@ -383,17 +437,35 @@ class CodexAppServerClient {
|
|
|
383
437
|
return;
|
|
384
438
|
}
|
|
385
439
|
this.connected = false;
|
|
440
|
+
const tail = this.stderrTail();
|
|
441
|
+
const exited = `Codex process exited (code=${code ?? "null"}${signal ? `, signal=${signal}` : ""})`;
|
|
386
442
|
for (const [id, req] of this.pending) {
|
|
387
443
|
if (req.epoch !== epoch) continue;
|
|
388
|
-
|
|
444
|
+
const error = new Error(`${exited} while waiting for ${req.method}`);
|
|
445
|
+
error.codexStderrTail = tail;
|
|
446
|
+
req.reject(error);
|
|
389
447
|
this.pending.delete(id);
|
|
390
448
|
}
|
|
449
|
+
if (this.pendingTurnCompletion) {
|
|
450
|
+
const turnId = this.pendingTurnCompletion.turnId ?? this._turnId;
|
|
451
|
+
this.eventHandler?.({
|
|
452
|
+
type: "turn_aborted",
|
|
453
|
+
reason: "process-exit",
|
|
454
|
+
...turnId ? { turn_id: turnId } : {},
|
|
455
|
+
error: { message: `${exited}${tail ? `: ${tail}` : ""}` }
|
|
456
|
+
});
|
|
457
|
+
}
|
|
391
458
|
this.resolvePendingTurn(true);
|
|
392
459
|
});
|
|
460
|
+
this.stderrRing = "";
|
|
393
461
|
proc.stderr?.on("data", (chunk) => {
|
|
394
462
|
if (this.process !== proc || this.processEpoch !== epoch) return;
|
|
395
463
|
const text = chunk.toString().trim();
|
|
396
|
-
if (text)
|
|
464
|
+
if (text) {
|
|
465
|
+
logger.debug("[CodexAppServer:stderr]", contentLogMetadata(text));
|
|
466
|
+
this.stderrRing = `${this.stderrRing}
|
|
467
|
+
${text}`.slice(-400);
|
|
468
|
+
}
|
|
397
469
|
});
|
|
398
470
|
this.readline = createInterface({ input: proc.stdout });
|
|
399
471
|
this.readline.on("line", (line) => {
|
|
@@ -444,6 +516,9 @@ class CodexAppServerClient {
|
|
|
444
516
|
this._turnId = null;
|
|
445
517
|
this.notificationProtocol = "unknown";
|
|
446
518
|
this.completedTurnIds.clear();
|
|
519
|
+
this.failedTurnIds.clear();
|
|
520
|
+
this.lastTurnError = null;
|
|
521
|
+
this.clearThreadStopGrace();
|
|
447
522
|
if (!opts?.preserveThreadState) {
|
|
448
523
|
this._threadId = null;
|
|
449
524
|
this.threadDefaults = null;
|
|
@@ -661,15 +736,50 @@ class CodexAppServerClient {
|
|
|
661
736
|
}
|
|
662
737
|
resolvePendingTurn(aborted) {
|
|
663
738
|
if (!this.pendingTurnCompletion) return;
|
|
739
|
+
this.clearTurnWatchdog();
|
|
740
|
+
this.clearThreadStopGrace();
|
|
664
741
|
this.pendingTurnCompletion.resolve(aborted);
|
|
665
742
|
this.pendingTurnCompletion = null;
|
|
666
743
|
}
|
|
667
744
|
markPendingTurnStarted(turnId) {
|
|
668
745
|
if (!this.pendingTurnCompletion) return;
|
|
746
|
+
this.pendingTurnCompletion.opened = true;
|
|
669
747
|
if (turnId) {
|
|
670
748
|
this.pendingTurnCompletion.turnId = turnId;
|
|
671
749
|
}
|
|
672
750
|
}
|
|
751
|
+
/** Default wait for Codex's `turn/completed` after its thread reported idle/systemError. */
|
|
752
|
+
static THREAD_STOP_GRACE_MS = 1500;
|
|
753
|
+
/**
|
|
754
|
+
* B-625: the own thread stopped (idle / systemError) while a turn was pending and
|
|
755
|
+
* had opened. Codex's `turn/completed` follows at once in every probed release
|
|
756
|
+
* (0.154.0: 1 ms); this is the net under a release that does not send it, so the
|
|
757
|
+
* session never waits on the silence watchdog for a turn Codex has already left.
|
|
758
|
+
*/
|
|
759
|
+
armThreadStopGrace(statusType) {
|
|
760
|
+
this.clearThreadStopGrace();
|
|
761
|
+
const graceMs = this.pendingTurnCompletion?.threadStopGraceMs ?? CodexAppServerClient.THREAD_STOP_GRACE_MS;
|
|
762
|
+
this.threadStopGrace = setTimeout(() => {
|
|
763
|
+
this.threadStopGrace = null;
|
|
764
|
+
const pending = this.pendingTurnCompletion;
|
|
765
|
+
if (!pending) return;
|
|
766
|
+
const turnId = pending.turnId ?? this._turnId;
|
|
767
|
+
const lastError = this.lastTurnError && (!turnId || !this.lastTurnError.turnId || this.lastTurnError.turnId === turnId) ? this.lastTurnError.error : null;
|
|
768
|
+
logger.warn(`[CodexAppServer] Thread went ${statusType} and no turn/completed followed for turn ${turnId ?? "?"}; ending the turn`);
|
|
769
|
+
const failed = statusType === "systemError" || lastError !== null;
|
|
770
|
+
this.emitRawTurnCompletion(
|
|
771
|
+
turnId,
|
|
772
|
+
failed ? "failed" : "completed",
|
|
773
|
+
lastError ?? (failed ? { message: "Codex reported a system error and ended the turn without a verdict." } : null),
|
|
774
|
+
`thread/status/changed:${statusType}`
|
|
775
|
+
);
|
|
776
|
+
}, graceMs);
|
|
777
|
+
}
|
|
778
|
+
clearThreadStopGrace() {
|
|
779
|
+
if (!this.threadStopGrace) return;
|
|
780
|
+
clearTimeout(this.threadStopGrace);
|
|
781
|
+
this.threadStopGrace = null;
|
|
782
|
+
}
|
|
673
783
|
tryResolvePendingTurn(aborted, turnId, source) {
|
|
674
784
|
const pending = this.pendingTurnCompletion;
|
|
675
785
|
if (!pending) return;
|
|
@@ -771,6 +881,8 @@ class CodexAppServerClient {
|
|
|
771
881
|
}
|
|
772
882
|
/** Default timeout for waiting on turn completion (ms). 10 minutes. */
|
|
773
883
|
static TURN_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
884
|
+
/** How much of the app-server's stderr is kept for its exit message. */
|
|
885
|
+
static STDERR_TAIL_CHARS = 400;
|
|
774
886
|
/**
|
|
775
887
|
* Send a user turn and wait for it to complete (task_complete or turn_aborted).
|
|
776
888
|
* Returns { aborted: true } if the turn was aborted (user cancel, permission reject, etc.).
|
|
@@ -782,30 +894,58 @@ class CodexAppServerClient {
|
|
|
782
894
|
}
|
|
783
895
|
await this.ensureConnected();
|
|
784
896
|
const timeoutMs = opts?.turnTimeoutMs ?? CodexAppServerClient.TURN_TIMEOUT_MS;
|
|
785
|
-
let timer = null;
|
|
786
897
|
const completion = new Promise((resolve) => {
|
|
787
898
|
this.pendingTurnCompletion = {
|
|
788
899
|
resolve,
|
|
789
|
-
turnId: null
|
|
900
|
+
turnId: null,
|
|
901
|
+
opened: false,
|
|
902
|
+
threadStopGraceMs: opts?.threadStopGraceMs ?? CodexAppServerClient.THREAD_STOP_GRACE_MS
|
|
790
903
|
};
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
logger.warn(`[CodexAppServer] Turn timed out after ${timeoutMs}ms \u2014 treating as abort`);
|
|
794
|
-
this.resolvePendingTurn(true);
|
|
795
|
-
}
|
|
796
|
-
}, timeoutMs);
|
|
904
|
+
this.lastTurnError = null;
|
|
905
|
+
this.armTurnWatchdog(timeoutMs);
|
|
797
906
|
});
|
|
798
907
|
try {
|
|
799
908
|
await this.sendTurn(prompt, opts);
|
|
800
909
|
} catch (err) {
|
|
801
|
-
|
|
910
|
+
this.clearTurnWatchdog();
|
|
802
911
|
this.pendingTurnCompletion = null;
|
|
803
912
|
throw err;
|
|
804
913
|
}
|
|
805
914
|
const aborted = await completion;
|
|
806
|
-
|
|
915
|
+
this.clearTurnWatchdog();
|
|
807
916
|
return { aborted };
|
|
808
917
|
}
|
|
918
|
+
armTurnWatchdog(timeoutMs) {
|
|
919
|
+
this.clearTurnWatchdog();
|
|
920
|
+
const timer = setTimeout(() => {
|
|
921
|
+
this.turnWatchdog = null;
|
|
922
|
+
if (!this.pendingTurnCompletion) return;
|
|
923
|
+
if (this.inflightServerRequests > 0) {
|
|
924
|
+
this.armTurnWatchdog(timeoutMs);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
logger.warn(`[CodexAppServer] No notification from Codex for ${timeoutMs}ms \u2014 giving the turn up as aborted`);
|
|
928
|
+
const turnId = this.pendingTurnCompletion.turnId ?? this._turnId;
|
|
929
|
+
this.eventHandler?.({
|
|
930
|
+
type: "turn_aborted",
|
|
931
|
+
reason: "timeout",
|
|
932
|
+
...turnId ? { turn_id: turnId } : {},
|
|
933
|
+
error: { message: `Codex sent nothing for ${Math.max(1, Math.round(timeoutMs / 6e4))} minutes; this turn was given up. Send the message again, or restart the session if it keeps happening.` }
|
|
934
|
+
});
|
|
935
|
+
this.resolvePendingTurn(true);
|
|
936
|
+
}, timeoutMs);
|
|
937
|
+
this.turnWatchdog = { timer, timeoutMs };
|
|
938
|
+
}
|
|
939
|
+
/** Any sign of life from the app-server while a turn is pending restarts the clock. */
|
|
940
|
+
touchTurnWatchdog() {
|
|
941
|
+
if (!this.turnWatchdog || !this.pendingTurnCompletion) return;
|
|
942
|
+
this.armTurnWatchdog(this.turnWatchdog.timeoutMs);
|
|
943
|
+
}
|
|
944
|
+
clearTurnWatchdog() {
|
|
945
|
+
if (!this.turnWatchdog) return;
|
|
946
|
+
clearTimeout(this.turnWatchdog.timer);
|
|
947
|
+
this.turnWatchdog = null;
|
|
948
|
+
}
|
|
809
949
|
async interruptTurn() {
|
|
810
950
|
if (!this._threadId) return;
|
|
811
951
|
if (!this._turnId) {
|
|
@@ -841,6 +981,8 @@ class CodexAppServerClient {
|
|
|
841
981
|
this._turnId = null;
|
|
842
982
|
this.threadDefaults = null;
|
|
843
983
|
this.completedTurnIds.clear();
|
|
984
|
+
this.failedTurnIds.clear();
|
|
985
|
+
this.lastTurnError = null;
|
|
844
986
|
this.rawFileChangesByItemId.clear();
|
|
845
987
|
}
|
|
846
988
|
// ─── JSON-RPC transport ─────────────────────────────────────
|
|
@@ -1013,6 +1155,15 @@ class CodexAppServerClient {
|
|
|
1013
1155
|
};
|
|
1014
1156
|
}
|
|
1015
1157
|
async handleServerRequest(id, method, params) {
|
|
1158
|
+
this.inflightServerRequests += 1;
|
|
1159
|
+
try {
|
|
1160
|
+
await this.handleServerRequestInner(id, method, params);
|
|
1161
|
+
} finally {
|
|
1162
|
+
this.inflightServerRequests -= 1;
|
|
1163
|
+
this.touchTurnWatchdog();
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
async handleServerRequestInner(id, method, params) {
|
|
1016
1167
|
if (method === "mcpServer/elicitation/request") {
|
|
1017
1168
|
const toolName = this.parseToolNameFromElicitationMessage(params?.message) ?? params?.serverName ?? "McpTool";
|
|
1018
1169
|
const decision = await this.handleApproval({
|
|
@@ -1066,6 +1217,7 @@ class CodexAppServerClient {
|
|
|
1066
1217
|
return "denied";
|
|
1067
1218
|
}
|
|
1068
1219
|
handleNotification(method, params) {
|
|
1220
|
+
this.touchTurnWatchdog();
|
|
1069
1221
|
if (method === "codex/event" || method.startsWith("codex/event/")) {
|
|
1070
1222
|
this.notificationProtocol = "legacy";
|
|
1071
1223
|
const msg = params?.msg;
|
|
@@ -1099,6 +1251,7 @@ class CodexAppServerClient {
|
|
|
1099
1251
|
}
|
|
1100
1252
|
if (method === "thread/started" || method === "turn/started" || method === "turn/completed" || method === "thread/status/changed") {
|
|
1101
1253
|
logger.debug(`[CodexAppServer] Lifecycle notification: ${method}`);
|
|
1254
|
+
if (!this.isOwnThreadFrame(params)) return;
|
|
1102
1255
|
if (method === "turn/started") {
|
|
1103
1256
|
const turnId = this.extractTurnId(params);
|
|
1104
1257
|
if (turnId) {
|
|
@@ -1125,6 +1278,30 @@ class CodexAppServerClient {
|
|
|
1125
1278
|
logger.debug(`[CodexAppServer] mcpServer startup status:`, params);
|
|
1126
1279
|
return;
|
|
1127
1280
|
}
|
|
1281
|
+
if (method === "error") {
|
|
1282
|
+
if (!this.isOwnThreadFrame(params)) return;
|
|
1283
|
+
const error = params?.error ?? {};
|
|
1284
|
+
const turnId = typeof params?.turnId === "string" && params.turnId.length > 0 ? params.turnId : null;
|
|
1285
|
+
if (params?.willRetry === true) {
|
|
1286
|
+
const message = typeof error.message === "string" ? error.message : "";
|
|
1287
|
+
const info = error.codexErrorInfo;
|
|
1288
|
+
const httpStatus = info && typeof info === "object" ? info.responseStreamDisconnected?.httpStatusCode ?? info.httpStatusCode ?? null : null;
|
|
1289
|
+
this.eventHandler?.({
|
|
1290
|
+
type: "turn_retry",
|
|
1291
|
+
message,
|
|
1292
|
+
...typeof httpStatus === "number" ? { http_status: httpStatus } : {},
|
|
1293
|
+
...turnId ? { turn_id: turnId } : {},
|
|
1294
|
+
...typeof error.additionalDetails === "string" ? { details: error.additionalDetails } : {}
|
|
1295
|
+
});
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
this.lastTurnError = { turnId, error };
|
|
1299
|
+
const pending = this.pendingTurnCompletion;
|
|
1300
|
+
if (pending && !pending.opened && (turnId === null || pending.turnId === null || pending.turnId === turnId)) {
|
|
1301
|
+
this.emitRawTurnCompletion(turnId ?? pending.turnId, "failed", error, "error:unopened-turn");
|
|
1302
|
+
}
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1128
1305
|
logger.debug(`[CodexAppServer] Notification: ${method}`);
|
|
1129
1306
|
}
|
|
1130
1307
|
}
|