nolo-cli 0.148.0-alpha.1 → 0.151.0-alpha.2
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/{_executeModel-NFJAMAGJ.js → _executeModel-XHAFJ2MM.js} +134 -91
- package/accountResolver-7RYB4D2P.js +300 -0
- package/action-SXJD5N5R.js +23 -0
- package/{addContentAction-B2DRF7P6.js → addContentAction-ZV774PHH.js} +20 -14
- package/{addDialogAgentAction-2P2FLTLD.js → addDialogAgentAction-A6SMKAGH.js} +26 -22
- package/{agentDeleteCommand-7IDWF6E3.js → agentDeleteCommand-DPUUS56Z.js} +181 -93
- package/{agentEmailCommands-4KW33JII.js → agentEmailCommands-V4P5EFLP.js} +132 -112
- package/{agentGrantCommands-M3XFO6EN.js → agentGrantCommands-HOJ3JBBQ.js} +3 -3
- package/agentListCommands-TWFLUYIZ.js +802 -0
- package/{agentMachineCommands-CMQR4RQ4.js → agentMachineCommands-MELPAZZI.js} +58 -62
- package/{agentProviderCommands-YK2BIIXZ.js → agentProviderCommands-HL6MBLCL.js} +149 -2
- package/{agentPullCommand-HF4A42D4.js → agentPullCommand-FA43RBRU.js} +7 -7
- package/agentRecordCommands-FSWSSQIO.js +154 -0
- package/agentRunCommand-GDBJVOAT.js +183 -0
- package/{agentRunControl-2SKCR4SB.js → agentRunControl-IFM7IGMG.js} +10 -2
- package/{agentRuntimeLocal-AK2QVJHY.js → agentRuntimeLocal-KKSQJMTE.js} +47 -50
- package/{agentSlice-OZ33K224.js → agentSlice-YO2ZLJMD.js} +23 -16
- package/{appDeleteCommands-N3XEVVYC.js → appDeleteCommands-4PL4KYRN.js} +58 -59
- package/{appDeployCommands-AWFIXYVW.js → appDeployCommands-EEEXCEB6.js} +67 -63
- package/{appDeployStatusCommands-CZRON2FO.js → appDeployStatusCommands-35ZX7T66.js} +56 -56
- package/{appGetCommands-XQIUY4TD.js → appGetCommands-WFCHXJWF.js} +56 -56
- package/{appListCommands-NNG4H36Y.js → appListCommands-XY2U6DPF.js} +57 -59
- package/{authCommand-UBJ4EWYZ.js → authCommand-QYN47CQD.js} +371 -68
- package/{authCommands-H6WKKCRW.js → authCommands-77CHYBGF.js} +12 -9
- package/{builtinSkillRegistry-ZMF6YGNO.js → builtinSkillRegistry-TDQ6JB2E.js} +13 -11
- package/{chromeCommands-2N6MEWRU.js → chromeCommands-OBBNJCLS.js} +314 -13
- package/chromeOpsCommands-3Z34RKSE.js +472 -0
- package/{chunk-ALXHV7NK.js → chunk-2GGXHQIW.js} +43 -4
- package/{localRuntimeAuthority-5W6IJRAD.js → chunk-2IXDJNZI.js} +154 -75
- package/{chunk-IVZJWTDI.js → chunk-36OMEXXR.js} +89 -21
- package/{chunk-H6A6X4EK.js → chunk-3MZAGMYY.js} +16 -0
- package/chunk-3PVYUPXK.js +40 -0
- package/chunk-3SZA4U64.js +1192 -0
- package/{chunk-GNMAFAIS.js → chunk-44WXLHFI.js} +1 -1
- package/{chunk-AGGIDPCZ.js → chunk-4JH2UMJR.js} +6 -0
- package/chunk-4LCOCOR5.js +50 -0
- package/chunk-4YRTZIVN.js +871 -0
- package/chunk-556RW72X.js +14110 -0
- package/{chunk-N7J63Q6C.js → chunk-56GBUMO5.js} +10 -1
- package/{chunk-W7XHHYWM.js → chunk-5BHQICF2.js} +5 -1
- package/{chunk-XUWRURDF.js → chunk-5EBLANFT.js} +1 -1
- package/{chunk-3AH7LNUB.js → chunk-5EMSBTQ6.js} +33 -14
- package/{chunk-YRRASA5Q.js → chunk-5MM7NNO6.js} +113 -52
- package/chunk-5MMAK75Q.js +15 -0
- package/{chunk-M5PVFLD4.js → chunk-64K7WX26.js} +90 -21
- package/{chunk-AKG5W4LG.js → chunk-6CCFTVBP.js} +76 -221
- package/chunk-6MJNEXUU.js +614 -0
- package/{chunk-62IL3KQV.js → chunk-6MXDOUMH.js} +15 -3
- package/{chunk-QOKAKDPE.js → chunk-6Q7UTJKR.js} +6 -94
- package/chunk-6QDYSCPW.js +223 -0
- package/{chunk-HYZIYH2H.js → chunk-74RAWNQN.js} +56 -63
- package/chunk-7DPNBQSV.js +9 -0
- package/chunk-7MOXKPHC.js +119 -0
- package/{chunk-523WHFSL.js → chunk-7XKL25PW.js} +1973 -754
- package/{chunk-IAESIMK7.js → chunk-A4MW3YZL.js} +10 -14
- package/chunk-AGIM7IMJ.js +147 -0
- package/{chunk-7CHC4W22.js → chunk-AIZE5TDM.js} +3 -3
- package/{chunk-P4BX6FFU.js → chunk-AOCM7HPT.js} +214 -51
- package/{chunk-5GVBDNTO.js → chunk-AU7AXHUL.js} +1 -1
- package/{chunk-4H22P2JV.js → chunk-AUIJZACN.js} +2073 -1275
- package/{chunk-CIF4X6ZM.js → chunk-AWVFQMOV.js} +25 -3
- package/{chunk-RYZINGPM.js → chunk-BPMPOFWP.js} +347 -235
- package/{chunk-YUNJN43V.js → chunk-BU2YQBV4.js} +215 -28
- package/{chunk-XPRWFQQK.js → chunk-CBHGZRCE.js} +38 -12
- package/{chunk-Y3PMXGLH.js → chunk-CHCS6XPJ.js} +365 -144
- package/chunk-CHOZJMJS.js +78 -0
- package/{chunk-GBRG75BQ.js → chunk-D2MDMY2M.js} +1 -0
- package/{chunk-3SV7RM24.js → chunk-D2QN6CTI.js} +117 -72
- package/{chunk-5TEEECZM.js → chunk-E2AKSW7L.js} +10 -7
- package/{chunk-RSEEDUMS.js → chunk-EDX5XSJM.js} +2 -2
- package/{chunk-BKWMNZ2X.js → chunk-ES633ZS5.js} +280 -98
- package/{chunk-QDSINZM3.js → chunk-EUGTFFO6.js} +2 -23
- package/{chunk-UNYJU5L6.js → chunk-EYLGAEB4.js} +5 -1
- package/{chunk-CU3QB4HW.js → chunk-EYWJT7A2.js} +12 -12
- package/{chunk-BNGW5ASC.js → chunk-EZVK3N5L.js} +66 -18
- package/{chunk-6FGTMQCL.js → chunk-F32Z66T4.js} +6 -10
- package/chunk-FJMRBOPO.js +11507 -0
- package/{chunk-ZOVKKMF6.js → chunk-FY4SDK2E.js} +1 -1
- package/chunk-G6OOUQWJ.js +417 -0
- package/{chunk-PQWU42UQ.js → chunk-GCKHQECX.js} +6 -6
- package/chunk-GKXCHNTE.js +15 -0
- package/{chunk-T7F46O36.js → chunk-GQN2WLAI.js} +20 -11
- package/{chunk-P6GMCCAT.js → chunk-GQV5KHJU.js} +78 -12
- package/{chunk-B2XUQXQX.js → chunk-HIQ4GF53.js} +191 -68
- package/{chunk-YUWMM4US.js → chunk-HKX3ULQB.js} +34 -22
- package/{chunk-GMZLP5DV.js → chunk-HNUWUO75.js} +30 -19
- package/{chunk-5UTFL4QJ.js → chunk-I2ZMGXXF.js} +10 -5
- package/chunk-I42VC5KR.js +15 -0
- package/{chunk-3BXNTXYI.js → chunk-I4SN4NUQ.js} +1199 -56
- package/chunk-IA7TRNNR.js +11 -0
- package/{chunk-WIWM4FE3.js → chunk-IJERIUXS.js} +55 -748
- package/{chunk-CPUFH46E.js → chunk-ILU2NPWY.js} +10 -10
- package/{chunk-SLLGJZDT.js → chunk-ISQL4V7C.js} +4 -4
- package/chunk-IT3ZZRJE.js +12 -0
- package/{chunk-LPVCRQMM.js → chunk-IZ7OJB6K.js} +20 -16
- package/{chunk-DY7ANLKG.js → chunk-JKMLSTZK.js} +43 -12
- package/{chunk-6TPOEJMQ.js → chunk-JZX2XLKC.js} +64 -23
- package/{chunk-27ONFIEY.js → chunk-K2AER7RX.js} +19 -12
- package/{chunk-O2OWEFII.js → chunk-KFHQQ3NO.js} +1 -1
- package/{chunk-QXGPFY6J.js → chunk-LGN377P3.js} +27 -17
- package/{chunk-L36OWPP3.js → chunk-LIQJTQRN.js} +118 -139
- package/{chunk-FWQEKRTD.js → chunk-LTRUTOHX.js} +36 -31
- package/{chunk-BFU6C242.js → chunk-NMFV26UG.js} +1 -1
- package/{chunk-5J3PYNUP.js → chunk-NYYFIKHI.js} +17 -3
- package/{chunk-6O4IK4V2.js → chunk-OFFL4DCR.js} +1 -1
- package/{chunk-B6SAMB33.js → chunk-OWYYDMGJ.js} +209 -9
- package/{chunk-KQHGZWSV.js → chunk-OXME3PEE.js} +1 -1
- package/{chunk-CTUQJVQM.js → chunk-P5QACQDK.js} +1 -1
- package/{chunk-DIXLJWCD.js → chunk-PCKVQXYV.js} +274 -93
- package/{chunk-4JMDLJAD.js → chunk-PJNFNEJE.js} +114 -37
- package/{chunk-Z4CSIXYP.js → chunk-PLSVXHSA.js} +3 -3
- package/{chunk-BIDGLJQ3.js → chunk-PLXDDGBK.js} +45 -8
- package/chunk-PWTNI4N7.js +47 -0
- package/chunk-QFEW2ULV.js +42 -0
- package/{chunk-RGNEEJ3Y.js → chunk-QLQ573SU.js} +35 -9
- package/chunk-QQ56R7KS.js +88 -0
- package/chunk-QYPE3TS3.js +43 -0
- package/{chunk-4DPP773Q.js → chunk-RSHPU4PD.js} +59 -11
- package/chunk-RVWMAFIT.js +134 -0
- package/{chunk-ESHYE7WU.js → chunk-S73EPYNC.js} +10 -7
- package/{chunk-UQNS32WZ.js → chunk-SCMHQUMK.js} +1 -1
- package/{chunk-T767MPHB.js → chunk-SMENBO3M.js} +354 -120
- package/{chunk-PCVVZ2MH.js → chunk-SSFDFOVT.js} +26 -31
- package/chunk-SW4S4XYB.js +1794 -0
- package/{chunk-HUFPWXFW.js → chunk-T6X3D7NB.js} +572 -430
- package/chunk-TY3TIUJK.js +89 -0
- package/{chunk-X2QRZXZH.js → chunk-TYJ5XFEA.js} +4 -4
- package/{chunk-ALFH24P3.js → chunk-TYYRSFBG.js} +197 -155
- package/{chunk-7KVZ5LDQ.js → chunk-UBUH2TCC.js} +18 -4
- package/chunk-UEILX4EV.js +15 -0
- package/chunk-UHTDNB5Y.js +140 -0
- package/{chunk-YYLHWIW6.js → chunk-UKZX3NHN.js} +1 -1
- package/{chunk-OHOVNO7I.js → chunk-UOKFKFPO.js} +6 -3
- package/{chunk-XISEYOGH.js → chunk-USHQX6VT.js} +5 -5
- package/chunk-UUPR3TD7.js +53 -0
- package/{chunk-HDLLCBRF.js → chunk-VEA7H5FG.js} +2 -2
- package/chunk-VHGD6FHV.js +116 -0
- package/chunk-VIWDGTDA.js +8 -0
- package/{chunk-GOH6RW6F.js → chunk-VJXHL6MH.js} +34 -11
- package/{chunk-4XEYAFLY.js → chunk-VL5KOY2C.js} +623 -94
- package/{chunk-EADNWBAZ.js → chunk-VP3BINY7.js} +13 -0
- package/{chunk-EOARMOVD.js → chunk-W4S6OTSC.js} +6 -3
- package/chunk-WD4XYDYC.js +567 -0
- package/chunk-WJZOQR2J.js +151 -0
- package/{chunk-AUDNYVRC.js → chunk-XETG4RIX.js} +5 -5
- package/{chunk-MX574M24.js → chunk-XI7DGLUK.js} +4 -4
- package/{chunk-3L2WKC3W.js → chunk-XPWGOTBQ.js} +8 -1
- package/chunk-XRUSXPCQ.js +514 -0
- package/{chunk-I4OPU5TK.js → chunk-XS47QOFV.js} +273 -11
- package/{chunk-S5XGT6GB.js → chunk-XZNCX52W.js} +30 -9
- package/{chunk-2JMMBU6V.js → chunk-Y2DXOPSO.js} +1920 -644
- package/{chunk-5OA5HMTL.js → chunk-YLMMECCH.js} +1 -1
- package/{chunk-CFT5HBGW.js → chunk-YVLQXTUB.js} +448 -12
- package/chunk-YVPQATSC.js +709 -0
- package/{chunk-DCFPQW22.js → chunk-Z7OJUX6S.js} +122 -107
- package/chunk-ZEZC7IIM.js +126 -0
- package/{chunk-ALGORS6Y.js → chunk-ZF6526IQ.js} +43 -8
- package/chunk-ZIWPQEFU.js +165 -0
- package/chunk-ZKZ5X2HS.js +7012 -0
- package/chunk-ZRAU6T47.js +56 -0
- package/{cliExecutor-AWYR3T33.js → cliExecutor-BWBF2MTI.js} +4 -3
- package/{clipboardy-BX4NMYHE.js → clipboardy-GCO3GT3I.js} +3 -8
- package/{commandRegistry-YOEQUA7T.js → commandRegistry-XN7C5GHO.js} +183 -107
- package/contentThunks-5L7YQI3S.js +84 -0
- package/{cooldownCommands-ZLEPIB4A.js → cooldownCommands-JFKTYS2D.js} +2 -2
- package/{createAgentAutomationAction-5EJL6ROU.js → createAgentAutomationAction-QOPOLCRK.js} +53 -44
- package/createDialogAction-MZ66VY5Q.js +76 -0
- package/{createPageAction-75ELC64R.js → createPageAction-VQDJIXMY.js} +65 -54
- package/cursorProvider-YGGNMVWX.js +6123 -0
- package/{db-VQSAOWAO.js → db-2QOTXYGH.js} +11 -5
- package/{dbSlice-DQ32LYTJ.js → dbSlice-J37OGIXH.js} +19 -13
- package/{deleteFile-NX6QHCWZ.js → deleteFile-6JWDDRVP.js} +10 -6
- package/dialogCommands-YZLSJB6X.js +113 -0
- package/{dialogSlice-KSXPGJB2.js → dialogSlice-6RODVYCK.js} +53 -39
- package/{docCreateCommands-ZSLGVBZT.js → docCreateCommands-JB2RRMRJ.js} +54 -57
- package/{docDeleteCommands-5N4GVZBG.js → docDeleteCommands-AQENULNM.js} +56 -58
- package/{docReadCommands-YJSAA7AV.js → docReadCommands-DYD25YLQ.js} +53 -56
- package/{docStore-AROBVRCR.js → docStore-ZZA3OPM5.js} +25 -16
- package/{docUpdateCommands-WEMLSW6W.js → docUpdateCommands-3GVS23QL.js} +54 -57
- package/{fetchMessages-67MEFPZR.js → fetchMessages-IIJWQ3HR.js} +5 -4
- package/{getPricing-NMMFT3YI.js → getPricing-FKK3F5EJ.js} +11 -9
- package/{handleSendMessageAction-EGNWHAUB.js → handleSendMessageAction-DVG5U26T.js} +619 -165
- package/index.js +11 -7
- package/{lib-FRRS27KN.js → lib-4YTWAGY7.js} +581 -248
- package/{localDialogRead-EBRS242U.js → localDialogRead-FSOMOPDZ.js} +2 -2
- package/localRuntimeAdapter-HXRHFKRC.js +244 -0
- package/localRuntimeAuthority-JDAD7CB6.js +16 -0
- package/{localRuntimeDb-3LRMNLCM.js → localRuntimeDb-CVC62PM5.js} +1 -1
- package/{machineCommands-ARZYKGGE.js → machineCommands-5KBF4RCC.js} +503 -161
- package/{machineInfo-66ZFUMLE.js → machineInfo-UKPTZO5Y.js} +2 -2
- package/machineWsRunDispatch-4OQDEDOR.js +169 -0
- package/{memberThunks-5ZXPR63F.js → memberThunks-66DH6ABQ.js} +25 -18
- package/{models-ZPU5EDF4.js → models-LAS4B2B5.js} +2 -2
- package/package.json +1 -1
- package/{providerPresetApply-DD6NGWW6.js → providerPresetApply-MY66I6NT.js} +10 -10
- package/{providerRegistry-XDRLMYGJ.js → providerRegistry-QOE2FT57.js} +13 -9
- package/{read-EPTJRAEF.js → read-DC4NUGN6.js} +12 -8
- package/{readDocTool-W4NDXNEX.js → readDocTool-NCJ5NT25.js} +1 -1
- package/{readlineWorkspace-3XOFVARF.js → readlineWorkspace-RIE62QVZ.js} +5022 -921
- package/{removeDialogAgentAction-OSYNZRX7.js → removeDialogAgentAction-E2H3OZU6.js} +29 -28
- package/{runAgentClientLoop-UMF7VZYZ.js → runAgentClientLoop-KLUUXBZS.js} +154 -97
- package/{runtimeDoctorCommands-ID23PNNZ.js → runtimeDoctorCommands-GIOGC5SC.js} +17 -17
- package/secretCommands-ZXZRLR3R.js +700 -0
- package/setDialogExtraReferencesAction-SITRPMYU.js +37 -0
- package/{setPrimaryDialogAgentAction-WZ7KI3YA.js → setPrimaryDialogAgentAction-U7N45TGC.js} +30 -29
- package/{chunk-SONWNI3L.js → settingThunks-Y7SVJOMZ.js} +223 -928
- package/{skillDiscovery-ZBU76COE.js → skillDiscovery-QC35EQY4.js} +2 -2
- package/{slateUtils-RIZES3PV.js → slateUtils-NGV2NMKM.js} +1 -1
- package/{spaceCommands-UJOVU4XI.js → spaceCommands-ZR5BR3GX.js} +59 -59
- package/{streamAgentChatTurn-GYGMYOSM.js → streamAgentChatTurn-MN2SSPGA.js} +309 -165
- package/{switchDialogAgentAction-GMR7WN3P.js → switchDialogAgentAction-OMGBD3N2.js} +26 -22
- package/{tableCommands-G7RV3RU3.js → tableCommands-U3QDY4L6.js} +19 -17
- package/{toolApiClient-CVGWM4PN.js → toolApiClient-7WSJJJBV.js} +6 -5
- package/tools-W2MOLERY.js +124 -0
- package/tuiSummaryLlmCaller-BM3VSTBU.js +130 -0
- package/{updateCommands-4EHDLF5J.js → updateCommands-NQXAGFM7.js} +3 -3
- package/{updateDialogTitleAction-4U5W4AMH.js → updateDialogTitleAction-Z4JX6REN.js} +102 -57
- package/workloadLifecycle-36DXRZKU.js +320 -0
- package/action-GI44T4DR.js +0 -31
- package/agentListCommands-IW3GQVUP.js +0 -427
- package/agentRecordCommands-4YBSYPIY.js +0 -134
- package/agentRunCommand-5MU5X5OT.js +0 -161
- package/browser-image-compression-MFDTD7K6.js +0 -1763
- package/chatQueueReduxAdapter-HVHA2HPM.js +0 -186
- package/chromeOpsCommands-IXRLN57H.js +0 -289
- package/chunk-42Z3EMC4.js +0 -25363
- package/chunk-CQ3WA2NE.js +0 -299
- package/chunk-CYSYR67N.js +0 -93
- package/chunk-IAG4FHOJ.js +0 -34
- package/chunk-JBTJAPUF.js +0 -35
- package/chunk-K2CSUCHJ.js +0 -620
- package/chunk-LTRXGFMS.js +0 -83
- package/chunk-M76ECQRD.js +0 -13658
- package/chunk-MEYIRKDN.js +0 -8967
- package/chunk-OCZKATRC.js +0 -129
- package/chunk-OTGFTBLI.js +0 -13
- package/chunk-PUOC4YRO.js +0 -394
- package/chunk-QU5A4LYX.js +0 -2415
- package/chunk-URMS4XY2.js +0 -10
- package/chunk-UV6VISQJ.js +0 -20
- package/chunk-VJVNU77E.js +0 -83
- package/chunk-WRMKCKZ3.js +0 -13807
- package/chunk-Y5GCAMGP.js +0 -9
- package/chunk-YPREESF4.js +0 -225
- package/contentThunks-AK2F3KNC.js +0 -73
- package/createDialogAction-F5WEWA47.js +0 -66
- package/dialogCommands-G7YBVAMC.js +0 -102
- package/levelLazyShim-GZBKODGI.js +0 -7
- package/machineWsRunDispatch-I7F4L532.js +0 -149
- package/serverStoreFactory-YMXDF4NI.js +0 -20
- package/setDialogExtraReferencesAction-M32UYNCG.js +0 -30
- package/settingSlice-Q6EKL7EQ.js +0 -204
- package/syncMapping-N6RGXGBW.js +0 -437
- package/tools-DU4JXVAV.js +0 -111
- package/tuiSummaryLlmCaller-3YFNHCTW.js +0 -128
- package/{chunk-SV5IJK6K.js → chunk-NBTY7YJF.js} +3 -3
- package/{chunk-2SYTUTLI.js → chunk-YBNHPX4S.js} +3 -3
- package/{offlineMarxistsAgentCommand-HGXZV4XJ.js → offlineMarxistsAgentCommand-2QTHJCHV.js} +4 -4
|
@@ -1,17 +1,517 @@
|
|
|
1
1
|
import {
|
|
2
|
+
buildCliProcessEnv,
|
|
2
3
|
resolveLaunchableCodexCommand
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZEZC7IIM.js";
|
|
4
5
|
import {
|
|
5
6
|
buildCliPrompt
|
|
6
7
|
} from "./chunk-ATNTHIZI.js";
|
|
7
8
|
|
|
8
9
|
// packages/ai/agent/cliExecutor.ts
|
|
9
|
-
import { exec,
|
|
10
|
-
import { randomUUID } from "node:crypto";
|
|
10
|
+
import { exec, spawn as spawn2 } from "child_process";
|
|
11
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
11
12
|
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
12
13
|
import { isAbsolute, join, resolve } from "node:path";
|
|
13
14
|
import { tmpdir } from "node:os";
|
|
14
15
|
import { StringDecoder } from "node:string_decoder";
|
|
16
|
+
|
|
17
|
+
// packages/ai/agent/executors/opencodeExecutor.ts
|
|
18
|
+
import { spawn } from "node:child_process";
|
|
19
|
+
import { randomUUID } from "node:crypto";
|
|
20
|
+
function terminateProcessGroup(proc, signal = "SIGTERM") {
|
|
21
|
+
const pid = proc.pid;
|
|
22
|
+
if (!pid || pid <= 0) return;
|
|
23
|
+
if (process.platform !== "win32") {
|
|
24
|
+
try {
|
|
25
|
+
process.kill(-pid, signal);
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
try {
|
|
30
|
+
const killer = spawn("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
31
|
+
stdio: "ignore",
|
|
32
|
+
windowsHide: true
|
|
33
|
+
});
|
|
34
|
+
killer.on("error", () => {
|
|
35
|
+
});
|
|
36
|
+
killer.unref?.();
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
proc.kill(signal);
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function killProcessGroupEscalating(proc, graceMs = 1200) {
|
|
46
|
+
const pid = proc.pid;
|
|
47
|
+
if (!pid || pid <= 0) return;
|
|
48
|
+
terminateProcessGroup(proc, "SIGTERM");
|
|
49
|
+
const start = Date.now();
|
|
50
|
+
while (Date.now() - start < graceMs) {
|
|
51
|
+
let alive = false;
|
|
52
|
+
if (process.platform !== "win32") {
|
|
53
|
+
try {
|
|
54
|
+
process.kill(-pid, 0);
|
|
55
|
+
alive = true;
|
|
56
|
+
} catch {
|
|
57
|
+
try {
|
|
58
|
+
process.kill(pid, 0);
|
|
59
|
+
alive = true;
|
|
60
|
+
} catch {
|
|
61
|
+
alive = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
try {
|
|
66
|
+
process.kill(pid, 0);
|
|
67
|
+
alive = true;
|
|
68
|
+
} catch {
|
|
69
|
+
alive = false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (!alive) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
76
|
+
}
|
|
77
|
+
terminateProcessGroup(proc, "SIGKILL");
|
|
78
|
+
}
|
|
79
|
+
async function executeOpenCodeStreaming(prompt, options) {
|
|
80
|
+
if (options.imageInputs && options.imageInputs.length > 0) {
|
|
81
|
+
throw new Error("OpenCode executor does not support imageInputs (unsupported)");
|
|
82
|
+
}
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const timeoutMs = options.timeout ?? 12e4;
|
|
85
|
+
const deadline = startTime + timeoutMs;
|
|
86
|
+
if (options.signal?.aborted) {
|
|
87
|
+
throw new DOMException("Execution was aborted before start", "AbortError");
|
|
88
|
+
}
|
|
89
|
+
if (timeoutMs <= 0 || deadline <= startTime) {
|
|
90
|
+
throw new Error(`OpenCode timed out after ${timeoutMs}ms`);
|
|
91
|
+
}
|
|
92
|
+
const internalAbortController = new AbortController();
|
|
93
|
+
let abortReason = null;
|
|
94
|
+
const onExternalAbort = () => {
|
|
95
|
+
abortReason = options.signal?.reason || new DOMException("OpenCode execution was aborted", "AbortError");
|
|
96
|
+
internalAbortController.abort(abortReason);
|
|
97
|
+
};
|
|
98
|
+
if (options.signal) {
|
|
99
|
+
options.signal.addEventListener("abort", onExternalAbort, { once: true });
|
|
100
|
+
}
|
|
101
|
+
const remainingTimeout = deadline - Date.now();
|
|
102
|
+
let deadlineTimer = null;
|
|
103
|
+
if (remainingTimeout <= 0) {
|
|
104
|
+
abortReason = new Error(`OpenCode execution timed out after ${timeoutMs}ms`);
|
|
105
|
+
internalAbortController.abort(abortReason);
|
|
106
|
+
} else {
|
|
107
|
+
deadlineTimer = setTimeout(() => {
|
|
108
|
+
deadlineTimer = null;
|
|
109
|
+
abortReason = new Error(`OpenCode execution timed out after ${timeoutMs}ms`);
|
|
110
|
+
internalAbortController.abort(abortReason);
|
|
111
|
+
}, remainingTimeout);
|
|
112
|
+
deadlineTimer?.unref?.();
|
|
113
|
+
}
|
|
114
|
+
const getAbortError = () => {
|
|
115
|
+
return abortReason || internalAbortController.signal.reason || new DOMException("OpenCode execution was aborted", "AbortError");
|
|
116
|
+
};
|
|
117
|
+
const env = buildCliProcessEnv(options.env);
|
|
118
|
+
const binPath = options.env?.OPENCODE_BIN || process.env.OPENCODE_BIN || "opencode";
|
|
119
|
+
const cwd = options.cwd || process.cwd();
|
|
120
|
+
const serveProc = spawn(
|
|
121
|
+
binPath,
|
|
122
|
+
["serve", "--port", "0", "--hostname", "127.0.0.1"],
|
|
123
|
+
{
|
|
124
|
+
cwd,
|
|
125
|
+
env,
|
|
126
|
+
detached: process.platform !== "win32",
|
|
127
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
let serverBaseUrl = null;
|
|
131
|
+
let activeSessionId = null;
|
|
132
|
+
let hasCleanedUp = false;
|
|
133
|
+
const onProcExit = (code, sig) => {
|
|
134
|
+
if (hasCleanedUp) return;
|
|
135
|
+
const err = new Error(
|
|
136
|
+
serverBaseUrl ? `OpenCode serve process exited prematurely (code: ${code}, signal: ${sig})` : `opencode serve exited before address detected (code: ${code}, signal: ${sig})`
|
|
137
|
+
);
|
|
138
|
+
if (!internalAbortController.signal.aborted) {
|
|
139
|
+
abortReason = err;
|
|
140
|
+
internalAbortController.abort(err);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
serveProc.on("exit", onProcExit);
|
|
144
|
+
serveProc.on("error", (err) => {
|
|
145
|
+
if (hasCleanedUp) return;
|
|
146
|
+
const procErr = new Error(`Failed to spawn opencode serve: ${err.message}`);
|
|
147
|
+
if (!internalAbortController.signal.aborted) {
|
|
148
|
+
abortReason = procErr;
|
|
149
|
+
internalAbortController.abort(procErr);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
const cleanup = async () => {
|
|
153
|
+
if (hasCleanedUp) return;
|
|
154
|
+
hasCleanedUp = true;
|
|
155
|
+
try {
|
|
156
|
+
if (!internalAbortController.signal.aborted) {
|
|
157
|
+
internalAbortController.abort();
|
|
158
|
+
}
|
|
159
|
+
} catch {
|
|
160
|
+
}
|
|
161
|
+
if (activeSessionId && serverBaseUrl) {
|
|
162
|
+
try {
|
|
163
|
+
const cleanupAbortController = new AbortController();
|
|
164
|
+
const abortTimeout = setTimeout(() => cleanupAbortController.abort(), 800);
|
|
165
|
+
try {
|
|
166
|
+
await fetch(`${serverBaseUrl}/session/${activeSessionId}/abort`, {
|
|
167
|
+
method: "POST",
|
|
168
|
+
headers: { "Content-Type": "application/json" },
|
|
169
|
+
body: "{}",
|
|
170
|
+
signal: cleanupAbortController.signal
|
|
171
|
+
});
|
|
172
|
+
} finally {
|
|
173
|
+
clearTimeout(abortTimeout);
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
await killProcessGroupEscalating(serveProc);
|
|
179
|
+
};
|
|
180
|
+
try {
|
|
181
|
+
const portPromise = new Promise((resolve2, reject) => {
|
|
182
|
+
let buffer = "";
|
|
183
|
+
const checkUrl = (chunk) => {
|
|
184
|
+
buffer += chunk.toString();
|
|
185
|
+
const match = buffer.match(/http:\/\/127\.0\.0\.1:(\d+)/);
|
|
186
|
+
if (match) {
|
|
187
|
+
cleanupStartup();
|
|
188
|
+
resolve2(match[0]);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const nonLoopback = buffer.match(/http:\/\/(?!127\.0\.0\.1)[a-zA-Z0-9.-]+:\d+/);
|
|
192
|
+
if (nonLoopback) {
|
|
193
|
+
cleanupStartup();
|
|
194
|
+
reject(new Error(`Rejected untrusted non-loopback OpenCode server url: ${nonLoopback[0]}`));
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const onAbort = () => {
|
|
198
|
+
cleanupStartup();
|
|
199
|
+
reject(getAbortError());
|
|
200
|
+
};
|
|
201
|
+
const cleanupStartup = () => {
|
|
202
|
+
serveProc.stdout?.off("data", checkUrl);
|
|
203
|
+
serveProc.stderr?.off("data", checkUrl);
|
|
204
|
+
internalAbortController.signal.removeEventListener("abort", onAbort);
|
|
205
|
+
};
|
|
206
|
+
if (internalAbortController.signal.aborted) {
|
|
207
|
+
cleanupStartup();
|
|
208
|
+
reject(getAbortError());
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
serveProc.stdout?.on("data", checkUrl);
|
|
212
|
+
serveProc.stderr?.on("data", checkUrl);
|
|
213
|
+
internalAbortController.signal.addEventListener("abort", onAbort, { once: true });
|
|
214
|
+
});
|
|
215
|
+
serverBaseUrl = await portPromise;
|
|
216
|
+
if (internalAbortController.signal.aborted || Date.now() > deadline) {
|
|
217
|
+
throw getAbortError();
|
|
218
|
+
}
|
|
219
|
+
const sseResponse = await fetch(`${serverBaseUrl}/event`, {
|
|
220
|
+
method: "GET",
|
|
221
|
+
headers: { Accept: "text/event-stream" },
|
|
222
|
+
signal: internalAbortController.signal
|
|
223
|
+
}).catch((err) => {
|
|
224
|
+
if (internalAbortController.signal.aborted) {
|
|
225
|
+
throw getAbortError();
|
|
226
|
+
}
|
|
227
|
+
throw new Error(`Failed to connect to OpenCode SSE stream: ${err.message}`);
|
|
228
|
+
});
|
|
229
|
+
if (!sseResponse.ok || !sseResponse.body) {
|
|
230
|
+
throw new Error(`OpenCode /event returned HTTP ${sseResponse.status}: ${sseResponse.statusText}`);
|
|
231
|
+
}
|
|
232
|
+
let sessionModel;
|
|
233
|
+
let promptModel;
|
|
234
|
+
if (options.model) {
|
|
235
|
+
const slashIndex = options.model.indexOf("/");
|
|
236
|
+
if (slashIndex > 0) {
|
|
237
|
+
const providerID = options.model.slice(0, slashIndex);
|
|
238
|
+
const id = options.model.slice(slashIndex + 1);
|
|
239
|
+
sessionModel = {
|
|
240
|
+
id,
|
|
241
|
+
providerID,
|
|
242
|
+
...options.reasoningEffort ? { variant: options.reasoningEffort } : {}
|
|
243
|
+
};
|
|
244
|
+
promptModel = { modelID: id, providerID };
|
|
245
|
+
} else {
|
|
246
|
+
sessionModel = {
|
|
247
|
+
id: options.model,
|
|
248
|
+
...options.reasoningEffort ? { variant: options.reasoningEffort } : {}
|
|
249
|
+
};
|
|
250
|
+
promptModel = { modelID: options.model };
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const sessionTitle = `nolo-opencode-${randomUUID().slice(0, 8)}`;
|
|
254
|
+
const createSessionResp = await fetch(`${serverBaseUrl}/session`, {
|
|
255
|
+
method: "POST",
|
|
256
|
+
headers: { "Content-Type": "application/json" },
|
|
257
|
+
body: JSON.stringify({
|
|
258
|
+
title: sessionTitle,
|
|
259
|
+
...sessionModel ? { model: sessionModel } : {}
|
|
260
|
+
}),
|
|
261
|
+
signal: internalAbortController.signal
|
|
262
|
+
}).catch((err) => {
|
|
263
|
+
if (internalAbortController.signal.aborted) {
|
|
264
|
+
throw getAbortError();
|
|
265
|
+
}
|
|
266
|
+
throw err;
|
|
267
|
+
});
|
|
268
|
+
if (!createSessionResp.ok) {
|
|
269
|
+
const errText = await createSessionResp.text().catch(() => "");
|
|
270
|
+
throw new Error(`Failed to create OpenCode session (HTTP ${createSessionResp.status}): ${errText}`);
|
|
271
|
+
}
|
|
272
|
+
const sessionData = await createSessionResp.json();
|
|
273
|
+
if (!sessionData.id) {
|
|
274
|
+
throw new Error("OpenCode create session response did not return an id");
|
|
275
|
+
}
|
|
276
|
+
const sessionId = sessionData.id;
|
|
277
|
+
activeSessionId = sessionId;
|
|
278
|
+
let fullText = "";
|
|
279
|
+
let hasBeenBusy = false;
|
|
280
|
+
let isCompleted = false;
|
|
281
|
+
const seenPartTexts = /* @__PURE__ */ new Map();
|
|
282
|
+
const emittedToolCalls = /* @__PURE__ */ new Set();
|
|
283
|
+
const emittedToolResults = /* @__PURE__ */ new Set();
|
|
284
|
+
const emittedToolErrors = /* @__PURE__ */ new Set();
|
|
285
|
+
const streamPromise = new Promise((resolve2, reject) => {
|
|
286
|
+
let buffer = "";
|
|
287
|
+
const reader = sseResponse.body.getReader();
|
|
288
|
+
const decoder = new TextDecoder("utf-8");
|
|
289
|
+
const markCompleted = () => {
|
|
290
|
+
isCompleted = true;
|
|
291
|
+
resolve2();
|
|
292
|
+
};
|
|
293
|
+
const handleEventJson = (parsed) => {
|
|
294
|
+
const type = parsed?.type;
|
|
295
|
+
const properties = parsed?.properties || parsed?.data || {};
|
|
296
|
+
if (properties.sessionID && properties.sessionID !== sessionId) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (properties.part?.sessionID && properties.part.sessionID !== sessionId) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (parsed?.sessionID && parsed.sessionID !== sessionId) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (type === "permission.asked" || type === "permission.v2.asked") {
|
|
306
|
+
reject(new Error(`OpenCode requested unsupported permission: ${properties.permission || properties.action || properties.id || "unsupported"}`));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (type === "session.error") {
|
|
310
|
+
const errDetail = properties.error ? JSON.stringify(properties.error) : "Session error";
|
|
311
|
+
reject(new Error(`OpenCode session error: ${errDetail}`));
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (type === "session.status") {
|
|
315
|
+
const statusType = properties.status?.type;
|
|
316
|
+
if (statusType === "busy") {
|
|
317
|
+
hasBeenBusy = true;
|
|
318
|
+
} else if (statusType === "idle") {
|
|
319
|
+
if (hasBeenBusy) {
|
|
320
|
+
markCompleted();
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (type === "session.idle") {
|
|
326
|
+
if (hasBeenBusy) {
|
|
327
|
+
markCompleted();
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (type === "message.part.delta") {
|
|
332
|
+
const field = properties.field;
|
|
333
|
+
const delta = properties.delta;
|
|
334
|
+
if (field === "text" && typeof delta === "string" && delta.length > 0) {
|
|
335
|
+
hasBeenBusy = true;
|
|
336
|
+
const partId = properties.partID || "default";
|
|
337
|
+
const currentSeen = seenPartTexts.get(partId) || "";
|
|
338
|
+
seenPartTexts.set(partId, currentSeen + delta);
|
|
339
|
+
fullText += delta;
|
|
340
|
+
options.onChunk?.(delta);
|
|
341
|
+
}
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (type === "message.part.updated") {
|
|
345
|
+
const part = properties.part;
|
|
346
|
+
if (!part) return;
|
|
347
|
+
if (part.type === "tool") {
|
|
348
|
+
hasBeenBusy = true;
|
|
349
|
+
const callId = part.callID || part.id || `tool-${randomUUID().slice(0, 6)}`;
|
|
350
|
+
const toolName = part.tool || "unknown";
|
|
351
|
+
const state = part.state;
|
|
352
|
+
const round = options.toolEventRound ?? 1;
|
|
353
|
+
if (state?.status === "pending" || state?.status === "running") {
|
|
354
|
+
if (!emittedToolCalls.has(callId)) {
|
|
355
|
+
emittedToolCalls.add(callId);
|
|
356
|
+
options.onToolEvent?.({
|
|
357
|
+
type: "tool-call",
|
|
358
|
+
round,
|
|
359
|
+
toolCallId: callId,
|
|
360
|
+
toolName,
|
|
361
|
+
summary: `Tool call: ${toolName}`,
|
|
362
|
+
metadata: { source: "cli-external", cliProvider: "opencode" }
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
} else if (state?.status === "completed") {
|
|
366
|
+
if (!emittedToolResults.has(callId)) {
|
|
367
|
+
emittedToolResults.add(callId);
|
|
368
|
+
options.onToolEvent?.({
|
|
369
|
+
type: "tool-result",
|
|
370
|
+
round,
|
|
371
|
+
toolCallId: callId,
|
|
372
|
+
toolName,
|
|
373
|
+
summary: `Tool completed: ${toolName}`,
|
|
374
|
+
metadata: { source: "cli-external", cliProvider: "opencode" }
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
} else if (state?.status === "error") {
|
|
378
|
+
if (!emittedToolErrors.has(callId)) {
|
|
379
|
+
emittedToolErrors.add(callId);
|
|
380
|
+
options.onToolEvent?.({
|
|
381
|
+
type: "tool-error",
|
|
382
|
+
round,
|
|
383
|
+
toolCallId: callId,
|
|
384
|
+
toolName,
|
|
385
|
+
message: "Tool execution failed",
|
|
386
|
+
summary: `Tool error: ${toolName}`,
|
|
387
|
+
metadata: { source: "cli-external", cliProvider: "opencode" }
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
} else if (part.type === "text") {
|
|
392
|
+
hasBeenBusy = true;
|
|
393
|
+
const partId = part.id || part.partID || "default";
|
|
394
|
+
const fullPartText = typeof part.text === "string" ? part.text : "";
|
|
395
|
+
const seen = seenPartTexts.get(partId) || "";
|
|
396
|
+
if (fullPartText.length > seen.length) {
|
|
397
|
+
const diff = fullPartText.slice(seen.length);
|
|
398
|
+
if (diff.length > 0) {
|
|
399
|
+
seenPartTexts.set(partId, seen + diff);
|
|
400
|
+
fullText += diff;
|
|
401
|
+
options.onChunk?.(diff);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
const pump = async () => {
|
|
408
|
+
try {
|
|
409
|
+
while (true) {
|
|
410
|
+
const { done, value } = await reader.read();
|
|
411
|
+
if (done) {
|
|
412
|
+
if (!isCompleted) {
|
|
413
|
+
reject(new Error("OpenCode SSE stream disconnected prematurely (unexpected EOF)"));
|
|
414
|
+
}
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
buffer += decoder.decode(value, { stream: true });
|
|
418
|
+
const lines = buffer.split(/\r?\n/);
|
|
419
|
+
buffer = lines.pop() ?? "";
|
|
420
|
+
for (const line of lines) {
|
|
421
|
+
const trimmed = line.trim();
|
|
422
|
+
if (trimmed.startsWith("data:")) {
|
|
423
|
+
const payload = trimmed.slice(5).trim();
|
|
424
|
+
if (payload === "[DONE]") {
|
|
425
|
+
markCompleted();
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
let parsed;
|
|
429
|
+
try {
|
|
430
|
+
parsed = JSON.parse(payload);
|
|
431
|
+
} catch {
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
handleEventJson(parsed);
|
|
435
|
+
if (isCompleted) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
} catch (err) {
|
|
442
|
+
if (isCompleted) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (internalAbortController.signal.aborted) {
|
|
446
|
+
reject(getAbortError());
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (err?.name === "AbortError") {
|
|
450
|
+
reject(getAbortError());
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
reject(err);
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
pump();
|
|
457
|
+
});
|
|
458
|
+
const promptPayload = {
|
|
459
|
+
parts: [{ type: "text", text: prompt }],
|
|
460
|
+
...promptModel ? { model: promptModel } : {},
|
|
461
|
+
...options.systemPrompt ? { system: options.systemPrompt } : {}
|
|
462
|
+
};
|
|
463
|
+
const promptResp = await fetch(`${serverBaseUrl}/session/${sessionId}/prompt_async`, {
|
|
464
|
+
method: "POST",
|
|
465
|
+
headers: { "Content-Type": "application/json" },
|
|
466
|
+
body: JSON.stringify(promptPayload),
|
|
467
|
+
signal: internalAbortController.signal
|
|
468
|
+
}).catch((err) => {
|
|
469
|
+
if (internalAbortController.signal.aborted) {
|
|
470
|
+
throw getAbortError();
|
|
471
|
+
}
|
|
472
|
+
throw err;
|
|
473
|
+
});
|
|
474
|
+
if (!promptResp.ok) {
|
|
475
|
+
const errText = await promptResp.text().catch(() => "");
|
|
476
|
+
throw new Error(`Failed to send prompt to OpenCode session (HTTP ${promptResp.status}): ${errText}`);
|
|
477
|
+
}
|
|
478
|
+
let abortListener = null;
|
|
479
|
+
const abortPromise = new Promise((_, reject) => {
|
|
480
|
+
if (internalAbortController.signal.aborted) {
|
|
481
|
+
reject(getAbortError());
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
abortListener = () => reject(getAbortError());
|
|
485
|
+
internalAbortController.signal.addEventListener("abort", abortListener, { once: true });
|
|
486
|
+
});
|
|
487
|
+
try {
|
|
488
|
+
await Promise.race([streamPromise, abortPromise]);
|
|
489
|
+
} finally {
|
|
490
|
+
if (abortListener) {
|
|
491
|
+
internalAbortController.signal.removeEventListener("abort", abortListener);
|
|
492
|
+
abortListener = null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
const elapsed = Date.now() - startTime;
|
|
496
|
+
return {
|
|
497
|
+
text: fullText,
|
|
498
|
+
raw: fullText,
|
|
499
|
+
elapsed
|
|
500
|
+
};
|
|
501
|
+
} finally {
|
|
502
|
+
if (deadlineTimer) {
|
|
503
|
+
clearTimeout(deadlineTimer);
|
|
504
|
+
deadlineTimer = null;
|
|
505
|
+
}
|
|
506
|
+
if (options.signal) {
|
|
507
|
+
options.signal.removeEventListener("abort", onExternalAbort);
|
|
508
|
+
}
|
|
509
|
+
serveProc.off("exit", onProcExit);
|
|
510
|
+
await cleanup();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// packages/ai/agent/cliExecutor.ts
|
|
15
515
|
var CliProviderQuotaError = class extends Error {
|
|
16
516
|
provider;
|
|
17
517
|
constructor(provider, message) {
|
|
@@ -59,9 +559,7 @@ var DEFAULT_GROK_TIMEOUT_MS = 6e5;
|
|
|
59
559
|
var BUFFERED_STREAMING_PROVIDERS = /* @__PURE__ */ new Set([
|
|
60
560
|
"codex",
|
|
61
561
|
"claude",
|
|
62
|
-
"agy",
|
|
63
562
|
"qoder",
|
|
64
|
-
"opencode",
|
|
65
563
|
"grok",
|
|
66
564
|
"kimi"
|
|
67
565
|
]);
|
|
@@ -69,54 +567,6 @@ function isBufferedCliStreamingProvider(provider) {
|
|
|
69
567
|
return BUFFERED_STREAMING_PROVIDERS.has(provider);
|
|
70
568
|
}
|
|
71
569
|
var cliSessions = /* @__PURE__ */ new Map();
|
|
72
|
-
function readMacSystemProxyEnv() {
|
|
73
|
-
if (process.platform !== "darwin") return {};
|
|
74
|
-
try {
|
|
75
|
-
const raw = String(execSync("scutil --proxy", { encoding: "utf8" }) || "");
|
|
76
|
-
const values = /* @__PURE__ */ new Map();
|
|
77
|
-
for (const line of raw.split("\n")) {
|
|
78
|
-
const match = line.match(/^\s*([A-Za-z0-9_]+)\s*:\s*(.+?)\s*$/);
|
|
79
|
-
if (!match) continue;
|
|
80
|
-
values.set(match[1], match[2].replace(/^"|"$/g, ""));
|
|
81
|
-
}
|
|
82
|
-
const httpEnabled = values.get("HTTPEnable") === "1";
|
|
83
|
-
const httpsEnabled = values.get("HTTPSEnable") === "1";
|
|
84
|
-
const httpHost = values.get("HTTPProxy")?.trim();
|
|
85
|
-
const httpsHost = values.get("HTTPSProxy")?.trim();
|
|
86
|
-
const httpPort = values.get("HTTPPort")?.trim();
|
|
87
|
-
const httpsPort = values.get("HTTPSPort")?.trim();
|
|
88
|
-
const noProxy = values.get("ExceptionsList")?.trim();
|
|
89
|
-
const httpProxy = httpEnabled && httpHost && httpPort ? `http://${httpHost}:${httpPort}` : "";
|
|
90
|
-
const httpsProxy = httpsEnabled && httpsHost && httpsPort ? `http://${httpsHost}:${httpsPort}` : "";
|
|
91
|
-
const allProxy = httpsProxy || httpProxy;
|
|
92
|
-
return {
|
|
93
|
-
...httpProxy ? { HTTP_PROXY: httpProxy, http_proxy: httpProxy } : {},
|
|
94
|
-
...httpsProxy ? { HTTPS_PROXY: httpsProxy, https_proxy: httpsProxy } : {},
|
|
95
|
-
...allProxy ? { ALL_PROXY: allProxy, all_proxy: allProxy } : {},
|
|
96
|
-
...noProxy ? { NO_PROXY: noProxy, no_proxy: noProxy } : {}
|
|
97
|
-
};
|
|
98
|
-
} catch {
|
|
99
|
-
return {};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
function normalizeProxyEnv(env) {
|
|
103
|
-
const explicitHttp = env.HTTP_PROXY?.trim() || env.http_proxy?.trim() || "";
|
|
104
|
-
const explicitHttps = env.HTTPS_PROXY?.trim() || env.https_proxy?.trim() || "";
|
|
105
|
-
const explicitAll = env.ALL_PROXY?.trim() || env.all_proxy?.trim() || "";
|
|
106
|
-
const explicitNoProxy = env.NO_PROXY?.trim() || env.no_proxy?.trim() || "";
|
|
107
|
-
const fallback = explicitHttp || explicitHttps || explicitAll ? {} : readMacSystemProxyEnv();
|
|
108
|
-
const httpProxy = explicitHttp || fallback.HTTP_PROXY || fallback.http_proxy || "";
|
|
109
|
-
const httpsProxy = explicitHttps || fallback.HTTPS_PROXY || fallback.https_proxy || httpProxy;
|
|
110
|
-
const allProxy = explicitAll || fallback.ALL_PROXY || fallback.all_proxy || httpsProxy || httpProxy;
|
|
111
|
-
const noProxy = explicitNoProxy || fallback.NO_PROXY || fallback.no_proxy || "";
|
|
112
|
-
return {
|
|
113
|
-
...env,
|
|
114
|
-
...httpProxy ? { HTTP_PROXY: httpProxy, http_proxy: httpProxy } : {},
|
|
115
|
-
...httpsProxy ? { HTTPS_PROXY: httpsProxy, https_proxy: httpsProxy } : {},
|
|
116
|
-
...allProxy ? { ALL_PROXY: allProxy, all_proxy: allProxy } : {},
|
|
117
|
-
...noProxy ? { NO_PROXY: noProxy, no_proxy: noProxy } : {}
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
570
|
var CLI_PROBE_BINARIES = {
|
|
121
571
|
copilot: ["gh", "copilot"],
|
|
122
572
|
gemini: ["gemini"],
|
|
@@ -128,39 +578,6 @@ var CLI_PROBE_BINARIES = {
|
|
|
128
578
|
grok: ["grok"],
|
|
129
579
|
kimi: ["kimi"]
|
|
130
580
|
};
|
|
131
|
-
function buildCliProcessEnv(extraEnv) {
|
|
132
|
-
const baseEnv = {
|
|
133
|
-
...process.env,
|
|
134
|
-
...extraEnv,
|
|
135
|
-
NO_COLOR: "1"
|
|
136
|
-
};
|
|
137
|
-
if (process.platform === "darwin") {
|
|
138
|
-
const defaultMacPaths = [
|
|
139
|
-
`${process.env.HOME || ""}/.local/bin`,
|
|
140
|
-
"/opt/homebrew/bin",
|
|
141
|
-
"/opt/homebrew/sbin",
|
|
142
|
-
"/usr/local/bin",
|
|
143
|
-
"/usr/local/sbin",
|
|
144
|
-
`${process.env.HOME || ""}/.bun/bin`,
|
|
145
|
-
`${process.env.HOME || ""}/Library/pnpm`,
|
|
146
|
-
`${process.env.HOME || ""}/.npm-global/bin`,
|
|
147
|
-
`${process.env.HOME || ""}/bin`
|
|
148
|
-
];
|
|
149
|
-
const existingPath = baseEnv.PATH || "/usr/bin:/bin:/usr/sbin:/sbin";
|
|
150
|
-
const paths = existingPath.split(":");
|
|
151
|
-
for (const p of defaultMacPaths) {
|
|
152
|
-
if (p && !paths.includes(p)) {
|
|
153
|
-
paths.unshift(p);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
baseEnv.PATH = paths.join(":");
|
|
157
|
-
}
|
|
158
|
-
return Object.fromEntries(
|
|
159
|
-
Object.entries(normalizeProxyEnv(baseEnv)).filter(
|
|
160
|
-
(entry) => typeof entry[1] === "string"
|
|
161
|
-
)
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
581
|
function getCliProviderLabel(provider) {
|
|
165
582
|
switch (provider) {
|
|
166
583
|
case "claude":
|
|
@@ -187,7 +604,7 @@ function supportsNativeSystemPrompt(provider) {
|
|
|
187
604
|
return provider === "claude";
|
|
188
605
|
}
|
|
189
606
|
function supportsModel(provider) {
|
|
190
|
-
return provider !== "
|
|
607
|
+
return provider !== "codex";
|
|
191
608
|
}
|
|
192
609
|
function supportsReasoningEffort(provider) {
|
|
193
610
|
return provider === "claude" || provider === "copilot" || provider === "qoder" || provider === "opencode" || provider === "grok";
|
|
@@ -667,7 +1084,7 @@ function terminateCliProcessGroup(proc, signal) {
|
|
|
667
1084
|
}
|
|
668
1085
|
if (pid > 0 && process.platform === "win32") {
|
|
669
1086
|
try {
|
|
670
|
-
const killer =
|
|
1087
|
+
const killer = spawn2("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
671
1088
|
stdio: "ignore",
|
|
672
1089
|
windowsHide: true
|
|
673
1090
|
});
|
|
@@ -710,7 +1127,7 @@ function attachCliAbortSignal(proc, signal, onAbort) {
|
|
|
710
1127
|
}
|
|
711
1128
|
function spawnCliProcess(executable, args, options) {
|
|
712
1129
|
const { signal, ...spawnOptions } = options;
|
|
713
|
-
const proc =
|
|
1130
|
+
const proc = spawn2(executable, args, {
|
|
714
1131
|
...spawnOptions,
|
|
715
1132
|
...signal ? { detached: true } : {}
|
|
716
1133
|
});
|
|
@@ -749,6 +1166,7 @@ function executeAgy(prompt, options) {
|
|
|
749
1166
|
"--print-timeout",
|
|
750
1167
|
formatCliTimeout(timeout)
|
|
751
1168
|
];
|
|
1169
|
+
if (options.model) args.push("--model", options.model);
|
|
752
1170
|
if (yolo) {
|
|
753
1171
|
args.push("--dangerously-skip-permissions");
|
|
754
1172
|
}
|
|
@@ -821,6 +1239,108 @@ stderr: ${stderrText}`));
|
|
|
821
1239
|
});
|
|
822
1240
|
});
|
|
823
1241
|
}
|
|
1242
|
+
function executeAgyStreaming(prompt, options) {
|
|
1243
|
+
const {
|
|
1244
|
+
cwd = process.cwd(),
|
|
1245
|
+
timeout = DEFAULT_AGY_TIMEOUT_MS,
|
|
1246
|
+
yolo = true,
|
|
1247
|
+
model,
|
|
1248
|
+
onChunk
|
|
1249
|
+
} = options;
|
|
1250
|
+
return new Promise((resolve2, reject) => {
|
|
1251
|
+
const args = [
|
|
1252
|
+
"--add-dir",
|
|
1253
|
+
cwd,
|
|
1254
|
+
"--print=" + prompt,
|
|
1255
|
+
"--output-format",
|
|
1256
|
+
"stream-json",
|
|
1257
|
+
"--print-timeout",
|
|
1258
|
+
formatCliTimeout(timeout)
|
|
1259
|
+
];
|
|
1260
|
+
if (model) args.push("--model", model);
|
|
1261
|
+
if (yolo) args.push("--dangerously-skip-permissions");
|
|
1262
|
+
const start = Date.now();
|
|
1263
|
+
const proc = spawnCliProcess("agy", args, {
|
|
1264
|
+
cwd,
|
|
1265
|
+
env: buildCliProcessEnv(options.env),
|
|
1266
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1267
|
+
detached: process.platform !== "win32",
|
|
1268
|
+
signal: options.signal
|
|
1269
|
+
});
|
|
1270
|
+
const stdout = createUtf8Collector();
|
|
1271
|
+
const stderr = createUtf8Collector();
|
|
1272
|
+
let pending = "";
|
|
1273
|
+
let answer = "";
|
|
1274
|
+
let settled = false;
|
|
1275
|
+
let timer;
|
|
1276
|
+
let detachAbort = () => {
|
|
1277
|
+
};
|
|
1278
|
+
const finish = (callback) => {
|
|
1279
|
+
if (settled) return;
|
|
1280
|
+
settled = true;
|
|
1281
|
+
if (timer) clearTimeout(timer);
|
|
1282
|
+
detachAbort();
|
|
1283
|
+
callback();
|
|
1284
|
+
};
|
|
1285
|
+
const fail = (error) => {
|
|
1286
|
+
if (settled) return;
|
|
1287
|
+
terminateCliProcessGroupEscalating(proc);
|
|
1288
|
+
finish(() => reject(error));
|
|
1289
|
+
};
|
|
1290
|
+
detachAbort = attachCliAbortSignal(proc, options.signal, (error) => {
|
|
1291
|
+
finish(() => reject(error));
|
|
1292
|
+
});
|
|
1293
|
+
if (!settled && timeout > 0) {
|
|
1294
|
+
timer = setTimeout(() => {
|
|
1295
|
+
fail(buildAgyTimeoutError(timeout, stdout.end(), stderr.end()));
|
|
1296
|
+
}, timeout + 1e3);
|
|
1297
|
+
}
|
|
1298
|
+
const consumeLine = (line) => {
|
|
1299
|
+
if (settled || !line.trim()) return;
|
|
1300
|
+
let event;
|
|
1301
|
+
try {
|
|
1302
|
+
event = JSON.parse(line);
|
|
1303
|
+
} catch {
|
|
1304
|
+
return;
|
|
1305
|
+
}
|
|
1306
|
+
if (event?.event !== "step_update" || event.step_update?.step_type !== "agent_response" || typeof event.step_update.text_delta !== "string") return;
|
|
1307
|
+
const delta = event.step_update.text_delta;
|
|
1308
|
+
if (!delta) return;
|
|
1309
|
+
answer += delta;
|
|
1310
|
+
try {
|
|
1311
|
+
onChunk(delta);
|
|
1312
|
+
} catch (error) {
|
|
1313
|
+
fail(error);
|
|
1314
|
+
}
|
|
1315
|
+
};
|
|
1316
|
+
proc.stdout.on("data", (data) => {
|
|
1317
|
+
if (settled) return;
|
|
1318
|
+
pending += stdout.write(data);
|
|
1319
|
+
const lines = pending.split("\n");
|
|
1320
|
+
pending = lines.pop() ?? "";
|
|
1321
|
+
for (const line of lines) consumeLine(line);
|
|
1322
|
+
});
|
|
1323
|
+
proc.stderr.on("data", (data) => {
|
|
1324
|
+
if (!settled) stderr.write(data);
|
|
1325
|
+
});
|
|
1326
|
+
proc.on("close", (code, signal) => {
|
|
1327
|
+
if (settled) return;
|
|
1328
|
+
pending += stdout.finish();
|
|
1329
|
+
consumeLine(pending);
|
|
1330
|
+
if (settled) return;
|
|
1331
|
+
const raw = stdout.end();
|
|
1332
|
+
const stderrText = stderr.end();
|
|
1333
|
+
if (code !== 0 || signal) {
|
|
1334
|
+
const quota = detectCliProviderQuotaLimit("agy", raw, stderrText, code);
|
|
1335
|
+
finish(() => reject(quota.limited ? new CliProviderQuotaError("agy", quota.message || "Agy reported quota/limit") : new Error(`Antigravity CLI exited with ${signal ? `signal ${signal}` : `code ${code}`}
|
|
1336
|
+
stderr: ${stderrText}`)));
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
finish(() => resolve2({ text: answer.trim(), raw, elapsed: Date.now() - start }));
|
|
1340
|
+
});
|
|
1341
|
+
proc.on("error", (error) => fail(error));
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
824
1344
|
function executeQoder(prompt, options) {
|
|
825
1345
|
const {
|
|
826
1346
|
model,
|
|
@@ -1272,7 +1792,7 @@ function startCliSession(provider, options = {}) {
|
|
|
1272
1792
|
if (!EXECUTORS[provider]) {
|
|
1273
1793
|
throw new Error(`Unknown CLI provider: "${provider}". Supported: ${Object.keys(EXECUTORS).join(", ")}`);
|
|
1274
1794
|
}
|
|
1275
|
-
const sessionId =
|
|
1795
|
+
const sessionId = randomUUID2();
|
|
1276
1796
|
cliSessions.set(sessionId, {
|
|
1277
1797
|
sessionId,
|
|
1278
1798
|
provider,
|
|
@@ -1382,7 +1902,17 @@ function executeCliStreaming(provider, prompt, options) {
|
|
|
1382
1902
|
})
|
|
1383
1903
|
);
|
|
1384
1904
|
}
|
|
1385
|
-
if (provider === "agy"
|
|
1905
|
+
if (provider === "agy") {
|
|
1906
|
+
return withCleanup(
|
|
1907
|
+
executeAgyStreaming(resolved.prompt, resolved.options).then((result) => ({ ...result, warnings: [...resolved.warnings, ...result.warnings ?? []] }))
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1910
|
+
if (provider === "opencode") {
|
|
1911
|
+
return withCleanup(
|
|
1912
|
+
executeOpenCodeStreaming(resolved.prompt, resolved.options).then((result) => ({ ...result, warnings: [...resolved.warnings, ...result.warnings ?? []] }))
|
|
1913
|
+
);
|
|
1914
|
+
}
|
|
1915
|
+
if (provider === "qoder" || provider === "grok" || provider === "kimi") {
|
|
1386
1916
|
return withCleanup(
|
|
1387
1917
|
executor(resolved.prompt, resolved.options).then((result) => {
|
|
1388
1918
|
const merged = { ...result, warnings: [...resolved.warnings, ...result.warnings ?? []] };
|
|
@@ -1421,7 +1951,7 @@ function executeCliStreaming(provider, prompt, options) {
|
|
|
1421
1951
|
}
|
|
1422
1952
|
if (yolo) args.push("--yolo");
|
|
1423
1953
|
const start = Date.now();
|
|
1424
|
-
const proc =
|
|
1954
|
+
const proc = spawn2("gh", args, {
|
|
1425
1955
|
cwd,
|
|
1426
1956
|
env: buildCliProcessEnv(resolved.options.env),
|
|
1427
1957
|
...resolved.options.signal ? { detached: true } : {}
|
|
@@ -1486,7 +2016,7 @@ function executeGeminiStreaming(prompt, options) {
|
|
|
1486
2016
|
if (yolo) args.push("--yolo");
|
|
1487
2017
|
args.push("-e", "none");
|
|
1488
2018
|
const start = Date.now();
|
|
1489
|
-
const proc =
|
|
2019
|
+
const proc = spawn2("gemini", args, {
|
|
1490
2020
|
cwd,
|
|
1491
2021
|
env: buildCliProcessEnv({
|
|
1492
2022
|
...options.env,
|
|
@@ -1580,7 +2110,6 @@ export {
|
|
|
1580
2110
|
detectCliProviderQuotaLimit,
|
|
1581
2111
|
isBufferedCliStreamingProvider,
|
|
1582
2112
|
CLI_PROBE_BINARIES,
|
|
1583
|
-
buildCliProcessEnv,
|
|
1584
2113
|
materializeCliImageInputs,
|
|
1585
2114
|
executeCli,
|
|
1586
2115
|
startCliSession,
|