very-happy-cli 0.2.176 → 0.2.177
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-9_ZI1Bv3.cjs → AcpBackend-B-ny68XM.cjs} +188 -37
- package/dist/{AcpBackend-COp6D8gl.mjs → AcpBackend-B0K0WrtW.mjs} +187 -38
- package/dist/{BasePermissionHandler-DPvLN7aR.cjs → BasePermissionHandler-DR6nxuEn.cjs} +1 -1
- package/dist/{BasePermissionHandler-ChMkmsGD.mjs → BasePermissionHandler-hdY7kTqX.mjs} +1 -1
- package/dist/{agentHome-BKi7tsE9.cjs → agentHome-BdTXEUPe.cjs} +4 -4
- package/dist/{agentHome-D61ZMLXM.mjs → agentHome-GRN2VfHv.mjs} +4 -4
- package/dist/{api-Buc_ejoA.cjs → api-BWX10o97.cjs} +15 -8
- package/dist/{api-CbwDDXJt.mjs → api-CKBViqI3.mjs} +16 -9
- package/dist/{apiMachine--PXoXwKq.cjs → apiMachine-BYYFGgFs.cjs} +14 -13
- package/dist/{apiMachine-CS7t3Rg-.mjs → apiMachine-DttO4UFj.mjs} +15 -14
- package/dist/{attachmentContent-BQYc8KpE.mjs → attachmentContent-cPVF463_.mjs} +1 -1
- package/dist/{attachmentContent-CFzzTeV9.cjs → attachmentContent-kJKXpkMX.cjs} +1 -1
- package/dist/{auth-B3xMoveE.mjs → auth-BmESeKuM.mjs} +5 -5
- package/dist/{auth-CBkmRIGw.mjs → auth-CKdXb9zp.mjs} +8 -8
- package/dist/{auth-CpO3ZUMz.cjs → auth-CTECt2Oz.cjs} +5 -5
- package/dist/{auth-LPvsVriN.cjs → auth-DNxVmVbn.cjs} +8 -8
- package/dist/{auto-DHGch_zK.mjs → auto-Ch3203qd.mjs} +16 -15
- package/dist/{auto-Dm3EIKT7.cjs → auto-D1ypjjfx.cjs} +14 -13
- package/dist/{backgroundTaskActivity-8PdPxrvy.mjs → backgroundTaskActivity-BVwJBl02.mjs} +1 -1
- package/dist/{bootstrap-BboDz_w2.cjs → bootstrap-6OI698q9.cjs} +2 -2
- package/dist/{bootstrap-CxuBAkJU.mjs → bootstrap-C0s2bPFQ.mjs} +2 -2
- package/dist/{browser-BvARP-YR.mjs → browser-BlLWZUMx.mjs} +1 -1
- package/dist/{browser-GQZJxD2n.cjs → browser-DG6Uof5O.cjs} +1 -1
- package/dist/{claudeLocal-B9EhFmD7.mjs → claudeLocal-CcWcKnoo.mjs} +5 -5
- package/dist/{claudeLocal-D-mujSX1.cjs → claudeLocal-CemsIArT.cjs} +4 -4
- package/dist/{claudeLocalLauncher-Bdl-9aU_.mjs → claudeLocalLauncher-7p6y88nj.mjs} +15 -18
- package/dist/{claudeLocalLauncher-Tbrx6TXF.cjs → claudeLocalLauncher-A4VuevIi.cjs} +14 -17
- package/dist/{claudeSessionFork-D_DKvDKE.mjs → claudeSessionFork-BtROOjqf.mjs} +1 -1
- package/dist/{claudeSessionFork-sOz97qqW.cjs → claudeSessionFork-CbDfm8Fz.cjs} +1 -1
- package/dist/{client-Cg6ABRe-.mjs → client-BPMWutfs.mjs} +3 -3
- package/dist/{client-D9pEOhn4.cjs → client-COmgDDy0.cjs} +2 -2
- package/dist/{client-Ryu9fllj.mjs → client-DG5ndWLw.mjs} +2 -2
- package/dist/{client-D7sSU04O.cjs → client-DyvBTYee.cjs} +3 -3
- package/dist/codex/happyMcpStdioBridge.cjs +14 -14
- package/dist/codex/happyMcpStdioBridge.mjs +15 -15
- package/dist/{codexAppServerClient-C70pJ-BB.mjs → codexAppServerClient-D-Z8qSfI.mjs} +10 -58
- package/dist/{codexAppServerClient-DsIUkVnX.cjs → codexAppServerClient-R24WZZfg.cjs} +6 -54
- package/dist/{codexCommand-Aycux-B7.cjs → codexCommand-6hW19gsq.cjs} +41 -63
- package/dist/{codexCommand-DWbA3pJN.mjs → codexCommand-CVTkZJ1o.mjs} +41 -63
- package/dist/{BaseReasoningProcessor-Dnf16mtJ.cjs → codexTermination-BBU7e92y.cjs} +25 -1
- package/dist/{BaseReasoningProcessor-pjvLSTQF.mjs → codexTermination-CCIfwzcx.mjs} +25 -2
- package/dist/{config-Bztmzu8z.mjs → config-CvsNChKX.mjs} +3 -3
- package/dist/{config-BcL0bxO5.cjs → config-DhdrvOLV.cjs} +3 -3
- package/dist/{configuration-BAwOtWFY.mjs → configuration-D55F0t16.mjs} +1 -1
- package/dist/{configuration-CpBrilxV.cjs → configuration-DZPy0T9Z.cjs} +1 -1
- package/dist/{connect-BeWQ4MMA.mjs → connect-CwCXMRmD.mjs} +12 -12
- package/dist/{connect-BBNCMTi8.cjs → connect-Wz-XZYXW.cjs} +11 -11
- package/dist/{context-Hk0j2Y9-.cjs → context-BKbrZ55r.cjs} +1 -1
- package/dist/{context-j114QJre.mjs → context-CCRpVXFo.mjs} +1 -1
- package/dist/{controlClient-00KYAjsI.mjs → controlClient-C4xB5J6O.mjs} +4 -4
- package/dist/{controlClient-bs_YqwDl.cjs → controlClient-SX8gSza2.cjs} +3 -3
- package/dist/{createSessionMetadata-D4Sj6H95.cjs → createSessionMetadata-BCFmYlBo.cjs} +2 -2
- package/dist/{createSessionMetadata-xlycGog5.mjs → createSessionMetadata-Bi-m0Y_O.mjs} +2 -2
- package/dist/{defaultPermissionMode-CMsiaRzr.cjs → defaultPermissionMode-DMBEnXll.cjs} +2 -2
- package/dist/{defaultPermissionMode-B97ox9p1.mjs → defaultPermissionMode-wBcbBezm.mjs} +2 -2
- package/dist/{deterministicJson-ucyv8j6b.mjs → deterministicJson-BkQETt8_.mjs} +8 -8
- package/dist/{deterministicJson-aHxtYLha.cjs → deterministicJson-ChGfQEF6.cjs} +8 -8
- package/dist/{doctor-D554c6Bg.mjs → doctor-B9c2C9dF.mjs} +8 -8
- package/dist/{doctor-BXkNXcok.cjs → doctor-BsN3JZJn.cjs} +7 -7
- package/dist/{downloadTarget-2_zMvt2N.mjs → downloadTarget-ByXzbDK4.mjs} +6 -6
- package/dist/{downloadTarget-CmdlljZW.cjs → downloadTarget-Dj3WoVJa.cjs} +6 -6
- package/dist/{ensureDaemonRunning-DJlziY-m.mjs → ensureDaemonRunning--HYzs5Ce.mjs} +5 -5
- package/dist/{ensureDaemonRunning-CY7iC--U.cjs → ensureDaemonRunning-7Wb8M7Lv.cjs} +5 -5
- package/dist/{handleResumeCommand-CNTnXBXA.mjs → handleResumeCommand-DHddBkNJ.mjs} +5 -5
- package/dist/{handleResumeCommand-lSVnvTNC.cjs → handleResumeCommand-OmuUGYjQ.cjs} +5 -5
- package/dist/{index-jeD70GGH.cjs → index-BRJzH4sc.cjs} +137 -83
- package/dist/{index-DY3I8j0W.mjs → index-BzJNDsJq.mjs} +139 -85
- package/dist/{index-B6UGRQ7h.mjs → index-CEjJnq05.mjs} +3 -0
- package/dist/{index-59hR7nVz.mjs → index-CEm0MYiS.mjs} +3 -3
- package/dist/{index-DhARRePz.cjs → index-CrR4JISa.cjs} +4 -4
- package/dist/{index-MwTVbeGW.cjs → index-D9NoYc5I.cjs} +3 -3
- package/dist/{index-D3kI0hDR.cjs → index-DFPT4HOO.cjs} +3 -0
- package/dist/{index-CxSLrTPA.mjs → index-Dhl6_bw7.mjs} +4 -4
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-DXUEtGfU.cjs → install-1qn-D9FS.cjs} +3 -3
- package/dist/{install-DytIJ_Ia.mjs → install-BDIUtPXi.mjs} +3 -3
- package/dist/lib.cjs +10 -10
- package/dist/lib.d.cts +7 -1
- package/dist/lib.d.mts +7 -1
- package/dist/lib.mjs +11 -11
- package/dist/{lidState-CduPmrM0.mjs → lidState-BqVsw7H1.mjs} +1 -1
- package/dist/{lidState-UasMvPzw.cjs → lidState-DxbK0qfu.cjs} +1 -1
- package/dist/{localHappyAgentAuth-DL8JjHTV.mjs → localHappyAgentAuth-Ce8kO2yc.mjs} +1 -1
- package/dist/{localHappyAgentAuth-CA02WOny.cjs → localHappyAgentAuth-D5tANdRD.cjs} +1 -1
- package/dist/{logger-CihCDWDw.mjs → logger-13cBr_ew.mjs} +2 -2
- package/dist/{logger-zoO54Zsy.cjs → logger-LvwVeATU.cjs} +2 -2
- package/dist/{machineMetadata-BAKVtr-k.cjs → machineMetadata-29h7vgf4.cjs} +3 -3
- package/dist/{machineMetadata-DEZcQ_CQ.mjs → machineMetadata-dMida2qq.mjs} +3 -3
- package/dist/{main-BIvxyX71.cjs → main-DpM5jaFH.cjs} +44 -44
- package/dist/{main-DyJfNlL_.mjs → main-x4nAhdH5.mjs} +44 -44
- package/dist/{manager-2Il8XJVq.mjs → manager-BEsI4qt3.mjs} +1 -1
- package/dist/{mcp-yoIdGe6C.mjs → mcp-DMiFGYMT.mjs} +15 -15
- package/dist/{mcp-Dd11vHij.cjs → mcp-DQv3caXs.cjs} +14 -14
- package/dist/{mirrorProtocol-D-hF_SE5.cjs → mirrorProtocol-BfrERW7Z.cjs} +2 -2
- package/dist/{mirrorProtocol-BukXB5s3.mjs → mirrorProtocol-Bz8tEabR.mjs} +2 -2
- package/dist/{package-A7zOGx8B.cjs → package-Ch9WGDV_.cjs} +7 -7
- package/dist/{package-ayqGDKSp.mjs → package-CjlsAaRe.mjs} +7 -7
- package/dist/{peerTools-DDMSViPu.mjs → peerTools-CxmrKnfV.mjs} +4 -4
- package/dist/{peerTools-dPc9hRC5.cjs → peerTools-DtGKWli5.cjs} +4 -4
- package/dist/{persistence-Dy3lmall.mjs → persistence-C_tYtOqK.mjs} +2 -2
- package/dist/{persistence-Cih2AWml.cjs → persistence-DXbKOHxl.cjs} +2 -2
- package/dist/{piRunnerArgs-BuJgnUI5.cjs → piRunnerArgs-BVRZe2AR.cjs} +1 -1
- package/dist/{piRunnerArgs-D3z3-1VJ.mjs → piRunnerArgs-BpHc-JZl.mjs} +1 -1
- package/dist/{piRuntime-B-SPcWIr.cjs → piRuntime-D7eio8Ix.cjs} +1 -1
- package/dist/{piRuntime-kVGue-_5.mjs → piRuntime-DOdGF395.mjs} +1 -1
- package/dist/{piTerminal-aEtVdCJ2.mjs → piTerminal-dpxz4Q8D.mjs} +17 -17
- package/dist/{piTerminal-DSxK5aAm.cjs → piTerminal-y_PRo2NY.cjs} +16 -16
- package/dist/processTree-CMHWlVse.cjs +66 -0
- package/dist/processTree-CP5IvQ2Z.mjs +61 -0
- package/dist/{rateLimitWindows-82izLQy8.cjs → rateLimitWindows-DFnMU2Vt.cjs} +1 -1
- package/dist/{rateLimitWindows-E5DRjfE6.mjs → rateLimitWindows-DYHDGuzQ.mjs} +1 -1
- package/dist/{registerCommonHandlers-CqO075-X.cjs → registerCommonHandlers-60VuTkdg.cjs} +2 -2
- package/dist/{registerCommonHandlers-Bm7CMqMv.mjs → registerCommonHandlers-D8OMpBbQ.mjs} +2 -2
- package/dist/{registerKillSessionHandler-D02OY4vi.mjs → registerKillSessionHandler-Drhf7-Vz.mjs} +4 -4
- package/dist/{registerKillSessionHandler-WQra3T9B.cjs → registerKillSessionHandler-pqChBKwO.cjs} +4 -4
- package/dist/{remoteSessionClient-f3DYorl8.cjs → remoteSessionClient-B7NvjHD3.cjs} +5 -5
- package/dist/{remoteSessionClient-Buh6NejV.mjs → remoteSessionClient-D01Hso2-.mjs} +5 -5
- package/dist/{reportProgressTool-C5aSoKYX.mjs → reportProgressTool-B203EZCR.mjs} +1 -1
- package/dist/{reportProgressTool-C2gn_HWD.cjs → reportProgressTool-Du_zAK4h.cjs} +1 -1
- package/dist/{run-Drxogp0j.mjs → run-DX4Zs3Ug.mjs} +31 -31
- package/dist/{run-CDEmq6Zs.cjs → run-DZ5jU53c.cjs} +31 -31
- package/dist/{runClaude-BF6U2Js7.mjs → runClaude-CgPHXP0L.mjs} +25 -21
- package/dist/{runClaude-yEcZTCt_.cjs → runClaude-ClRhHpwR.cjs} +24 -20
- package/dist/{runClaudeDeps-CnNNFjlI.cjs → runClaudeDeps-D2v_WDSL.cjs} +384 -86
- package/dist/{runClaudeDeps-Bl4ndq7N.mjs → runClaudeDeps-Dz2iydq4.mjs} +390 -92
- package/dist/{runGemini-DDVDRNg4.cjs → runGemini-BtZqGFkp.cjs} +206 -191
- package/dist/{runGemini-C3wt7iv7.mjs → runGemini-DBXxpoY8.mjs} +206 -191
- package/dist/{runOpenClaw-CY6YHAvj.mjs → runOpenClaw-BOHpzCEU.mjs} +16 -16
- package/dist/{runOpenClaw-BzlVA_9Q.cjs → runOpenClaw-D8q8G57u.cjs} +15 -15
- package/dist/{sandbox-CX_wLwpq.mjs → sandbox-C452Vrsc.mjs} +4 -4
- package/dist/{sandbox-0UNHR3hP.cjs → sandbox-Cu9mMzjx.cjs} +4 -4
- package/dist/selfCheck-BAvqBwBR.mjs +84 -0
- package/dist/{selfCheck-FNwMFY8p.cjs → selfCheck-gKa3uVr1.cjs} +35 -35
- package/dist/{send-BQkl25g0.cjs → send-2Vb5eppI.cjs} +8 -8
- package/dist/{send-CpEGYict.mjs → send-B8HARi7x.mjs} +9 -9
- package/dist/{server-DnINX_Lm.mjs → server-BBWCIZyS.mjs} +4 -4
- package/dist/{server-BodFZ5sW.cjs → server-Db9Wuam3.cjs} +6 -6
- package/dist/{sessionLock-DOj6mMXn.cjs → sessionLock-6qL_N6Rn.cjs} +3 -3
- package/dist/{sessionLock-Ddn-fhZ0.mjs → sessionLock-ZfvFVdUi.mjs} +3 -3
- package/dist/{sessionModeFile-DDbonFR_.mjs → sessionModeFile-CWVq8AT9.mjs} +1 -1
- package/dist/{sessionModeFile-DVukoSp7.cjs → sessionModeFile-CsLtn_PL.cjs} +1 -1
- package/dist/{sessionOps-B1vQ25GS.mjs → sessionOps-CdgbEJgf.mjs} +5 -5
- package/dist/{sessionOps-Nryt1DZt.cjs → sessionOps-Dmt7WUUs.cjs} +4 -4
- package/dist/{sessionScanner-DCr3ofhR.mjs → sessionScanner-CNVaSNOn.mjs} +34 -4
- package/dist/{sessionScanner-D1h-cdte.cjs → sessionScanner-CQL_WSaC.cjs} +34 -3
- package/dist/{sessions-D2HsTbLf.cjs → sessions-BJblG_Hx.cjs} +9 -9
- package/dist/{sessions-DpAN6Ft9.mjs → sessions-DTomHfFg.mjs} +10 -10
- package/dist/{setupOfflineReconnection-DQHEp330.mjs → setupOfflineReconnection-C5trsV-j.mjs} +2 -2
- package/dist/{setupOfflineReconnection-B9Tw1Ouj.cjs → setupOfflineReconnection-DVA0VpQL.cjs} +2 -2
- package/dist/{spawn-CNjm1yOi.mjs → spawn-CQJFgoOq.mjs} +14 -13
- package/dist/{spawn-CvDZ38hi.cjs → spawn-DRyNAqD8.cjs} +12 -11
- package/dist/{spawnHappyCLI-C8Vl56wB.mjs → spawnHappyCLI-B_0RWxD4.mjs} +1 -1
- package/dist/{spawnHappyCLI-ahi4j6Mh.cjs → spawnHappyCLI-ChniczJ5.cjs} +1 -1
- package/dist/{specialCommands-BpqnGrOP.cjs → specialCommands-DbntVs0d.cjs} +3 -3
- package/dist/{specialCommands-DfVMGXTl.mjs → specialCommands-DkdFJi4N.mjs} +3 -3
- package/dist/{startFileWatcher-Ddn3L0u3.cjs → startFileWatcher-C292fhra.cjs} +1 -1
- package/dist/{startFileWatcher-DXJXY4AE.mjs → startFileWatcher-UQyTSRAP.mjs} +1 -1
- package/dist/{sync-BKvgkhPs.mjs → sync-C3p7-KLn.mjs} +1 -1
- package/dist/{sync-BgZuthoS.cjs → sync-C7sxoUYG.cjs} +1 -1
- package/dist/{systemPrompt-DuPem6c9.mjs → systemPrompt-CdHOlyVW.mjs} +1 -1
- package/dist/{systemPrompt-C6O1cHUg.cjs → systemPrompt-DtibzbRU.cjs} +1 -1
- package/dist/{teams-DifEhhmk.cjs → teams-D7O7TpVU.cjs} +6 -6
- package/dist/{teams-CffMBBfU.mjs → teams-ujXr3AFn.mjs} +6 -6
- package/dist/{time-s8CaneqW.cjs → time-Dg5tVB8S.cjs} +1 -1
- package/dist/{time-DxCTiteK.mjs → time-yEL6wHUF.mjs} +1 -1
- package/dist/{titleGenerator-CXr7t6cf.cjs → titleGenerator-BMEaDTwU.cjs} +2 -2
- package/dist/{titleGenerator-B5T7QSzu.mjs → titleGenerator-Dr-BtjzO.mjs} +1 -1
- package/dist/{todo-B41GKMcI.cjs → todo-CUcFamGs.cjs} +5 -5
- package/dist/{todo-DNO7s8td.mjs → todo-CvJe4M2C.mjs} +5 -5
- package/dist/{tools-697R1uqn.mjs → tools-BrM3bZW5.mjs} +1 -1
- package/dist/{tools-lotMyxIE.cjs → tools-DDKTB5aQ.cjs} +1 -1
- package/dist/{uninstall-CRu96len.cjs → uninstall-7oLuhYIu.cjs} +3 -3
- package/dist/{uninstall-CYO7EDjO.mjs → uninstall-CEcMMQGz.mjs} +3 -3
- package/package.json +7 -7
- package/dist/selfCheck-ClVv8NK3.mjs +0 -84
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
var node_child_process = require('node:child_process');
|
|
4
4
|
var sdk = require('@agentclientprotocol/sdk');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var logger = require('./logger-
|
|
7
|
-
var time = require('./time-
|
|
6
|
+
var logger = require('./logger-LvwVeATU.cjs');
|
|
7
|
+
var time = require('./time-Dg5tVB8S.cjs');
|
|
8
8
|
var contentLogMetadata = require('./contentLogMetadata-ZSFk_NjQ.cjs');
|
|
9
|
-
var
|
|
9
|
+
var processTree = require('./processTree-CMHWlVse.cjs');
|
|
10
|
+
var _package = require('./package-Ch9WGDV_.cjs');
|
|
10
11
|
|
|
11
12
|
function acpImageBlocks(attachments, supportsImages) {
|
|
12
13
|
return attachments.filter((file) => ["image/jpeg", "image/png", "image/gif", "image/webp"].includes(file.mimeType)).map((file) => {
|
|
@@ -15,6 +16,19 @@ function acpImageBlocks(attachments, supportsImages) {
|
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
function isAgentExitError(error) {
|
|
20
|
+
return error instanceof Error && error.agentExited === true;
|
|
21
|
+
}
|
|
22
|
+
function agentExitError(agentName, code, signal, tail) {
|
|
23
|
+
const exited = `${agentName} process exited (code=${code ?? "null"}${signal ? `, signal=${signal}` : ""})`;
|
|
24
|
+
return Object.assign(new Error(tail ? `${exited}: ${tail}` : exited), {
|
|
25
|
+
agentExited: true,
|
|
26
|
+
agentExitCode: code,
|
|
27
|
+
agentExitSignal: signal,
|
|
28
|
+
agentStderrTail: tail
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
18
32
|
const DEFAULT_TIMEOUTS = {
|
|
19
33
|
/** Default initialization timeout: 60 seconds */
|
|
20
34
|
init: 6e4,
|
|
@@ -187,6 +201,48 @@ function buildAcpPermissionMeta(toolCall) {
|
|
|
187
201
|
return meta;
|
|
188
202
|
}
|
|
189
203
|
|
|
204
|
+
const PI_ACP_RETRY = /^Retrying(?: \(attempt \d+\/\d+, waiting \d+s\))?\.\.\.$/;
|
|
205
|
+
const PI_ACP_RETRY_END = "Retry finished, resuming.";
|
|
206
|
+
const PI_ACP_COMPACTION = "Context nearing limit, running automatic compaction...";
|
|
207
|
+
const PI_ACP_COMPACTION_END = "Automatic compaction finished; context was summarized to continue the session.";
|
|
208
|
+
const PI_ACP_UNSUPPORTED = /^Pi (input|editor) UI request is not supported in ACP yet; cancelling it\.$/;
|
|
209
|
+
function notifyMeta(meta) {
|
|
210
|
+
if (!meta || typeof meta !== "object") return null;
|
|
211
|
+
const piAcp = meta.piAcp;
|
|
212
|
+
if (!piAcp || typeof piAcp !== "object") return null;
|
|
213
|
+
const notify = piAcp.notify;
|
|
214
|
+
if (!notify || typeof notify !== "object") return null;
|
|
215
|
+
const level = notify.level;
|
|
216
|
+
return { ...typeof level === "string" ? { level } : {} };
|
|
217
|
+
}
|
|
218
|
+
function classifyPiAcpNotice(text, meta) {
|
|
219
|
+
const notify = notifyMeta(meta);
|
|
220
|
+
if (notify) return { kind: "notify", text: text.trim(), ...notify.level ? { level: notify.level } : {} };
|
|
221
|
+
const trimmed = text.trim();
|
|
222
|
+
if (PI_ACP_RETRY.test(trimmed)) return { kind: "retry", text: trimmed };
|
|
223
|
+
if (trimmed === PI_ACP_RETRY_END) return { kind: "retry-end", text: trimmed };
|
|
224
|
+
if (trimmed === PI_ACP_COMPACTION) return { kind: "compaction", text: trimmed };
|
|
225
|
+
if (trimmed === PI_ACP_COMPACTION_END) return { kind: "compaction-end", text: trimmed };
|
|
226
|
+
if (PI_ACP_UNSUPPORTED.test(trimmed)) return { kind: "unsupported", text: trimmed };
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
function acpNoticeMessage(agentName, notice) {
|
|
230
|
+
switch (notice.kind) {
|
|
231
|
+
case "retry":
|
|
232
|
+
return `${agentName} is retrying the model request${notice.text.startsWith("Retrying (") ? ` ${notice.text.slice("Retrying ".length).replace(/\.\.\.$/, "")}` : ""}`;
|
|
233
|
+
case "retry-end":
|
|
234
|
+
return `${agentName} retry finished, resuming`;
|
|
235
|
+
case "compaction":
|
|
236
|
+
return `${agentName} is compacting its context (nearing the limit)`;
|
|
237
|
+
case "compaction-end":
|
|
238
|
+
return `${agentName} compacted its context; the session continues on a summary`;
|
|
239
|
+
case "unsupported":
|
|
240
|
+
return `${agentName}: ${notice.text}`;
|
|
241
|
+
case "notify":
|
|
242
|
+
return `${agentName}${notice.level && notice.level !== "info" ? ` ${notice.level}` : ""}: ${notice.text}`;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
190
246
|
const DEFAULT_IDLE_TIMEOUT_MS = 500;
|
|
191
247
|
const DEFAULT_TOOL_CALL_TIMEOUT_MS = 12e4;
|
|
192
248
|
function parseArgsFromContent(content) {
|
|
@@ -240,6 +296,13 @@ function handleAgentMessageChunk(update, ctx) {
|
|
|
240
296
|
if (typeof text !== "string") {
|
|
241
297
|
return { handled: false };
|
|
242
298
|
}
|
|
299
|
+
if (ctx.transport.agentName === "pi") {
|
|
300
|
+
const notice = classifyPiAcpNotice(text, update._meta);
|
|
301
|
+
if (notice) {
|
|
302
|
+
ctx.emit({ type: "event", name: "notice", payload: notice });
|
|
303
|
+
return { handled: true };
|
|
304
|
+
}
|
|
305
|
+
}
|
|
243
306
|
const isThinking = /^\*\*[^*]+\*\*\n/.test(text);
|
|
244
307
|
if (isThinking) {
|
|
245
308
|
ctx.emit({
|
|
@@ -302,25 +365,6 @@ function startToolCall(toolCallId, toolKind, update, ctx, source) {
|
|
|
302
365
|
if (isInvestigation) {
|
|
303
366
|
logger.logger.debug(`[AcpBackend] \u{1F50D} Investigation tool detected - extended timeout (10min) will be used`);
|
|
304
367
|
}
|
|
305
|
-
const timeoutMs = ctx.transport.getToolCallTimeout?.(toolCallId, toolKindStr) ?? DEFAULT_TOOL_CALL_TIMEOUT_MS;
|
|
306
|
-
if (!ctx.toolCallTimeouts.has(toolCallId)) {
|
|
307
|
-
const timeout = setTimeout(() => {
|
|
308
|
-
const duration = formatDuration(ctx.toolCallStartTimes.get(toolCallId));
|
|
309
|
-
logger.logger.debug(`[AcpBackend] Tool call TIMEOUT (from ${source}): ${toolCallId} after ${(timeoutMs / 1e3).toFixed(0)}s - Duration: ${duration}, removing from active set`);
|
|
310
|
-
ctx.activeToolCalls.delete(toolCallId);
|
|
311
|
-
ctx.toolCallStartTimes.delete(toolCallId);
|
|
312
|
-
ctx.toolCallTimeouts.delete(toolCallId);
|
|
313
|
-
ctx.toolCallOutputs.delete(toolCallId);
|
|
314
|
-
if (ctx.activeToolCalls.size === 0) {
|
|
315
|
-
logger.logger.debug("[AcpBackend] No more active tool calls after timeout, emitting idle status");
|
|
316
|
-
ctx.emitIdleStatus();
|
|
317
|
-
}
|
|
318
|
-
}, timeoutMs);
|
|
319
|
-
ctx.toolCallTimeouts.set(toolCallId, timeout);
|
|
320
|
-
logger.logger.debug(`[AcpBackend] \u23F1\uFE0F Set timeout for ${toolCallId}: ${(timeoutMs / 1e3).toFixed(0)}s${isInvestigation ? " (investigation tool)" : ""}`);
|
|
321
|
-
} else {
|
|
322
|
-
logger.logger.debug(`[AcpBackend] Timeout already set for ${toolCallId}, skipping`);
|
|
323
|
-
}
|
|
324
368
|
ctx.clearIdleTimeout();
|
|
325
369
|
ctx.emit({ type: "status", status: "running" });
|
|
326
370
|
const args = parseArgsFromContent(update.content);
|
|
@@ -633,6 +677,23 @@ class AcpBackend {
|
|
|
633
677
|
toolCallCountSincePrompt = 0;
|
|
634
678
|
/** Timeout for emitting 'idle' status after last message chunk */
|
|
635
679
|
idleTimeout = null;
|
|
680
|
+
// B-629 (approach from Orca, src/main/acp/acp-agent-connection.ts): the agent process is
|
|
681
|
+
// part of the turn. Its last stderr lines are kept so its death can be explained, any exit
|
|
682
|
+
// (code or signal) is announced as `stopped`, and a request in flight when it dies rejects
|
|
683
|
+
// at once instead of waiting forever on a stream that will never answer.
|
|
684
|
+
/** Last stderr output of the agent process, bounded. */
|
|
685
|
+
stderrRing = "";
|
|
686
|
+
static STDERR_TAIL_CHARS = 2e3;
|
|
687
|
+
/** Set when the current agent process exited; the backend takes no further prompt. */
|
|
688
|
+
exited = null;
|
|
689
|
+
/** Rejects with the exit error when the current agent process exits (one per spawn). */
|
|
690
|
+
processGone = null;
|
|
691
|
+
/** Fails the request in flight (an oversized frame that was its answer, see MAX_FRAME_CHARS). */
|
|
692
|
+
inflightReject = null;
|
|
693
|
+
/** A single JSON-RPC line longer than this is dropped rather than buffered (Orca: 16 MiB). */
|
|
694
|
+
static MAX_FRAME_CHARS = 16 * 1024 * 1024;
|
|
695
|
+
/** How long the graceful stop gets on dispose before the process tree is killed. */
|
|
696
|
+
static DISPOSE_GRACE_MS = 4e3;
|
|
636
697
|
/** Transport handler for agent-specific behavior */
|
|
637
698
|
transport;
|
|
638
699
|
onMessage(handler) {
|
|
@@ -644,6 +705,23 @@ class AcpBackend {
|
|
|
644
705
|
this.listeners.splice(index, 1);
|
|
645
706
|
}
|
|
646
707
|
}
|
|
708
|
+
/** B-629: the agent's last stderr lines, one line, for a message a person reads. */
|
|
709
|
+
stderrTail() {
|
|
710
|
+
return processTree.readableStderrTail(this.stderrRing);
|
|
711
|
+
}
|
|
712
|
+
/** B-629: the agent process exited; this backend cannot take another prompt. */
|
|
713
|
+
get hasExited() {
|
|
714
|
+
return this.exited !== null;
|
|
715
|
+
}
|
|
716
|
+
/** B-629: a frame that cannot be read in full. One that answers a request fails that request. */
|
|
717
|
+
onOversizedFrame(head, chars) {
|
|
718
|
+
const looksLikeResponse = /"id"\s*:\s*\d+/.test(head) && /"(result|error)"\s*:/.test(head);
|
|
719
|
+
logger.logger.debug(`[AcpBackend] Dropped an oversized ${this.transport.agentName} frame (${Math.round(chars / 1024 / 1024)} MiB${looksLikeResponse ? ", a response" : ""})`);
|
|
720
|
+
if (!looksLikeResponse) return;
|
|
721
|
+
const error = new Error(`${this.transport.agentName} sent a ${Math.round(chars / 1024 / 1024)} MiB response frame that cannot be read; the turn was given up`);
|
|
722
|
+
this.inflightReject?.(error);
|
|
723
|
+
this.emit({ type: "status", status: "error", detail: error.message });
|
|
724
|
+
}
|
|
647
725
|
emit(msg) {
|
|
648
726
|
if (this.disposed) return;
|
|
649
727
|
for (const listener of this.listeners) {
|
|
@@ -686,6 +764,15 @@ class AcpBackend {
|
|
|
686
764
|
if (!this.process.stdin || !this.process.stdout || !this.process.stderr) {
|
|
687
765
|
throw new Error("Failed to create stdio pipes");
|
|
688
766
|
}
|
|
767
|
+
const child = this.process;
|
|
768
|
+
let rejectGone;
|
|
769
|
+
const processGone = new Promise((_, reject) => {
|
|
770
|
+
rejectGone = reject;
|
|
771
|
+
});
|
|
772
|
+
processGone.catch(() => void 0);
|
|
773
|
+
this.processGone = processGone;
|
|
774
|
+
this.exited = null;
|
|
775
|
+
this.stderrRing = "";
|
|
689
776
|
let startupFailure = null;
|
|
690
777
|
let startupFailureSettled = false;
|
|
691
778
|
let rejectStartupFailure = null;
|
|
@@ -705,6 +792,9 @@ class AcpBackend {
|
|
|
705
792
|
this.process.stderr.on("data", (data) => {
|
|
706
793
|
const text = data.toString();
|
|
707
794
|
if (!text.trim()) return;
|
|
795
|
+
if (this.process === child) {
|
|
796
|
+
this.stderrRing = processTree.appendStderrRing(this.stderrRing, text, AcpBackend.STDERR_TAIL_CHARS);
|
|
797
|
+
}
|
|
708
798
|
const hasActiveInvestigation = this.transport.isInvestigationTool ? Array.from(this.activeToolCalls).some((id) => this.transport.isInvestigationTool(id)) : false;
|
|
709
799
|
const context = {
|
|
710
800
|
activeToolCalls: this.activeToolCalls,
|
|
@@ -728,10 +818,14 @@ class AcpBackend {
|
|
|
728
818
|
this.emit({ type: "status", status: "error", detail: err.message });
|
|
729
819
|
});
|
|
730
820
|
this.process.on("exit", (code, signal) => {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
821
|
+
const error = agentExitError(this.transport.agentName, code, signal, this.stderrTail());
|
|
822
|
+
setTimeout(() => rejectGone(error), 50);
|
|
823
|
+
if (this.process !== child) return;
|
|
824
|
+
this.exited = { code, signal, error };
|
|
825
|
+
signalStartupFailure(error);
|
|
826
|
+
logger.logger.debug(`[AcpBackend] Process exited with code ${code}, signal ${signal}`);
|
|
827
|
+
if (!this.disposed) {
|
|
828
|
+
this.emit({ type: "status", status: "stopped", detail: error.message });
|
|
735
829
|
}
|
|
736
830
|
});
|
|
737
831
|
const streams = nodeToWebStreams(
|
|
@@ -741,6 +835,7 @@ class AcpBackend {
|
|
|
741
835
|
const writable = streams.writable;
|
|
742
836
|
const readable = streams.readable;
|
|
743
837
|
const transport = this.transport;
|
|
838
|
+
const backend = this;
|
|
744
839
|
const filteredReadable = new ReadableStream({
|
|
745
840
|
async start(controller) {
|
|
746
841
|
const reader = readable.getReader();
|
|
@@ -771,8 +866,18 @@ class AcpBackend {
|
|
|
771
866
|
buffer += decoder.decode(value, { stream: true });
|
|
772
867
|
const lines = buffer.split("\n");
|
|
773
868
|
buffer = lines.pop() || "";
|
|
869
|
+
if (buffer.length > AcpBackend.MAX_FRAME_CHARS) {
|
|
870
|
+
backend.onOversizedFrame(buffer.slice(0, 200), buffer.length);
|
|
871
|
+
buffer = "";
|
|
872
|
+
filteredCount++;
|
|
873
|
+
}
|
|
774
874
|
for (const line of lines) {
|
|
775
875
|
if (!line.trim()) continue;
|
|
876
|
+
if (line.length > AcpBackend.MAX_FRAME_CHARS) {
|
|
877
|
+
backend.onOversizedFrame(line.slice(0, 200), line.length);
|
|
878
|
+
filteredCount++;
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
776
881
|
const filtered = transport.filterStdoutLine?.(line);
|
|
777
882
|
if (filtered === void 0) {
|
|
778
883
|
controller.enqueue(encoder.encode(line + "\n"));
|
|
@@ -1182,6 +1287,11 @@ class AcpBackend {
|
|
|
1182
1287
|
get supportsImageAttachments() {
|
|
1183
1288
|
return this.supportsImagePrompt;
|
|
1184
1289
|
}
|
|
1290
|
+
/**
|
|
1291
|
+
* B-629: the turn is over when ACP's `prompt` answers (the agent sends every update before
|
|
1292
|
+
* its response on the same ordered stream), never when the text goes quiet — the idle
|
|
1293
|
+
* heuristic below is only a status hint now. Resolves with the agent's `stopReason`.
|
|
1294
|
+
*/
|
|
1185
1295
|
async sendPrompt(sessionId, prompt, attachments = []) {
|
|
1186
1296
|
const promptHasChangeTitle = this.options.hasChangeTitleInstruction?.(prompt) ?? false;
|
|
1187
1297
|
this.toolCallCountSincePrompt = 0;
|
|
@@ -1192,11 +1302,18 @@ class AcpBackend {
|
|
|
1192
1302
|
if (this.disposed) {
|
|
1193
1303
|
throw new Error("Backend has been disposed");
|
|
1194
1304
|
}
|
|
1305
|
+
if (this.exited) {
|
|
1306
|
+
throw this.exited.error;
|
|
1307
|
+
}
|
|
1195
1308
|
if (!this.connection || !this.acpSessionId) {
|
|
1196
1309
|
throw new Error("Session not started");
|
|
1197
1310
|
}
|
|
1198
1311
|
this.emit({ type: "status", status: "running" });
|
|
1199
1312
|
this.waitingForResponse = true;
|
|
1313
|
+
const inflight = new Promise((_, reject) => {
|
|
1314
|
+
this.inflightReject = reject;
|
|
1315
|
+
});
|
|
1316
|
+
inflight.catch(() => void 0);
|
|
1200
1317
|
try {
|
|
1201
1318
|
logger.logger.debug("[AcpBackend] Sending prompt:", {
|
|
1202
1319
|
sessionId,
|
|
@@ -1214,14 +1331,21 @@ class AcpBackend {
|
|
|
1214
1331
|
sessionId: this.acpSessionId,
|
|
1215
1332
|
blockCount: promptRequest.prompt.length
|
|
1216
1333
|
});
|
|
1217
|
-
const response = await
|
|
1334
|
+
const response = await Promise.race([
|
|
1335
|
+
this.connection.prompt(promptRequest),
|
|
1336
|
+
this.processGone ?? new Promise(() => void 0),
|
|
1337
|
+
inflight
|
|
1338
|
+
]);
|
|
1218
1339
|
if (response.usage) {
|
|
1219
1340
|
this.emit({ type: "token-count", ...response.usage });
|
|
1220
1341
|
}
|
|
1221
|
-
|
|
1342
|
+
const stopReason = typeof response.stopReason === "string" ? response.stopReason : void 0;
|
|
1343
|
+
logger.logger.debug(`[AcpBackend] Prompt answered (stopReason=${stopReason ?? "none"})`);
|
|
1344
|
+
this.finishTurn();
|
|
1345
|
+
return stopReason ? { stopReason } : {};
|
|
1222
1346
|
} catch (error) {
|
|
1223
1347
|
logger.logger.debug("[AcpBackend] Error sending prompt:", contentLogMetadata.errorLogMetadata(error));
|
|
1224
|
-
this.
|
|
1348
|
+
this.finishTurn(false);
|
|
1225
1349
|
let errorDetail;
|
|
1226
1350
|
if (error instanceof Error) {
|
|
1227
1351
|
errorDetail = error.message;
|
|
@@ -1244,7 +1368,29 @@ class AcpBackend {
|
|
|
1244
1368
|
detail: errorDetail
|
|
1245
1369
|
});
|
|
1246
1370
|
throw error;
|
|
1371
|
+
} finally {
|
|
1372
|
+
this.inflightReject = null;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* B-629: the turn's bookkeeping ends with the prompt answer: no response is awaited any
|
|
1377
|
+
* more, the idle timer and per-call timers are dropped, and the calls still marked active
|
|
1378
|
+
* belong to a turn that is over. `idle` is emitted once for status listeners.
|
|
1379
|
+
*/
|
|
1380
|
+
finishTurn(announceIdle = true) {
|
|
1381
|
+
this.waitingForResponse = false;
|
|
1382
|
+
if (this.idleTimeout) {
|
|
1383
|
+
clearTimeout(this.idleTimeout);
|
|
1384
|
+
this.idleTimeout = null;
|
|
1385
|
+
}
|
|
1386
|
+
for (const timeout of this.toolCallTimeouts.values()) {
|
|
1387
|
+
clearTimeout(timeout);
|
|
1247
1388
|
}
|
|
1389
|
+
this.toolCallTimeouts.clear();
|
|
1390
|
+
this.activeToolCalls.clear();
|
|
1391
|
+
this.toolCallStartTimes.clear();
|
|
1392
|
+
this.toolCallOutputs.clear();
|
|
1393
|
+
if (announceIdle) this.emitIdleStatus();
|
|
1248
1394
|
}
|
|
1249
1395
|
/**
|
|
1250
1396
|
* Set a session config option value.
|
|
@@ -1389,7 +1535,7 @@ class AcpBackend {
|
|
|
1389
1535
|
if (this.disposed) return;
|
|
1390
1536
|
logger.logger.debug("[AcpBackend] Disposing backend");
|
|
1391
1537
|
this.disposed = true;
|
|
1392
|
-
if (this.connection && this.acpSessionId) {
|
|
1538
|
+
if (this.connection && this.acpSessionId && !this.exited) {
|
|
1393
1539
|
try {
|
|
1394
1540
|
await Promise.race([
|
|
1395
1541
|
this.connection.cancel({ sessionId: this.acpSessionId }),
|
|
@@ -1401,16 +1547,19 @@ class AcpBackend {
|
|
|
1401
1547
|
}
|
|
1402
1548
|
}
|
|
1403
1549
|
if (this.process) {
|
|
1404
|
-
this.process
|
|
1550
|
+
const proc = this.process;
|
|
1551
|
+
processTree.stopProcessGracefully(proc);
|
|
1405
1552
|
await new Promise((resolve) => {
|
|
1553
|
+
if (proc.exitCode != null || proc.signalCode != null) {
|
|
1554
|
+
resolve();
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1406
1557
|
const timeout = setTimeout(() => {
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
this.process.kill("SIGKILL");
|
|
1410
|
-
}
|
|
1558
|
+
logger.logger.debug("[AcpBackend] Force killing process tree");
|
|
1559
|
+
processTree.killProcessTree(proc);
|
|
1411
1560
|
resolve();
|
|
1412
|
-
},
|
|
1413
|
-
|
|
1561
|
+
}, AcpBackend.DISPOSE_GRACE_MS);
|
|
1562
|
+
proc.once("exit", () => {
|
|
1414
1563
|
clearTimeout(timeout);
|
|
1415
1564
|
resolve();
|
|
1416
1565
|
});
|
|
@@ -1439,6 +1588,7 @@ exports.AcpBackend = AcpBackend;
|
|
|
1439
1588
|
exports.DEFAULT_IDLE_TIMEOUT_MS = DEFAULT_IDLE_TIMEOUT_MS;
|
|
1440
1589
|
exports.DEFAULT_TOOL_CALL_TIMEOUT_MS = DEFAULT_TOOL_CALL_TIMEOUT_MS;
|
|
1441
1590
|
exports.DefaultTransport = DefaultTransport;
|
|
1591
|
+
exports.acpNoticeMessage = acpNoticeMessage;
|
|
1442
1592
|
exports.extractErrorDetail = extractErrorDetail;
|
|
1443
1593
|
exports.formatDuration = formatDuration;
|
|
1444
1594
|
exports.formatDurationMinutes = formatDurationMinutes;
|
|
@@ -1449,4 +1599,5 @@ exports.handlePlanUpdate = handlePlanUpdate;
|
|
|
1449
1599
|
exports.handleThinkingUpdate = handleThinkingUpdate;
|
|
1450
1600
|
exports.handleToolCall = handleToolCall;
|
|
1451
1601
|
exports.handleToolCallUpdate = handleToolCallUpdate;
|
|
1602
|
+
exports.isAgentExitError = isAgentExitError;
|
|
1452
1603
|
exports.parseArgsFromContent = parseArgsFromContent;
|