very-happy-cli 0.2.177 → 0.2.179
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-B0K0WrtW.mjs → AcpBackend-CHp3y7cb.mjs} +135 -16
- package/dist/{AcpBackend-B-ny68XM.cjs → AcpBackend-DFipFF7-.cjs} +135 -16
- package/dist/{AcpSessionManager-CjdJLofq.cjs → AcpSessionManager-0zpvRJXc.cjs} +38 -4
- package/dist/{AcpSessionManager-DykjzBM4.mjs → AcpSessionManager-d2-rKWWa.mjs} +38 -4
- package/dist/{BasePermissionHandler-DR6nxuEn.cjs → BasePermissionHandler-CH3zuEkA.cjs} +5 -2
- package/dist/{BasePermissionHandler-hdY7kTqX.mjs → BasePermissionHandler-DdZBYIR4.mjs} +5 -2
- package/dist/acpSessionResume-DTGmAPLt.mjs +67 -0
- package/dist/acpSessionResume-oiCBnAVA.cjs +74 -0
- package/dist/{agentHome-BdTXEUPe.cjs → agentHome-BWcz8mz0.cjs} +5 -5
- package/dist/{agentHome-GRN2VfHv.mjs → agentHome-CghLvL_1.mjs} +5 -5
- package/dist/{api-BWX10o97.cjs → api-Cmjfr8Z7.cjs} +29 -261
- package/dist/{api-CKBViqI3.mjs → api-CzwFpJQc.mjs} +22 -254
- package/dist/{apiMachine-DttO4UFj.mjs → apiMachine-DJkTEiqy.mjs} +53 -16
- package/dist/{apiMachine-BYYFGgFs.cjs → apiMachine-G6OogT08.cjs} +53 -16
- package/dist/{attachmentContent-cPVF463_.mjs → attachmentContent-B2os4HbA.mjs} +2 -2
- package/dist/{attachmentContent-kJKXpkMX.cjs → attachmentContent-Bo0UAsSu.cjs} +4 -4
- package/dist/{auth-BmESeKuM.mjs → auth-BS6PaOOG.mjs} +6 -6
- package/dist/{auth-CTECt2Oz.cjs → auth-D6bBUwZa.cjs} +6 -6
- package/dist/{auth-CKdXb9zp.mjs → auth-DMX0xPNK.mjs} +9 -9
- package/dist/{auth-DNxVmVbn.cjs → auth-HEhRaNgL.cjs} +9 -9
- package/dist/{authRelay-DSAvg1uv.mjs → authRelay-DhQhkBvX.mjs} +1 -1
- package/dist/{authRelay-BdYkC1Po.cjs → authRelay-Dy1qU9td.cjs} +1 -0
- package/dist/{auto-D1ypjjfx.cjs → auto-C6I55iOh.cjs} +19 -18
- package/dist/{auto-Ch3203qd.mjs → auto-Cl1SEDcD.mjs} +19 -18
- package/dist/{bootstrap-6OI698q9.cjs → bootstrap-exVucYav.cjs} +2 -2
- package/dist/{bootstrap-C0s2bPFQ.mjs → bootstrap-iuyufnp3.mjs} +2 -2
- package/dist/{browser-DG6Uof5O.cjs → browser-BohJK12g.cjs} +1 -1
- package/dist/{browser-BlLWZUMx.mjs → browser-CSYum7xH.mjs} +1 -1
- package/dist/{claudeLocal-CcWcKnoo.mjs → claudeLocal-Dq_R3Ax_.mjs} +6 -5
- package/dist/{claudeLocal-CemsIArT.cjs → claudeLocal-re4yjSTx.cjs} +6 -5
- package/dist/{claudeLocalLauncher-A4VuevIi.cjs → claudeLocalLauncher-B4hJHpCA.cjs} +11 -10
- package/dist/{claudeLocalLauncher-7p6y88nj.mjs → claudeLocalLauncher-CN67lN7-.mjs} +11 -10
- package/dist/{claudeSessionFork-BtROOjqf.mjs → claudeSessionFork-BihfD0Ik.mjs} +1 -1
- package/dist/{claudeSessionFork-CbDfm8Fz.cjs → claudeSessionFork-DiSMYerV.cjs} +1 -1
- package/dist/{client-DyvBTYee.cjs → client-BKcK1Bi-.cjs} +3 -3
- package/dist/client-BhoEBnuN.mjs +71 -0
- package/dist/{client-COmgDDy0.cjs → client-CuVdN6PP.cjs} +2 -2
- package/dist/{client-BPMWutfs.mjs → client-DuTDwWSQ.mjs} +3 -3
- package/dist/client-ZjOsn6nZ.cjs +76 -0
- package/dist/{client-DG5ndWLw.mjs → client-wo9nbxuf.mjs} +2 -2
- package/dist/codex/happyMcpStdioBridge.cjs +25 -16
- package/dist/codex/happyMcpStdioBridge.mjs +25 -16
- package/dist/{codexAppServerClient-D-Z8qSfI.mjs → codexAppServerClient-BK3zra_1.mjs} +3 -3
- package/dist/{codexAppServerClient-R24WZZfg.cjs → codexAppServerClient-Dt5zxrun.cjs} +3 -3
- package/dist/{codexCommand-CVTkZJ1o.mjs → codexCommand-B6pY7CMh.mjs} +66 -61
- package/dist/{codexCommand-6hW19gsq.cjs → codexCommand-CAZ1SLjg.cjs} +89 -84
- package/dist/{codexTermination-CCIfwzcx.mjs → codexTermination-Cd1Eon_4.mjs} +1 -1
- package/dist/{codexTermination-BBU7e92y.cjs → codexTermination-DmGbHxcD.cjs} +1 -1
- package/dist/{config-CvsNChKX.mjs → config-2oMG_fEI.mjs} +3 -3
- package/dist/{config-DhdrvOLV.cjs → config-B0uK6K7n.cjs} +3 -3
- package/dist/{configuration-DZPy0T9Z.cjs → configuration-CMHZnp6G.cjs} +1 -1
- package/dist/{configuration-D55F0t16.mjs → configuration-WMi4idBB.mjs} +1 -1
- package/dist/{connect-CwCXMRmD.mjs → connect-BLVHhHzA.mjs} +15 -15
- package/dist/{connect-Wz-XZYXW.cjs → connect-uaglGrde.cjs} +15 -15
- package/dist/{context-BKbrZ55r.cjs → context-DXzU5bFM.cjs} +1 -1
- package/dist/{context-CCRpVXFo.mjs → context-DploEcoN.mjs} +1 -1
- package/dist/{controlClient-C4xB5J6O.mjs → controlClient-BWUJrj3t.mjs} +3 -3
- package/dist/{controlClient-SX8gSza2.cjs → controlClient-C-5qCt8W.cjs} +3 -3
- package/dist/{createSessionMetadata-Bi-m0Y_O.mjs → createSessionMetadata-3uXrJgOW.mjs} +2 -2
- package/dist/{createSessionMetadata-BCFmYlBo.cjs → createSessionMetadata-BkIzHALd.cjs} +2 -2
- package/dist/{defaultPermissionMode-wBcbBezm.mjs → defaultPermissionMode-BzxLh20a.mjs} +2 -2
- package/dist/{defaultPermissionMode-DMBEnXll.cjs → defaultPermissionMode-pS3vmiSg.cjs} +2 -2
- package/dist/{deterministicJson-ChGfQEF6.cjs → deterministicJson-B8z2GPi9.cjs} +220 -14
- package/dist/{deterministicJson-BkQETt8_.mjs → deterministicJson-D_whDMFd.mjs} +217 -12
- package/dist/{doctor-BsN3JZJn.cjs → doctor-Br1Kcy2J.cjs} +8 -8
- package/dist/{doctor-B9c2C9dF.mjs → doctor-CmtSsR2-.mjs} +8 -8
- package/dist/{downloadTarget-Dj3WoVJa.cjs → downloadTarget-BQJK_6oH.cjs} +6 -6
- package/dist/{downloadTarget-ByXzbDK4.mjs → downloadTarget-BoNwTIH_.mjs} +6 -6
- package/dist/{ensureDaemonRunning-7Wb8M7Lv.cjs → ensureDaemonRunning-BRUmsq6J.cjs} +5 -5
- package/dist/{ensureDaemonRunning--HYzs5Ce.mjs → ensureDaemonRunning-Czo9IHJQ.mjs} +5 -5
- package/dist/{handleResumeCommand-DHddBkNJ.mjs → handleResumeCommand-C8thKjqf.mjs} +22 -6
- package/dist/{handleResumeCommand-OmuUGYjQ.cjs → handleResumeCommand-tKD_Hpxc.cjs} +22 -6
- package/dist/{index-CrR4JISa.cjs → index-B0UjHlAe.cjs} +5 -5
- package/dist/{index-BzJNDsJq.mjs → index-BTxHphpV.mjs} +254 -49
- package/dist/index-BiyC7cZ3.mjs +18 -0
- package/dist/{index-De8L5lFK.cjs → index-C6O2vVjm.cjs} +156 -34
- package/dist/index-CUuc6iCn.cjs +24 -0
- package/dist/{index-Dhl6_bw7.mjs → index-CdQI0C9p.mjs} +5 -5
- package/dist/{index-D9NoYc5I.cjs → index-D09T1m8Y.cjs} +3 -3
- package/dist/{index-CEm0MYiS.mjs → index-D3bidoG8.mjs} +3 -3
- package/dist/{index-BRJzH4sc.cjs → index-DMqDMT1Q.cjs} +257 -52
- package/dist/{index-DMy3OCBe.mjs → index-DPOa4NhL.mjs} +154 -35
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-BdvKiOQw.mjs → install-BX3lv3NO.mjs} +1 -1
- package/dist/{install-Cf6AFSWC.cjs → install-BXvf2E3o.cjs} +1 -1
- package/dist/{install-1qn-D9FS.cjs → install-CYRZxS87.cjs} +3 -3
- package/dist/{install-BDIUtPXi.mjs → install-hnve_9vq.mjs} +3 -3
- package/dist/lib.cjs +14 -14
- package/dist/lib.d.cts +65 -1
- package/dist/lib.d.mts +65 -1
- package/dist/lib.mjs +14 -14
- package/dist/{lidState-BqVsw7H1.mjs → lidState-Bb8fgXg3.mjs} +2 -2
- package/dist/{lidState-DxbK0qfu.cjs → lidState-Dv2wwFTj.cjs} +2 -2
- package/dist/{localHappyAgentAuth-D5tANdRD.cjs → localHappyAgentAuth-DjYvkXvV.cjs} +2 -2
- package/dist/{localHappyAgentAuth-Ce8kO2yc.mjs → localHappyAgentAuth-NEU7fax7.mjs} +2 -2
- package/dist/{logger-13cBr_ew.mjs → logger-BtVhHnD8.mjs} +2 -2
- package/dist/{logger-LvwVeATU.cjs → logger-C1GWx3gi.cjs} +2 -2
- package/dist/{machineMetadata-29h7vgf4.cjs → machineMetadata-CLHS9sv_.cjs} +3 -3
- package/dist/{machineMetadata-dMida2qq.mjs → machineMetadata-D-g--oU_.mjs} +3 -3
- package/dist/{main-x4nAhdH5.mjs → main-B2LWV8DI.mjs} +59 -46
- package/dist/{main-DpM5jaFH.cjs → main-CWhSsbtU.cjs} +59 -46
- package/dist/{mcp-DQv3caXs.cjs → mcp-CARUsXHV.cjs} +15 -15
- package/dist/{mcp-DMiFGYMT.mjs → mcp-ext92q3Y.mjs} +15 -15
- package/dist/{mirrorProtocol-Bz8tEabR.mjs → mirrorProtocol-BwYibqry.mjs} +3 -3
- package/dist/{mirrorProtocol-BfrERW7Z.cjs → mirrorProtocol-DEy2g1CB.cjs} +3 -3
- package/dist/{package-CjlsAaRe.mjs → package-BPPebGQF.mjs} +7 -7
- package/dist/{package-Ch9WGDV_.cjs → package-SgqTYsjn.cjs} +7 -7
- package/dist/panels-BZ0_Tt7B.mjs +137 -0
- package/dist/panels-D1c7q2dD.cjs +142 -0
- package/dist/{peerTools-CxmrKnfV.mjs → peerTools-CWKzcQ7u.mjs} +60 -10
- package/dist/{peerTools-DtGKWli5.cjs → peerTools-DRQETXaz.cjs} +60 -9
- package/dist/{persistence-DXbKOHxl.cjs → persistence-BegE7NPa.cjs} +14 -3
- package/dist/{persistence-C_tYtOqK.mjs → persistence-Cr-wutZ4.mjs} +14 -4
- package/dist/{piRunnerArgs-BVRZe2AR.cjs → piRunnerArgs-Cs-378Vz.cjs} +8 -2
- package/dist/{piRunnerArgs-BpHc-JZl.mjs → piRunnerArgs-DwvM_yWA.mjs} +7 -1
- package/dist/{piRuntime-D7eio8Ix.cjs → piRuntime-BG-1td_n.cjs} +2 -2
- package/dist/{piRuntime-DOdGF395.mjs → piRuntime-Bue5mnlc.mjs} +2 -2
- package/dist/{piTerminal-dpxz4Q8D.mjs → piTerminal-B5x9X5yV.mjs} +18 -18
- package/dist/{piTerminal-y_PRo2NY.cjs → piTerminal-G4z-xVyy.cjs} +18 -18
- package/dist/processTreeSnapshot-CuLJDNC-.mjs +101 -0
- package/dist/processTreeSnapshot-mDbnuojn.cjs +105 -0
- package/dist/prompt-BOouDaTM.mjs +99 -0
- package/dist/prompt-lgF9IE82.cjs +105 -0
- package/dist/{attachmentLimits-Di1Z93lN.mjs → pushNotifications-BdFjDjQe.mjs} +303 -3
- package/dist/{attachmentLimits-DtFqqiwR.cjs → pushNotifications-DaLQUyi0.cjs} +304 -2
- package/dist/{index-DFPT4HOO.cjs → query-Ctfg-5gy.cjs} +25 -5
- package/dist/{index-CEjJnq05.mjs → query-DYP_W1wp.mjs} +26 -3
- package/dist/{rateLimitWindows-DYHDGuzQ.mjs → rateLimitWindows-CuEqk_0g.mjs} +1 -1
- package/dist/{rateLimitWindows-DFnMU2Vt.cjs → rateLimitWindows-Dj_8voBK.cjs} +1 -1
- package/dist/{registerCommonHandlers-D8OMpBbQ.mjs → registerCommonHandlers-BAlP7SGc.mjs} +2 -2
- package/dist/{registerCommonHandlers-60VuTkdg.cjs → registerCommonHandlers-Cj084Sg7.cjs} +2 -2
- package/dist/{registerKillSessionHandler-Drhf7-Vz.mjs → registerKillSessionHandler-PD0jWtQo.mjs} +6 -6
- package/dist/{registerKillSessionHandler-pqChBKwO.cjs → registerKillSessionHandler-qMju0ZfF.cjs} +6 -6
- package/dist/{remoteSessionClient-B7NvjHD3.cjs → remoteSessionClient-B7i7MkYV.cjs} +5 -5
- package/dist/{remoteSessionClient-D01Hso2-.mjs → remoteSessionClient-Bn2qu5C5.mjs} +5 -5
- package/dist/{reportProgressTool-Du_zAK4h.cjs → reportProgressTool-CM1JFAHg.cjs} +84 -2
- package/dist/{reportProgressTool-B203EZCR.mjs → reportProgressTool-gHItlSzz.mjs} +82 -3
- package/dist/{resources-JDPugcDq.cjs → resources-CvIlkzpP.cjs} +30 -0
- package/dist/{resources-BdFBQi8r.mjs → resources-y9jfyO-_.mjs} +30 -0
- package/dist/{run-DX4Zs3Ug.mjs → run-BM4TxiyN.mjs} +249 -45
- package/dist/{run-DZ5jU53c.cjs → run-CNXwIe0A.cjs} +263 -59
- package/dist/{runClaude-ClRhHpwR.cjs → runClaude-CWhj2V4Q.cjs} +37 -41
- package/dist/{runClaude-CgPHXP0L.mjs → runClaude-C_3I8hvR.mjs} +37 -41
- package/dist/{runClaudeDeps-D2v_WDSL.cjs → runClaudeDeps-B81cOKnH.cjs} +295 -157
- package/dist/{runClaudeDeps-Dz2iydq4.mjs → runClaudeDeps-QGrOeDe2.mjs} +295 -160
- package/dist/{runGemini-DBXxpoY8.mjs → runGemini-BEdWEZLR.mjs} +61 -55
- package/dist/{runGemini-BtZqGFkp.cjs → runGemini-CgRLYbt5.cjs} +61 -55
- package/dist/{runOpenClaw-D8q8G57u.cjs → runOpenClaw-C1NVmzOL.cjs} +19 -19
- package/dist/{runOpenClaw-BOHpzCEU.mjs → runOpenClaw-DdQZAYj1.mjs} +19 -19
- package/dist/{sandbox-C452Vrsc.mjs → sandbox-DjQUdCMG.mjs} +5 -5
- package/dist/{sandbox-Cu9mMzjx.cjs → sandbox-nocIjliq.cjs} +5 -5
- package/dist/selfCheck-CjCF4C3v.mjs +85 -0
- package/dist/{selfCheck-gKa3uVr1.cjs → selfCheck-DCt4Uzbq.cjs} +36 -35
- package/dist/{send-B8HARi7x.mjs → send-Ct7X4pPU.mjs} +9 -9
- package/dist/{send-2Vb5eppI.cjs → send-Dydf_hwZ.cjs} +9 -9
- package/dist/{server-Db9Wuam3.cjs → server-CosABFbd.cjs} +7 -7
- package/dist/{server-BBWCIZyS.mjs → server-DTQGZMxh.mjs} +5 -5
- package/dist/{sessionLock-6qL_N6Rn.cjs → sessionLock-DokGab2R.cjs} +16 -3
- package/dist/{sessionLock-ZfvFVdUi.mjs → sessionLock-WYIyaVO4.mjs} +16 -4
- package/dist/{sessionOps-CdgbEJgf.mjs → sessionOps-BIGgRube.mjs} +11 -6
- package/dist/{sessionOps-Dmt7WUUs.cjs → sessionOps-S-qPBLFf.cjs} +11 -6
- package/dist/{sessionScanner-CQL_WSaC.cjs → sessionScanner-CIMM2hvZ.cjs} +3 -3
- package/dist/{sessionScanner-CNVaSNOn.mjs → sessionScanner-o5hnMi5e.mjs} +3 -3
- package/dist/{sessions-DTomHfFg.mjs → sessions-BJHEZpi2.mjs} +40 -18
- package/dist/{sessions-BJblG_Hx.cjs → sessions-JchI1w3z.cjs} +40 -17
- package/dist/{setupOfflineReconnection-DVA0VpQL.cjs → setupOfflineReconnection-CNiAt5ZP.cjs} +2 -2
- package/dist/{setupOfflineReconnection-C5trsV-j.mjs → setupOfflineReconnection-DMiBO2y9.mjs} +2 -2
- package/dist/{spawn-DRyNAqD8.cjs → spawn-6PD7nnoC.cjs} +49 -18
- package/dist/{spawn-CQJFgoOq.mjs → spawn-DgvUNYEo.mjs} +49 -18
- package/dist/{spawnAgents-CCjJifAW.cjs → spawnAgents-DsXgegHM.cjs} +37 -1
- package/dist/spawnAgents-P006Hqio.mjs +79 -0
- package/dist/{spawnHappyCLI-B_0RWxD4.mjs → spawnHappyCLI-CCOrEtf9.mjs} +1 -1
- package/dist/{spawnHappyCLI-ChniczJ5.cjs → spawnHappyCLI-Dywezwk6.cjs} +1 -1
- package/dist/{specialCommands-DkdFJi4N.mjs → specialCommands-DPcd9edP.mjs} +3 -3
- package/dist/{specialCommands-DbntVs0d.cjs → specialCommands-QxPpkGKf.cjs} +3 -3
- package/dist/{startFileWatcher-UQyTSRAP.mjs → startFileWatcher-DghDOCO4.mjs} +1 -1
- package/dist/{startFileWatcher-C292fhra.cjs → startFileWatcher-RECH5qY8.cjs} +1 -1
- package/dist/{streamRelay-_qCd873P.mjs → streamRelay-DMV_TXfS.mjs} +1 -1
- package/dist/{streamRelay-Cx01enfe.cjs → streamRelay-DlUWKUpo.cjs} +1 -1
- package/dist/{sync-C3p7-KLn.mjs → sync-CSe0Rf45.mjs} +1 -1
- package/dist/{sync-C7sxoUYG.cjs → sync-D23jbqVa.cjs} +1 -1
- package/dist/{systemPrompt-DtibzbRU.cjs → systemPrompt-BOy4kU4P.cjs} +4 -3
- package/dist/{systemPrompt-CdHOlyVW.mjs → systemPrompt-CFNKnh65.mjs} +4 -3
- package/dist/{teams-ujXr3AFn.mjs → teams-DyY669f0.mjs} +9 -9
- package/dist/{teams-D7O7TpVU.cjs → teams-Ov2BDT-A.cjs} +9 -9
- package/dist/{time-yEL6wHUF.mjs → time-65DcU6Jx.mjs} +1 -1
- package/dist/{time-Dg5tVB8S.cjs → time-CrwIMHta.cjs} +1 -1
- package/dist/{titleGenerator-BMEaDTwU.cjs → titleGenerator-CS_rh2_J.cjs} +9 -8
- package/dist/{titleGenerator-Dr-BtjzO.mjs → titleGenerator-CiAMxf7s.mjs} +9 -8
- package/dist/{todo-CvJe4M2C.mjs → todo-BDONw0sK.mjs} +7 -7
- package/dist/{todo-CUcFamGs.cjs → todo-KY-okGii.cjs} +7 -7
- package/dist/{tools-BrM3bZW5.mjs → tools-D8-PnZEG.mjs} +1 -1
- package/dist/{tools-DDKTB5aQ.cjs → tools-_w52DZG6.cjs} +1 -1
- package/dist/{uninstall-7oLuhYIu.cjs → uninstall-8vnLN-IE.cjs} +3 -3
- package/dist/{uninstall-CEcMMQGz.mjs → uninstall-_fjGRP9b.mjs} +3 -3
- package/dist/webPanels-B2_C2-3g.mjs +49 -0
- package/dist/webPanels-FCgFKvVe.cjs +53 -0
- package/package.json +7 -7
- package/dist/selfCheck-BAvqBwBR.mjs +0 -84
- package/dist/sessionModeFile-CWVq8AT9.mjs +0 -32
- package/dist/sessionModeFile-CsLtn_PL.cjs +0 -36
- package/dist/spawnAgents-BjtmjBvP.mjs +0 -45
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import { l as logger } from './logger-
|
|
5
|
-
import { d as delay } from './time-
|
|
4
|
+
import { l as logger } from './logger-BtVhHnD8.mjs';
|
|
5
|
+
import { d as delay } from './time-65DcU6Jx.mjs';
|
|
6
6
|
import { c as contentLogMetadata, e as errorLogMetadata } from './contentLogMetadata-BlWI0egu.mjs';
|
|
7
7
|
import { r as readableStderrTail, a as appendStderrRing, s as stopProcessGracefully, k as killProcessTree } from './processTree-CP5IvQ2Z.mjs';
|
|
8
|
-
import { p as packageJson } from './package-
|
|
8
|
+
import { p as packageJson } from './package-BPPebGQF.mjs';
|
|
9
9
|
|
|
10
10
|
function acpImageBlocks(attachments, supportsImages) {
|
|
11
11
|
return attachments.filter((file) => ["image/jpeg", "image/png", "image/gif", "image/webp"].includes(file.mimeType)).map((file) => {
|
|
@@ -539,6 +539,51 @@ function handleThinkingUpdate(update, ctx) {
|
|
|
539
539
|
return { handled: true };
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
+
const CHOICE = /^choice-\d+$/;
|
|
543
|
+
function readPiExtensionDialog(params) {
|
|
544
|
+
const toolCall = params.toolCall;
|
|
545
|
+
if (!toolCall || typeof toolCall.toolCallId !== "string" || !toolCall.toolCallId.startsWith("pi-ui-")) return null;
|
|
546
|
+
const method = toolCall.rawInput?.method;
|
|
547
|
+
const options = params.options ?? [];
|
|
548
|
+
if (method === "select" && options.length > 0 && options.every((o) => typeof o.optionId === "string" && CHOICE.test(o.optionId))) {
|
|
549
|
+
const title = typeof toolCall.rawInput?.title === "string" ? toolCall.rawInput.title : toolCall.title;
|
|
550
|
+
return {
|
|
551
|
+
kind: "select",
|
|
552
|
+
question: typeof title === "string" && title.trim() ? title : "pi asks",
|
|
553
|
+
options: options.map((o) => ({ optionId: o.optionId, label: String(o.name ?? o.optionId) }))
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
if (method === "confirm" && options.some((o) => o.optionId === "yes") && options.some((o) => o.optionId === "no")) {
|
|
557
|
+
return { kind: "confirm" };
|
|
558
|
+
}
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
function piSelectQuestionInput(dialog, message) {
|
|
562
|
+
return {
|
|
563
|
+
questions: [{
|
|
564
|
+
question: dialog.question,
|
|
565
|
+
header: dialog.question.length > 30 ? `${dialog.question.slice(0, 29)}\u2026` : dialog.question,
|
|
566
|
+
options: dialog.options.map((o) => ({ label: o.label, description: "" })),
|
|
567
|
+
multiSelect: false
|
|
568
|
+
}],
|
|
569
|
+
...typeof message === "string" && message.trim() ? { message } : {}
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function piDialogOutcome(dialog, result) {
|
|
573
|
+
const approved = result.decision === "approved" || result.decision === "approved_for_session";
|
|
574
|
+
if (dialog.kind === "confirm") return { outcome: "selected", optionId: approved ? "yes" : "no" };
|
|
575
|
+
if (!approved) return { outcome: "cancelled" };
|
|
576
|
+
const answers = result.updatedInput?.answers;
|
|
577
|
+
const picked = answers && typeof answers === "object" ? answers[dialog.question] : void 0;
|
|
578
|
+
if (typeof picked !== "string") return { outcome: "cancelled" };
|
|
579
|
+
const match = dialog.options.find((o) => o.label === picked);
|
|
580
|
+
return match ? { outcome: "selected", optionId: match.optionId } : { outcome: "cancelled" };
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const LOAD_SESSION_TIMEOUT_MS = 6e4;
|
|
584
|
+
function isReplayedConversationUpdate(updateType) {
|
|
585
|
+
return updateType === "user_message_chunk" || updateType === "agent_message_chunk" || updateType === "agent_thought_chunk" || updateType === "tool_call" || updateType === "tool_call_update" || updateType === "plan";
|
|
586
|
+
}
|
|
542
587
|
const RETRY_CONFIG = {
|
|
543
588
|
/** Maximum number of retry attempts for init/newSession */
|
|
544
589
|
maxAttempts: 3,
|
|
@@ -655,6 +700,13 @@ class AcpBackend {
|
|
|
655
700
|
process = null;
|
|
656
701
|
connection = null;
|
|
657
702
|
acpSessionId = null;
|
|
703
|
+
/**
|
|
704
|
+
* B-633: true while `session/load` runs. pi-acp replays the whole earlier
|
|
705
|
+
* conversation as user/agent/tool updates before it answers; the web already
|
|
706
|
+
* holds that transcript, so those updates are dropped (config, mode, model
|
|
707
|
+
* and command updates still apply).
|
|
708
|
+
*/
|
|
709
|
+
replayingHistory = false;
|
|
658
710
|
disposed = false;
|
|
659
711
|
/** Track active tool calls to prevent duplicate events */
|
|
660
712
|
activeToolCalls = /* @__PURE__ */ new Set();
|
|
@@ -730,7 +782,7 @@ class AcpBackend {
|
|
|
730
782
|
}
|
|
731
783
|
}
|
|
732
784
|
}
|
|
733
|
-
async startSession(initialPrompt) {
|
|
785
|
+
async startSession(initialPrompt, options = {}) {
|
|
734
786
|
if (this.disposed) {
|
|
735
787
|
throw new Error("Backend has been disposed");
|
|
736
788
|
}
|
|
@@ -906,21 +958,26 @@ class AcpBackend {
|
|
|
906
958
|
let toolName = resolved.toolName;
|
|
907
959
|
const toolCallId = resolved.toolCallId;
|
|
908
960
|
const permissionId = toolCallId;
|
|
909
|
-
|
|
961
|
+
let input = resolved.input;
|
|
962
|
+
const piDialog = readPiExtensionDialog(extendedParams);
|
|
910
963
|
const context = {
|
|
911
964
|
recentPromptHadChangeTitle: this.recentPromptHadChangeTitle,
|
|
912
965
|
toolCallCountSincePrompt: this.toolCallCountSincePrompt
|
|
913
966
|
};
|
|
914
967
|
toolName = this.transport.determineToolName?.(toolName, toolCallId, input, context) ?? toolName;
|
|
968
|
+
if (piDialog?.kind === "select") {
|
|
969
|
+
toolName = "AskUserQuestion";
|
|
970
|
+
input = piSelectQuestionInput(piDialog, resolved.input.message);
|
|
971
|
+
}
|
|
915
972
|
if (toolName !== (toolCall?.kind || toolCall?.toolName || extendedParams.kind || "Unknown tool")) {
|
|
916
973
|
logger.debug(`[AcpBackend] Inferred tool name for toolCallId: ${toolCallId}`);
|
|
917
974
|
}
|
|
918
975
|
this.toolCallCountSincePrompt++;
|
|
919
|
-
const
|
|
976
|
+
const options2 = extendedParams.options || [];
|
|
920
977
|
logger.debug("[AcpBackend] Permission request metadata:", {
|
|
921
978
|
hasToolCall: !!toolCall,
|
|
922
979
|
toolCallId,
|
|
923
|
-
optionCount:
|
|
980
|
+
optionCount: options2.length,
|
|
924
981
|
input: contentLogMetadata(input)
|
|
925
982
|
});
|
|
926
983
|
this.emit({
|
|
@@ -933,7 +990,7 @@ class AcpBackend {
|
|
|
933
990
|
toolCallId,
|
|
934
991
|
toolName,
|
|
935
992
|
input,
|
|
936
|
-
options:
|
|
993
|
+
options: options2.map((opt) => ({
|
|
937
994
|
id: opt.optionId,
|
|
938
995
|
name: opt.name,
|
|
939
996
|
kind: opt.kind
|
|
@@ -947,20 +1004,31 @@ class AcpBackend {
|
|
|
947
1004
|
toolName,
|
|
948
1005
|
input
|
|
949
1006
|
);
|
|
1007
|
+
if (piDialog) {
|
|
1008
|
+
const answer = piDialogOutcome(piDialog, result);
|
|
1009
|
+
const answered = answer.outcome === "selected" && answer.optionId !== "no";
|
|
1010
|
+
this.emit({
|
|
1011
|
+
type: "tool-result",
|
|
1012
|
+
toolName,
|
|
1013
|
+
result: { status: answered ? "approved" : "denied", decision: result.decision },
|
|
1014
|
+
callId: permissionId
|
|
1015
|
+
});
|
|
1016
|
+
return { outcome: answer };
|
|
1017
|
+
}
|
|
950
1018
|
let optionId = "cancel";
|
|
951
1019
|
if (result.decision === "approved" || result.decision === "approved_for_session") {
|
|
952
|
-
const proceedOnceOption2 =
|
|
1020
|
+
const proceedOnceOption2 = options2.find(
|
|
953
1021
|
(opt) => opt.optionId === "proceed_once" || opt.name?.toLowerCase().includes("once")
|
|
954
1022
|
);
|
|
955
|
-
const proceedAlwaysOption =
|
|
1023
|
+
const proceedAlwaysOption = options2.find(
|
|
956
1024
|
(opt) => opt.optionId === "proceed_always" || opt.name?.toLowerCase().includes("always")
|
|
957
1025
|
);
|
|
958
1026
|
if (result.decision === "approved_for_session" && proceedAlwaysOption) {
|
|
959
1027
|
optionId = proceedAlwaysOption.optionId || "proceed_always";
|
|
960
1028
|
} else if (proceedOnceOption2) {
|
|
961
1029
|
optionId = proceedOnceOption2.optionId || "proceed_once";
|
|
962
|
-
} else if (
|
|
963
|
-
optionId =
|
|
1030
|
+
} else if (options2.length > 0) {
|
|
1031
|
+
optionId = options2[0].optionId || "proceed_once";
|
|
964
1032
|
}
|
|
965
1033
|
this.emit({
|
|
966
1034
|
type: "tool-result",
|
|
@@ -969,7 +1037,7 @@ class AcpBackend {
|
|
|
969
1037
|
callId: permissionId
|
|
970
1038
|
});
|
|
971
1039
|
} else {
|
|
972
|
-
const cancelOption =
|
|
1040
|
+
const cancelOption = options2.find(
|
|
973
1041
|
(opt) => opt.optionId === "cancel" || opt.name?.toLowerCase().includes("cancel")
|
|
974
1042
|
);
|
|
975
1043
|
if (cancelOption) {
|
|
@@ -988,10 +1056,10 @@ class AcpBackend {
|
|
|
988
1056
|
return { outcome: { outcome: "selected", optionId: "cancel" } };
|
|
989
1057
|
}
|
|
990
1058
|
}
|
|
991
|
-
const proceedOnceOption =
|
|
1059
|
+
const proceedOnceOption = options2.find(
|
|
992
1060
|
(opt) => opt.optionId === "proceed_once" || typeof opt.name === "string" && opt.name.toLowerCase().includes("once")
|
|
993
1061
|
);
|
|
994
|
-
const defaultOptionId = proceedOnceOption?.optionId || (
|
|
1062
|
+
const defaultOptionId = proceedOnceOption?.optionId || (options2.length > 0 && options2[0].optionId ? options2[0].optionId : "proceed_once");
|
|
995
1063
|
return { outcome: { outcome: "selected", optionId: defaultOptionId } };
|
|
996
1064
|
}
|
|
997
1065
|
};
|
|
@@ -1072,6 +1140,50 @@ class AcpBackend {
|
|
|
1072
1140
|
cwd: this.options.cwd,
|
|
1073
1141
|
mcpServers
|
|
1074
1142
|
};
|
|
1143
|
+
let resumed;
|
|
1144
|
+
let loadFailure;
|
|
1145
|
+
if (options.loadSessionId) {
|
|
1146
|
+
if (initializeResponse.agentCapabilities?.loadSession !== true) {
|
|
1147
|
+
resumed = "fresh";
|
|
1148
|
+
loadFailure = `${this.transport.agentName} cannot reopen sessions`;
|
|
1149
|
+
} else {
|
|
1150
|
+
const loadRequest = { ...newSessionRequest, sessionId: options.loadSessionId };
|
|
1151
|
+
let timeoutHandle = null;
|
|
1152
|
+
this.replayingHistory = true;
|
|
1153
|
+
try {
|
|
1154
|
+
const loaded = await Promise.race([
|
|
1155
|
+
startupFailurePromise,
|
|
1156
|
+
this.connection.loadSession(loadRequest),
|
|
1157
|
+
new Promise((_, reject) => {
|
|
1158
|
+
timeoutHandle = setTimeout(() => reject(new Error(`Load session timeout after ${LOAD_SESSION_TIMEOUT_MS}ms`)), LOAD_SESSION_TIMEOUT_MS);
|
|
1159
|
+
})
|
|
1160
|
+
]);
|
|
1161
|
+
this.acpSessionId = options.loadSessionId;
|
|
1162
|
+
resumed = "loaded";
|
|
1163
|
+
logger.debug(`[AcpBackend] Session reopened: ${this.acpSessionId}`);
|
|
1164
|
+
this.emitInitialSessionMetadata(loaded);
|
|
1165
|
+
} catch (error) {
|
|
1166
|
+
if (startupFailure && error === startupFailure) throw error;
|
|
1167
|
+
resumed = "fresh";
|
|
1168
|
+
const message = error?.message;
|
|
1169
|
+
loadFailure = typeof message === "string" ? message : String(error);
|
|
1170
|
+
logger.debug(`[AcpBackend] Reopening session ${options.loadSessionId} failed; starting a new one: ${loadFailure}`);
|
|
1171
|
+
} finally {
|
|
1172
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
1173
|
+
this.replayingHistory = false;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
if (resumed === "loaded") {
|
|
1178
|
+
this.emitIdleStatus();
|
|
1179
|
+
if (initialPrompt) {
|
|
1180
|
+
this.sendPrompt(sessionId, initialPrompt).catch((error) => {
|
|
1181
|
+
logger.debug("[AcpBackend] Error sending initial prompt:", errorLogMetadata(error));
|
|
1182
|
+
this.emit({ type: "status", status: "error", detail: String(error) });
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
return { sessionId, agentSessionId: this.acpSessionId, resumed };
|
|
1186
|
+
}
|
|
1075
1187
|
logger.debug(`[AcpBackend] Creating new session...`);
|
|
1076
1188
|
const sessionResponse = await withRetry(
|
|
1077
1189
|
async () => {
|
|
@@ -1122,7 +1234,11 @@ class AcpBackend {
|
|
|
1122
1234
|
this.emit({ type: "status", status: "error", detail: String(error) });
|
|
1123
1235
|
});
|
|
1124
1236
|
}
|
|
1125
|
-
return {
|
|
1237
|
+
return {
|
|
1238
|
+
sessionId,
|
|
1239
|
+
agentSessionId: this.acpSessionId ?? void 0,
|
|
1240
|
+
...resumed ? { resumed, ...loadFailure ? { loadFailure } : {} } : {}
|
|
1241
|
+
};
|
|
1126
1242
|
} catch (error) {
|
|
1127
1243
|
logger.debug("[AcpBackend] Error starting session:", errorLogMetadata(error));
|
|
1128
1244
|
if (!startupStatusErrorEmitted) {
|
|
@@ -1208,6 +1324,9 @@ class AcpBackend {
|
|
|
1208
1324
|
`Incoming session update from ${this.options.agentName}: type=${sessionUpdateType ?? "unknown"} payloadBytes=${String(updateMetadata.payloadBytes ?? "unknown")}`
|
|
1209
1325
|
);
|
|
1210
1326
|
}
|
|
1327
|
+
if (this.replayingHistory && isReplayedConversationUpdate(updateType)) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1211
1330
|
const ctx = this.createHandlerContext();
|
|
1212
1331
|
if (sessionUpdateType === "agent_message_chunk") {
|
|
1213
1332
|
handleAgentMessageChunk(update, ctx);
|
|
@@ -3,11 +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-C1GWx3gi.cjs');
|
|
7
|
+
var time = require('./time-CrwIMHta.cjs');
|
|
8
8
|
var contentLogMetadata = require('./contentLogMetadata-ZSFk_NjQ.cjs');
|
|
9
9
|
var processTree = require('./processTree-CMHWlVse.cjs');
|
|
10
|
-
var _package = require('./package-
|
|
10
|
+
var _package = require('./package-SgqTYsjn.cjs');
|
|
11
11
|
|
|
12
12
|
function acpImageBlocks(attachments, supportsImages) {
|
|
13
13
|
return attachments.filter((file) => ["image/jpeg", "image/png", "image/gif", "image/webp"].includes(file.mimeType)).map((file) => {
|
|
@@ -541,6 +541,51 @@ function handleThinkingUpdate(update, ctx) {
|
|
|
541
541
|
return { handled: true };
|
|
542
542
|
}
|
|
543
543
|
|
|
544
|
+
const CHOICE = /^choice-\d+$/;
|
|
545
|
+
function readPiExtensionDialog(params) {
|
|
546
|
+
const toolCall = params.toolCall;
|
|
547
|
+
if (!toolCall || typeof toolCall.toolCallId !== "string" || !toolCall.toolCallId.startsWith("pi-ui-")) return null;
|
|
548
|
+
const method = toolCall.rawInput?.method;
|
|
549
|
+
const options = params.options ?? [];
|
|
550
|
+
if (method === "select" && options.length > 0 && options.every((o) => typeof o.optionId === "string" && CHOICE.test(o.optionId))) {
|
|
551
|
+
const title = typeof toolCall.rawInput?.title === "string" ? toolCall.rawInput.title : toolCall.title;
|
|
552
|
+
return {
|
|
553
|
+
kind: "select",
|
|
554
|
+
question: typeof title === "string" && title.trim() ? title : "pi asks",
|
|
555
|
+
options: options.map((o) => ({ optionId: o.optionId, label: String(o.name ?? o.optionId) }))
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
if (method === "confirm" && options.some((o) => o.optionId === "yes") && options.some((o) => o.optionId === "no")) {
|
|
559
|
+
return { kind: "confirm" };
|
|
560
|
+
}
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
function piSelectQuestionInput(dialog, message) {
|
|
564
|
+
return {
|
|
565
|
+
questions: [{
|
|
566
|
+
question: dialog.question,
|
|
567
|
+
header: dialog.question.length > 30 ? `${dialog.question.slice(0, 29)}\u2026` : dialog.question,
|
|
568
|
+
options: dialog.options.map((o) => ({ label: o.label, description: "" })),
|
|
569
|
+
multiSelect: false
|
|
570
|
+
}],
|
|
571
|
+
...typeof message === "string" && message.trim() ? { message } : {}
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
function piDialogOutcome(dialog, result) {
|
|
575
|
+
const approved = result.decision === "approved" || result.decision === "approved_for_session";
|
|
576
|
+
if (dialog.kind === "confirm") return { outcome: "selected", optionId: approved ? "yes" : "no" };
|
|
577
|
+
if (!approved) return { outcome: "cancelled" };
|
|
578
|
+
const answers = result.updatedInput?.answers;
|
|
579
|
+
const picked = answers && typeof answers === "object" ? answers[dialog.question] : void 0;
|
|
580
|
+
if (typeof picked !== "string") return { outcome: "cancelled" };
|
|
581
|
+
const match = dialog.options.find((o) => o.label === picked);
|
|
582
|
+
return match ? { outcome: "selected", optionId: match.optionId } : { outcome: "cancelled" };
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const LOAD_SESSION_TIMEOUT_MS = 6e4;
|
|
586
|
+
function isReplayedConversationUpdate(updateType) {
|
|
587
|
+
return updateType === "user_message_chunk" || updateType === "agent_message_chunk" || updateType === "agent_thought_chunk" || updateType === "tool_call" || updateType === "tool_call_update" || updateType === "plan";
|
|
588
|
+
}
|
|
544
589
|
const RETRY_CONFIG = {
|
|
545
590
|
/** Maximum number of retry attempts for init/newSession */
|
|
546
591
|
maxAttempts: 3,
|
|
@@ -657,6 +702,13 @@ class AcpBackend {
|
|
|
657
702
|
process = null;
|
|
658
703
|
connection = null;
|
|
659
704
|
acpSessionId = null;
|
|
705
|
+
/**
|
|
706
|
+
* B-633: true while `session/load` runs. pi-acp replays the whole earlier
|
|
707
|
+
* conversation as user/agent/tool updates before it answers; the web already
|
|
708
|
+
* holds that transcript, so those updates are dropped (config, mode, model
|
|
709
|
+
* and command updates still apply).
|
|
710
|
+
*/
|
|
711
|
+
replayingHistory = false;
|
|
660
712
|
disposed = false;
|
|
661
713
|
/** Track active tool calls to prevent duplicate events */
|
|
662
714
|
activeToolCalls = /* @__PURE__ */ new Set();
|
|
@@ -732,7 +784,7 @@ class AcpBackend {
|
|
|
732
784
|
}
|
|
733
785
|
}
|
|
734
786
|
}
|
|
735
|
-
async startSession(initialPrompt) {
|
|
787
|
+
async startSession(initialPrompt, options = {}) {
|
|
736
788
|
if (this.disposed) {
|
|
737
789
|
throw new Error("Backend has been disposed");
|
|
738
790
|
}
|
|
@@ -908,21 +960,26 @@ class AcpBackend {
|
|
|
908
960
|
let toolName = resolved.toolName;
|
|
909
961
|
const toolCallId = resolved.toolCallId;
|
|
910
962
|
const permissionId = toolCallId;
|
|
911
|
-
|
|
963
|
+
let input = resolved.input;
|
|
964
|
+
const piDialog = readPiExtensionDialog(extendedParams);
|
|
912
965
|
const context = {
|
|
913
966
|
recentPromptHadChangeTitle: this.recentPromptHadChangeTitle,
|
|
914
967
|
toolCallCountSincePrompt: this.toolCallCountSincePrompt
|
|
915
968
|
};
|
|
916
969
|
toolName = this.transport.determineToolName?.(toolName, toolCallId, input, context) ?? toolName;
|
|
970
|
+
if (piDialog?.kind === "select") {
|
|
971
|
+
toolName = "AskUserQuestion";
|
|
972
|
+
input = piSelectQuestionInput(piDialog, resolved.input.message);
|
|
973
|
+
}
|
|
917
974
|
if (toolName !== (toolCall?.kind || toolCall?.toolName || extendedParams.kind || "Unknown tool")) {
|
|
918
975
|
logger.logger.debug(`[AcpBackend] Inferred tool name for toolCallId: ${toolCallId}`);
|
|
919
976
|
}
|
|
920
977
|
this.toolCallCountSincePrompt++;
|
|
921
|
-
const
|
|
978
|
+
const options2 = extendedParams.options || [];
|
|
922
979
|
logger.logger.debug("[AcpBackend] Permission request metadata:", {
|
|
923
980
|
hasToolCall: !!toolCall,
|
|
924
981
|
toolCallId,
|
|
925
|
-
optionCount:
|
|
982
|
+
optionCount: options2.length,
|
|
926
983
|
input: contentLogMetadata.contentLogMetadata(input)
|
|
927
984
|
});
|
|
928
985
|
this.emit({
|
|
@@ -935,7 +992,7 @@ class AcpBackend {
|
|
|
935
992
|
toolCallId,
|
|
936
993
|
toolName,
|
|
937
994
|
input,
|
|
938
|
-
options:
|
|
995
|
+
options: options2.map((opt) => ({
|
|
939
996
|
id: opt.optionId,
|
|
940
997
|
name: opt.name,
|
|
941
998
|
kind: opt.kind
|
|
@@ -949,20 +1006,31 @@ class AcpBackend {
|
|
|
949
1006
|
toolName,
|
|
950
1007
|
input
|
|
951
1008
|
);
|
|
1009
|
+
if (piDialog) {
|
|
1010
|
+
const answer = piDialogOutcome(piDialog, result);
|
|
1011
|
+
const answered = answer.outcome === "selected" && answer.optionId !== "no";
|
|
1012
|
+
this.emit({
|
|
1013
|
+
type: "tool-result",
|
|
1014
|
+
toolName,
|
|
1015
|
+
result: { status: answered ? "approved" : "denied", decision: result.decision },
|
|
1016
|
+
callId: permissionId
|
|
1017
|
+
});
|
|
1018
|
+
return { outcome: answer };
|
|
1019
|
+
}
|
|
952
1020
|
let optionId = "cancel";
|
|
953
1021
|
if (result.decision === "approved" || result.decision === "approved_for_session") {
|
|
954
|
-
const proceedOnceOption2 =
|
|
1022
|
+
const proceedOnceOption2 = options2.find(
|
|
955
1023
|
(opt) => opt.optionId === "proceed_once" || opt.name?.toLowerCase().includes("once")
|
|
956
1024
|
);
|
|
957
|
-
const proceedAlwaysOption =
|
|
1025
|
+
const proceedAlwaysOption = options2.find(
|
|
958
1026
|
(opt) => opt.optionId === "proceed_always" || opt.name?.toLowerCase().includes("always")
|
|
959
1027
|
);
|
|
960
1028
|
if (result.decision === "approved_for_session" && proceedAlwaysOption) {
|
|
961
1029
|
optionId = proceedAlwaysOption.optionId || "proceed_always";
|
|
962
1030
|
} else if (proceedOnceOption2) {
|
|
963
1031
|
optionId = proceedOnceOption2.optionId || "proceed_once";
|
|
964
|
-
} else if (
|
|
965
|
-
optionId =
|
|
1032
|
+
} else if (options2.length > 0) {
|
|
1033
|
+
optionId = options2[0].optionId || "proceed_once";
|
|
966
1034
|
}
|
|
967
1035
|
this.emit({
|
|
968
1036
|
type: "tool-result",
|
|
@@ -971,7 +1039,7 @@ class AcpBackend {
|
|
|
971
1039
|
callId: permissionId
|
|
972
1040
|
});
|
|
973
1041
|
} else {
|
|
974
|
-
const cancelOption =
|
|
1042
|
+
const cancelOption = options2.find(
|
|
975
1043
|
(opt) => opt.optionId === "cancel" || opt.name?.toLowerCase().includes("cancel")
|
|
976
1044
|
);
|
|
977
1045
|
if (cancelOption) {
|
|
@@ -990,10 +1058,10 @@ class AcpBackend {
|
|
|
990
1058
|
return { outcome: { outcome: "selected", optionId: "cancel" } };
|
|
991
1059
|
}
|
|
992
1060
|
}
|
|
993
|
-
const proceedOnceOption =
|
|
1061
|
+
const proceedOnceOption = options2.find(
|
|
994
1062
|
(opt) => opt.optionId === "proceed_once" || typeof opt.name === "string" && opt.name.toLowerCase().includes("once")
|
|
995
1063
|
);
|
|
996
|
-
const defaultOptionId = proceedOnceOption?.optionId || (
|
|
1064
|
+
const defaultOptionId = proceedOnceOption?.optionId || (options2.length > 0 && options2[0].optionId ? options2[0].optionId : "proceed_once");
|
|
997
1065
|
return { outcome: { outcome: "selected", optionId: defaultOptionId } };
|
|
998
1066
|
}
|
|
999
1067
|
};
|
|
@@ -1074,6 +1142,50 @@ class AcpBackend {
|
|
|
1074
1142
|
cwd: this.options.cwd,
|
|
1075
1143
|
mcpServers
|
|
1076
1144
|
};
|
|
1145
|
+
let resumed;
|
|
1146
|
+
let loadFailure;
|
|
1147
|
+
if (options.loadSessionId) {
|
|
1148
|
+
if (initializeResponse.agentCapabilities?.loadSession !== true) {
|
|
1149
|
+
resumed = "fresh";
|
|
1150
|
+
loadFailure = `${this.transport.agentName} cannot reopen sessions`;
|
|
1151
|
+
} else {
|
|
1152
|
+
const loadRequest = { ...newSessionRequest, sessionId: options.loadSessionId };
|
|
1153
|
+
let timeoutHandle = null;
|
|
1154
|
+
this.replayingHistory = true;
|
|
1155
|
+
try {
|
|
1156
|
+
const loaded = await Promise.race([
|
|
1157
|
+
startupFailurePromise,
|
|
1158
|
+
this.connection.loadSession(loadRequest),
|
|
1159
|
+
new Promise((_, reject) => {
|
|
1160
|
+
timeoutHandle = setTimeout(() => reject(new Error(`Load session timeout after ${LOAD_SESSION_TIMEOUT_MS}ms`)), LOAD_SESSION_TIMEOUT_MS);
|
|
1161
|
+
})
|
|
1162
|
+
]);
|
|
1163
|
+
this.acpSessionId = options.loadSessionId;
|
|
1164
|
+
resumed = "loaded";
|
|
1165
|
+
logger.logger.debug(`[AcpBackend] Session reopened: ${this.acpSessionId}`);
|
|
1166
|
+
this.emitInitialSessionMetadata(loaded);
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
if (startupFailure && error === startupFailure) throw error;
|
|
1169
|
+
resumed = "fresh";
|
|
1170
|
+
const message = error?.message;
|
|
1171
|
+
loadFailure = typeof message === "string" ? message : String(error);
|
|
1172
|
+
logger.logger.debug(`[AcpBackend] Reopening session ${options.loadSessionId} failed; starting a new one: ${loadFailure}`);
|
|
1173
|
+
} finally {
|
|
1174
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
1175
|
+
this.replayingHistory = false;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
if (resumed === "loaded") {
|
|
1180
|
+
this.emitIdleStatus();
|
|
1181
|
+
if (initialPrompt) {
|
|
1182
|
+
this.sendPrompt(sessionId, initialPrompt).catch((error) => {
|
|
1183
|
+
logger.logger.debug("[AcpBackend] Error sending initial prompt:", contentLogMetadata.errorLogMetadata(error));
|
|
1184
|
+
this.emit({ type: "status", status: "error", detail: String(error) });
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
return { sessionId, agentSessionId: this.acpSessionId, resumed };
|
|
1188
|
+
}
|
|
1077
1189
|
logger.logger.debug(`[AcpBackend] Creating new session...`);
|
|
1078
1190
|
const sessionResponse = await withRetry(
|
|
1079
1191
|
async () => {
|
|
@@ -1124,7 +1236,11 @@ class AcpBackend {
|
|
|
1124
1236
|
this.emit({ type: "status", status: "error", detail: String(error) });
|
|
1125
1237
|
});
|
|
1126
1238
|
}
|
|
1127
|
-
return {
|
|
1239
|
+
return {
|
|
1240
|
+
sessionId,
|
|
1241
|
+
agentSessionId: this.acpSessionId ?? void 0,
|
|
1242
|
+
...resumed ? { resumed, ...loadFailure ? { loadFailure } : {} } : {}
|
|
1243
|
+
};
|
|
1128
1244
|
} catch (error) {
|
|
1129
1245
|
logger.logger.debug("[AcpBackend] Error starting session:", contentLogMetadata.errorLogMetadata(error));
|
|
1130
1246
|
if (!startupStatusErrorEmitted) {
|
|
@@ -1210,6 +1326,9 @@ class AcpBackend {
|
|
|
1210
1326
|
`Incoming session update from ${this.options.agentName}: type=${sessionUpdateType ?? "unknown"} payloadBytes=${String(updateMetadata.payloadBytes ?? "unknown")}`
|
|
1211
1327
|
);
|
|
1212
1328
|
}
|
|
1329
|
+
if (this.replayingHistory && isReplayedConversationUpdate(updateType)) {
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1213
1332
|
const ctx = this.createHandlerContext();
|
|
1214
1333
|
if (sessionUpdateType === "agent_message_chunk") {
|
|
1215
1334
|
handleAgentMessageChunk(update, ctx);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var cuid2 = require('@paralleldrive/cuid2');
|
|
4
|
-
var index = require('./index-
|
|
4
|
+
var index = require('./index-C6O2vVjm.cjs');
|
|
5
5
|
|
|
6
6
|
function turnOptions(turnId, time) {
|
|
7
7
|
return turnId ? { turn: turnId, time } : { time };
|
|
@@ -24,6 +24,26 @@ function toolCallEndResult(result) {
|
|
|
24
24
|
...record.truncated === true ? { truncated: true } : {}
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
function piSubagentLabel(args) {
|
|
28
|
+
if (args.piTool !== "subagent") return null;
|
|
29
|
+
const raw = args.rawInput && typeof args.rawInput === "object" ? args.rawInput : {};
|
|
30
|
+
const clip = (text) => {
|
|
31
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
32
|
+
return flat.length > 120 ? `${flat.slice(0, 119)}\u2026` : flat;
|
|
33
|
+
};
|
|
34
|
+
const agent = typeof raw.agent === "string" ? raw.agent : void 0;
|
|
35
|
+
if (typeof raw.task === "string" && raw.task.trim()) return { description: clip(raw.task), ...agent ? { subagentType: agent } : {} };
|
|
36
|
+
if (Array.isArray(raw.tasks)) return { description: `${raw.tasks.length} parallel task${raw.tasks.length === 1 ? "" : "s"}`, ...agent ? { subagentType: agent } : {} };
|
|
37
|
+
if (Array.isArray(raw.chain)) return { description: `chain of ${raw.chain.length} step${raw.chain.length === 1 ? "" : "s"}` };
|
|
38
|
+
return { description: agent ? `${agent} sub-agent` : "sub-agent", ...agent ? { subagentType: agent } : {} };
|
|
39
|
+
}
|
|
40
|
+
function subagentStopStatus(result) {
|
|
41
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return "completed";
|
|
42
|
+
const record = result;
|
|
43
|
+
if (record.status === "cancelled" || record.status === "canceled") return "stopped";
|
|
44
|
+
if (record.error !== void 0 || record.status === "failed" || typeof record.exitCode === "number" && record.exitCode !== 0) return "failed";
|
|
45
|
+
return "completed";
|
|
46
|
+
}
|
|
27
47
|
function parseThinkingPayload(payload) {
|
|
28
48
|
if (typeof payload === "string") {
|
|
29
49
|
return { text: payload, streaming: false };
|
|
@@ -37,6 +57,8 @@ function parseThinkingPayload(payload) {
|
|
|
37
57
|
}
|
|
38
58
|
class AcpSessionManager {
|
|
39
59
|
currentTurnId = null;
|
|
60
|
+
/** B-632 ③: ACP call id → sub-agent id of a running pi `subagent` call. */
|
|
61
|
+
subagentByCall = /* @__PURE__ */ new Map();
|
|
40
62
|
acpCallToSessionCall = /* @__PURE__ */ new Map();
|
|
41
63
|
stream;
|
|
42
64
|
/** Monotonic clock: max(lastTime + 1, Date.now()) */
|
|
@@ -134,10 +156,13 @@ class AcpSessionManager {
|
|
|
134
156
|
return flushed;
|
|
135
157
|
}
|
|
136
158
|
const turnId = this.currentTurnId;
|
|
159
|
+
const stops = [...this.subagentByCall.values()].map((subagent) => index.createEnvelope("agent", { t: "stop", status: status === "completed" ? "completed" : "stopped" }, { turn: turnId, time: this.nextTime(), subagent }));
|
|
160
|
+
this.subagentByCall.clear();
|
|
137
161
|
this.currentTurnId = null;
|
|
138
162
|
this.acpCallToSessionCall.clear();
|
|
139
163
|
return [
|
|
140
164
|
...flushed,
|
|
165
|
+
...stops,
|
|
141
166
|
index.createEnvelope("agent", { t: "turn-end", status }, { turn: turnId, time: this.nextTime() })
|
|
142
167
|
];
|
|
143
168
|
}
|
|
@@ -172,6 +197,10 @@ class AcpSessionManager {
|
|
|
172
197
|
if (msg.type === "tool-call") {
|
|
173
198
|
const flushed = this.flush();
|
|
174
199
|
const call = this.ensureSessionCallId(msg.callId);
|
|
200
|
+
const label = piSubagentLabel(msg.args ?? {});
|
|
201
|
+
const subagent = label ? this.subagentByCall.get(msg.callId) ?? cuid2.createId() : void 0;
|
|
202
|
+
const started = subagent !== void 0 && !this.subagentByCall.has(msg.callId);
|
|
203
|
+
if (subagent) this.subagentByCall.set(msg.callId, subagent);
|
|
175
204
|
return [
|
|
176
205
|
...flushed,
|
|
177
206
|
index.createEnvelope("agent", {
|
|
@@ -180,17 +209,22 @@ class AcpSessionManager {
|
|
|
180
209
|
name: msg.toolName,
|
|
181
210
|
title: buildToolTitle(msg.toolName),
|
|
182
211
|
description: buildToolDescription(msg.toolName),
|
|
183
|
-
|
|
184
|
-
|
|
212
|
+
// The web links the call row to the sub-agent card by this id (as for Claude's Agent).
|
|
213
|
+
args: subagent ? { ...msg.args, sessionSubagent: subagent } : msg.args
|
|
214
|
+
}, turnOptions(this.currentTurnId, this.nextTime())),
|
|
215
|
+
...started && label ? [index.createEnvelope("agent", { t: "start", ...label }, { ...turnOptions(this.currentTurnId, this.nextTime()), subagent })] : []
|
|
185
216
|
];
|
|
186
217
|
}
|
|
187
218
|
if (msg.type === "tool-result") {
|
|
188
219
|
const flushed = this.flush();
|
|
189
220
|
const call = this.ensureSessionCallId(msg.callId);
|
|
190
221
|
const result = toolCallEndResult(msg.result);
|
|
222
|
+
const subagent = this.subagentByCall.get(msg.callId);
|
|
223
|
+
if (subagent) this.subagentByCall.delete(msg.callId);
|
|
191
224
|
return [
|
|
192
225
|
...flushed,
|
|
193
|
-
index.createEnvelope("agent", { t: "tool-call-end", call, ...result ? { result } : {} }, turnOptions(this.currentTurnId, this.nextTime()))
|
|
226
|
+
index.createEnvelope("agent", { t: "tool-call-end", call, ...result ? { result } : {} }, turnOptions(this.currentTurnId, this.nextTime())),
|
|
227
|
+
...subagent ? [index.createEnvelope("agent", { t: "stop", status: subagentStopStatus(msg.result) }, { ...turnOptions(this.currentTurnId, this.nextTime()), subagent })] : []
|
|
194
228
|
];
|
|
195
229
|
}
|
|
196
230
|
return [];
|