nolo-cli 0.149.0-alpha.1 → 0.151.0-alpha.3
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-OW3H7ICR.js → _executeModel-T7ANHTUW.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-4L5KCKFY.js} +181 -93
- package/{agentEmailCommands-A6XBQZBN.js → agentEmailCommands-2IMMIRO2.js} +132 -112
- package/{agentGrantCommands-M3XFO6EN.js → agentGrantCommands-HOJ3JBBQ.js} +3 -3
- package/agentListCommands-TWFLUYIZ.js +802 -0
- package/{agentMachineCommands-DQPUIMAC.js → agentMachineCommands-KIWXWT6L.js} +58 -62
- package/{agentProviderCommands-YK2BIIXZ.js → agentProviderCommands-HL6MBLCL.js} +149 -2
- package/{agentPullCommand-HF4A42D4.js → agentPullCommand-FA43RBRU.js} +7 -7
- package/agentRecordCommands-727NPCRW.js +154 -0
- package/agentRunCommand-JASIG3FZ.js +183 -0
- package/{agentRunControl-2SKCR4SB.js → agentRunControl-IFM7IGMG.js} +10 -2
- package/{agentRuntimeLocal-AK2QVJHY.js → agentRuntimeLocal-KKSQJMTE.js} +47 -50
- package/{agentSlice-O4RUQUMT.js → agentSlice-SLV57QGU.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-ID7LNBWR.js → chunk-3T4ZG6AC.js} +1920 -644
- 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-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-TXH4IWJL.js → chunk-626KHJNX.js} +20 -11
- 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-IAESIMK7.js → chunk-A4MW3YZL.js} +10 -14
- package/{chunk-OMRJYNCI.js → chunk-AG7MCDLR.js} +26 -31
- package/chunk-AGIM7IMJ.js +147 -0
- package/{chunk-7CHC4W22.js → chunk-AIZE5TDM.js} +3 -3
- package/chunk-AJ3G7X2K.js +7012 -0
- 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-YAQJJDC2.js → chunk-BJEZC5RA.js} +214 -51
- 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-CYJWI3NH.js +119 -0
- package/{chunk-GBRG75BQ.js → chunk-D2MDMY2M.js} +1 -0
- package/{chunk-3SV7RM24.js → chunk-D2QN6CTI.js} +117 -72
- package/{chunk-TZZ2WRBL.js → chunk-DFDXM2Y4.js} +20 -16
- package/{chunk-5TEEECZM.js → chunk-E2AKSW7L.js} +10 -7
- package/{chunk-RSEEDUMS.js → chunk-EDX5XSJM.js} +2 -2
- 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-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-P6GMCCAT.js → chunk-GQV5KHJU.js} +78 -12
- package/{chunk-B2XUQXQX.js → chunk-HIQ4GF53.js} +191 -68
- package/{chunk-GMZLP5DV.js → chunk-HNUWUO75.js} +30 -19
- package/{chunk-UASIEDKM.js → chunk-I2XLRXVX.js} +36 -31
- 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-BIDGLJQ3.js → chunk-IK2TSJQA.js} +45 -8
- 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-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-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-TB3MIBRC.js → chunk-PIDUNDFS.js} +572 -430
- package/{chunk-4JMDLJAD.js → chunk-PJNFNEJE.js} +114 -37
- package/chunk-PKZKOVA5.js +11507 -0
- package/{chunk-Z4CSIXYP.js → chunk-PLSVXHSA.js} +3 -3
- 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-HTVYCXBP.js → chunk-RN2GPWN6.js} +354 -120
- package/{chunk-ATLTFRYJ.js → chunk-ROCUB2H2.js} +280 -98
- 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-SW4S4XYB.js +1794 -0
- package/{chunk-ZUEK6A6C.js → chunk-TTH4HOJD.js} +1973 -754
- 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-MST6R3E4.js → chunk-U5GPBQDG.js} +34 -22
- package/chunk-U5ICMAFV.js +14110 -0
- 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-3DAVPNFT.js → chunk-V4EE3D54.js} +122 -107
- 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-DXHL7G2L.js → chunk-VWW6O2TL.js} +274 -93
- 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-5OA5HMTL.js → chunk-YLMMECCH.js} +1 -1
- package/{chunk-CFT5HBGW.js → chunk-YVLQXTUB.js} +448 -12
- package/chunk-YVPQATSC.js +709 -0
- package/chunk-ZEZC7IIM.js +126 -0
- package/{chunk-ALGORS6Y.js → chunk-ZF6526IQ.js} +43 -8
- package/chunk-ZIWPQEFU.js +165 -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-2KBOXZQC.js → commandRegistry-NBLZEMCW.js} +183 -107
- package/contentThunks-6AIWNSGO.js +84 -0
- package/{cooldownCommands-ZLEPIB4A.js → cooldownCommands-JFKTYS2D.js} +2 -2
- package/{createAgentAutomationAction-5UGTB26P.js → createAgentAutomationAction-4BUS65DZ.js} +53 -44
- package/createDialogAction-QAIKSCG4.js +76 -0
- package/{createPageAction-CDLDKPRM.js → createPageAction-DXCZ334C.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-N3YB65G5.js → dialogSlice-PVUSMKFW.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-E3CEOV5Q.js → docStore-CSEBEMKP.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-DQAD5ERJ.js → handleSendMessageAction-G2TLYGC4.js} +422 -118
- 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-B4TAYYA7.js +244 -0
- package/localRuntimeAuthority-JDAD7CB6.js +16 -0
- package/{localRuntimeDb-3LRMNLCM.js → localRuntimeDb-CVC62PM5.js} +1 -1
- package/{machineCommands-HAP75VSG.js → machineCommands-6OBFD3XF.js} +503 -161
- package/{machineInfo-66ZFUMLE.js → machineInfo-UKPTZO5Y.js} +2 -2
- package/machineWsRunDispatch-OO7N3O3Y.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-7BC66QSX.js → readlineWorkspace-UIQN7JUR.js} +5017 -915
- package/{removeDialogAgentAction-OSYNZRX7.js → removeDialogAgentAction-E2H3OZU6.js} +29 -28
- package/{runAgentClientLoop-6E6UC3CE.js → runAgentClientLoop-GS3SGG37.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-3UXPYFNX.js → streamAgentChatTurn-4XYC33KE.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-P77EE7Q4.js +124 -0
- package/tuiSummaryLlmCaller-BM3VSTBU.js +130 -0
- package/{updateCommands-4EHDLF5J.js → updateCommands-NQXAGFM7.js} +3 -3
- package/{updateDialogTitleAction-UPFV7TDT.js → updateDialogTitleAction-CIANVPZC.js} +102 -57
- package/workloadLifecycle-36DXRZKU.js +320 -0
- package/action-GI44T4DR.js +0 -31
- package/agentListCommands-IW3GQVUP.js +0 -427
- package/agentRecordCommands-VCA76W6B.js +0 -134
- package/agentRunCommand-YNLDKVR7.js +0 -161
- package/browser-image-compression-MFDTD7K6.js +0 -1763
- package/chatQueueReduxAdapter-TJRMXMYA.js +0 -186
- package/chromeOpsCommands-IXRLN57H.js +0 -289
- package/chunk-36KZDDO5.js +0 -2415
- package/chunk-ACQD6YI2.js +0 -25363
- package/chunk-CQ3WA2NE.js +0 -299
- package/chunk-CYSYR67N.js +0 -93
- 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-PZZTFEKK.js +0 -34
- package/chunk-URMS4XY2.js +0 -10
- package/chunk-UV6VISQJ.js +0 -20
- package/chunk-VJVNU77E.js +0 -83
- package/chunk-XYJSY4KG.js +0 -13807
- package/chunk-Y5GCAMGP.js +0 -9
- package/chunk-YPREESF4.js +0 -225
- package/contentThunks-BDIQRZR6.js +0 -73
- package/createDialogAction-B7VGVEVU.js +0 -66
- package/dialogCommands-G7YBVAMC.js +0 -102
- package/levelLazyShim-GZBKODGI.js +0 -7
- package/machineWsRunDispatch-L32G7C4P.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-MKYDMWA4.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
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildExecutionTicket
|
|
3
|
+
} from "./chunk-PWTNI4N7.js";
|
|
4
|
+
|
|
5
|
+
// packages/agent-runtime/docker/executionTicket.ts
|
|
6
|
+
function buildPrimaryExecutionTicket(runGrant, executionClass = "session") {
|
|
7
|
+
return buildExecutionTicket({
|
|
8
|
+
runGrant,
|
|
9
|
+
ticketId: `${runGrant.grantId}:primary`,
|
|
10
|
+
executionClass
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// packages/agent-runtime/docker/destructiveShellPolicy.ts
|
|
15
|
+
var SHELL_DESTRUCTIVE_PATTERNS = [
|
|
16
|
+
/\brm\s+(-[^\n\r]*\s+)?/i,
|
|
17
|
+
/\bremove-item\b/i,
|
|
18
|
+
/\bdel\s+\/?[a-z]*\s+/i,
|
|
19
|
+
/\berase\s+/i,
|
|
20
|
+
/\brmdir\s+/i,
|
|
21
|
+
/\brd\s+\/s\b/i,
|
|
22
|
+
/\bgit\s+reset\s+(--hard\b|--merge\b|--keep\b)/i,
|
|
23
|
+
/\bgit\s+clean\s+-[^\n\r]*f/i,
|
|
24
|
+
/\bgit\s+checkout\s+--\b/i,
|
|
25
|
+
/\bgit\s+restore\s+--source=/i
|
|
26
|
+
];
|
|
27
|
+
var isDestructiveShellCommand = (params) => {
|
|
28
|
+
const combined = [
|
|
29
|
+
typeof params.command === "string" ? params.command : "",
|
|
30
|
+
typeof params.input === "string" ? params.input : ""
|
|
31
|
+
].filter(Boolean).join("\n");
|
|
32
|
+
if (!combined.trim()) return false;
|
|
33
|
+
return SHELL_DESTRUCTIVE_PATTERNS.some((pattern) => pattern.test(combined));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// packages/agent-runtime/docker/sandboxWorkspaceHelper.ts
|
|
37
|
+
import * as path from "node:path";
|
|
38
|
+
var SANDBOX_WORKSPACE_ROOT = "/home/bun/app";
|
|
39
|
+
var SANDBOX_HELPER_PATH = "/tmp/nolo-tools/workspace-tool.mjs";
|
|
40
|
+
function posixQuote(value) {
|
|
41
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
42
|
+
}
|
|
43
|
+
function buildSandboxHelperUploadArgv() {
|
|
44
|
+
const encoded = Buffer.from(buildWorkspaceHelperSource(), "utf8").toString("base64");
|
|
45
|
+
const dir = SANDBOX_HELPER_PATH.slice(0, SANDBOX_HELPER_PATH.lastIndexOf("/"));
|
|
46
|
+
return [
|
|
47
|
+
"bash",
|
|
48
|
+
"-lc",
|
|
49
|
+
`mkdir -p ${posixQuote(dir)} && printf %s ${posixQuote(encoded)} | base64 -d > ${posixQuote(SANDBOX_HELPER_PATH)} && chmod 0644 ${posixQuote(SANDBOX_HELPER_PATH)}`
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
var SANDBOX_OUTPUT_LIMITS = {
|
|
53
|
+
/** readFile: chars kept from the head of value.content */
|
|
54
|
+
readHeadChars: 2e4,
|
|
55
|
+
/** readFile: chars kept from the tail; head + marker + tail is the content cap */
|
|
56
|
+
readTailChars: 1e4,
|
|
57
|
+
/** glob/grep: max elements returned in value */
|
|
58
|
+
maxArrayItems: 500,
|
|
59
|
+
/** glob/grep: max chars per element (path or matched line) */
|
|
60
|
+
maxItemChars: 2e3,
|
|
61
|
+
/** glob/grep: serialized-char budget for the whole array */
|
|
62
|
+
arrayCharBudget: 24e3,
|
|
63
|
+
/** hard cap on the serialized {ok:true,value} envelope */
|
|
64
|
+
maxSerializedChars: 32e3,
|
|
65
|
+
/** writeFile.content and editFile.newText: max UTF-8 bytes per argument */
|
|
66
|
+
maxContentBytes: 64 * 1024,
|
|
67
|
+
/** base64 argv hard guard: one exec argument must stay far below 128KiB */
|
|
68
|
+
maxArgvBytes: 96 * 1024
|
|
69
|
+
};
|
|
70
|
+
var ALLOWED_GREP_FLAGS = "imsu";
|
|
71
|
+
function checkGrepFlags(flags) {
|
|
72
|
+
if (flags === void 0) return { ok: true, value: "" };
|
|
73
|
+
if (typeof flags !== "string") return { ok: false, error: "unsupported_regex_flags" };
|
|
74
|
+
for (const ch of flags) {
|
|
75
|
+
if (!ALLOWED_GREP_FLAGS.includes(ch)) return { ok: false, error: "unsupported_regex_flags" };
|
|
76
|
+
}
|
|
77
|
+
return { ok: true, value: flags };
|
|
78
|
+
}
|
|
79
|
+
function resolveSandboxPath(input) {
|
|
80
|
+
if (typeof input !== "string" || !input.trim()) {
|
|
81
|
+
return { ok: false, error: "invalid_path" };
|
|
82
|
+
}
|
|
83
|
+
if (input.includes("\0")) {
|
|
84
|
+
return { ok: false, error: "path_contains_nul" };
|
|
85
|
+
}
|
|
86
|
+
const isAbsolute = path.posix.isAbsolute(input);
|
|
87
|
+
if (isAbsolute && input !== SANDBOX_WORKSPACE_ROOT && !input.startsWith(SANDBOX_WORKSPACE_ROOT + "/")) {
|
|
88
|
+
return { ok: false, error: "path_outside_workspace" };
|
|
89
|
+
}
|
|
90
|
+
const resolved = isAbsolute ? path.posix.normalize(input) : path.posix.normalize(path.posix.join(SANDBOX_WORKSPACE_ROOT, input));
|
|
91
|
+
if (resolved !== SANDBOX_WORKSPACE_ROOT && !resolved.startsWith(SANDBOX_WORKSPACE_ROOT + "/")) {
|
|
92
|
+
return { ok: false, error: "path_escape" };
|
|
93
|
+
}
|
|
94
|
+
return { ok: true, path: resolved };
|
|
95
|
+
}
|
|
96
|
+
function buildWorkspaceHelperSource() {
|
|
97
|
+
return `import fs from "node:fs/promises";
|
|
98
|
+
import path from "node:path";
|
|
99
|
+
|
|
100
|
+
const ROOT = "${SANDBOX_WORKSPACE_ROOT}";
|
|
101
|
+
const MAX_SERIALIZED_CHARS = ${SANDBOX_OUTPUT_LIMITS.maxSerializedChars};
|
|
102
|
+
const READ_HEAD_CHARS = ${SANDBOX_OUTPUT_LIMITS.readHeadChars};
|
|
103
|
+
const READ_TAIL_CHARS = ${SANDBOX_OUTPUT_LIMITS.readTailChars};
|
|
104
|
+
const MAX_ARRAY_ITEMS = ${SANDBOX_OUTPUT_LIMITS.maxArrayItems};
|
|
105
|
+
const MAX_ITEM_CHARS = ${SANDBOX_OUTPUT_LIMITS.maxItemChars};
|
|
106
|
+
const ARRAY_CHAR_BUDGET = ${SANDBOX_OUTPUT_LIMITS.arrayCharBudget};
|
|
107
|
+
const MAX_CONTENT_BYTES = ${SANDBOX_OUTPUT_LIMITS.maxContentBytes};
|
|
108
|
+
const NL = String.fromCharCode(10);
|
|
109
|
+
|
|
110
|
+
function resolvePath(input) {
|
|
111
|
+
if (typeof input !== "string" || !input.trim() || input.includes("\\0")) {
|
|
112
|
+
return { ok: false, error: "invalid_path" };
|
|
113
|
+
}
|
|
114
|
+
const isAbs = path.posix.isAbsolute(input);
|
|
115
|
+
if (isAbs && input !== ROOT && !input.startsWith(ROOT + "/")) {
|
|
116
|
+
return { ok: false, error: "path_outside_workspace" };
|
|
117
|
+
}
|
|
118
|
+
const res = isAbs ? path.posix.normalize(input) : path.posix.normalize(path.posix.join(ROOT, input));
|
|
119
|
+
if (res !== ROOT && !res.startsWith(ROOT + "/")) {
|
|
120
|
+
return { ok: false, error: "path_escape" };
|
|
121
|
+
}
|
|
122
|
+
return { ok: true, path: res };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function truncateContent(str) {
|
|
126
|
+
if (typeof str !== "string") return str;
|
|
127
|
+
if (str.length <= READ_HEAD_CHARS + READ_TAIL_CHARS) return str;
|
|
128
|
+
const omitted = str.length - READ_HEAD_CHARS - READ_TAIL_CHARS;
|
|
129
|
+
return str.slice(0, READ_HEAD_CHARS) + NL + "...[truncated " + omitted + " chars]..." + NL + str.slice(str.length - READ_TAIL_CHARS);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function capText(text, limit) {
|
|
133
|
+
if (typeof text !== "string") return "";
|
|
134
|
+
if (text.length <= limit) return text;
|
|
135
|
+
return text.slice(0, limit) + "...[+" + (text.length - limit) + " chars]";
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Arrays are trimmed element by element (never by cutting the serialized
|
|
139
|
+
// string), so the emitted envelope is always complete JSON. A single trailing
|
|
140
|
+
// marker string reports how many results were dropped.
|
|
141
|
+
function capPaths(paths) {
|
|
142
|
+
const kept = [];
|
|
143
|
+
let used = 0;
|
|
144
|
+
let omitted = 0;
|
|
145
|
+
for (let i = 0; i < paths.length; i++) {
|
|
146
|
+
if (kept.length >= MAX_ARRAY_ITEMS) { omitted = paths.length - i; break; }
|
|
147
|
+
const text = capText(paths[i], MAX_ITEM_CHARS);
|
|
148
|
+
const cost = JSON.stringify(text).length;
|
|
149
|
+
if (used + cost > ARRAY_CHAR_BUDGET) { omitted = paths.length - i; break; }
|
|
150
|
+
used += cost;
|
|
151
|
+
kept.push(text);
|
|
152
|
+
}
|
|
153
|
+
return { items: kept, omitted };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function capMatches(matches) {
|
|
157
|
+
const kept = [];
|
|
158
|
+
let used = 0;
|
|
159
|
+
let omitted = 0;
|
|
160
|
+
for (let i = 0; i < matches.length; i++) {
|
|
161
|
+
if (kept.length >= MAX_ARRAY_ITEMS) { omitted = matches.length - i; break; }
|
|
162
|
+
const item = { file: capText(matches[i].file, MAX_ITEM_CHARS), line: matches[i].line, text: capText(matches[i].text, MAX_ITEM_CHARS) };
|
|
163
|
+
const cost = JSON.stringify(item).length;
|
|
164
|
+
if (used + cost > ARRAY_CHAR_BUDGET) { omitted = matches.length - i; break; }
|
|
165
|
+
used += cost;
|
|
166
|
+
kept.push(item);
|
|
167
|
+
}
|
|
168
|
+
return { items: kept, omitted };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function withMarker(items, omitted) {
|
|
172
|
+
if (omitted <= 0) return items;
|
|
173
|
+
return items.concat("...[truncated: " + omitted + " more results omitted]");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function clampArray(items) {
|
|
177
|
+
let kept = items;
|
|
178
|
+
while (kept.length > 0) {
|
|
179
|
+
const out = JSON.stringify({ ok: true, value: kept });
|
|
180
|
+
if (out.length <= MAX_SERIALIZED_CHARS) return out;
|
|
181
|
+
const nextCount = Math.max(0, Math.floor(kept.length / 2) - 1);
|
|
182
|
+
kept = kept.slice(0, nextCount).concat("...[output clipped: " + (kept.length - nextCount) + " items dropped]");
|
|
183
|
+
}
|
|
184
|
+
return JSON.stringify({ ok: true, value: [] });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function clampString(value) {
|
|
188
|
+
const plain = JSON.stringify({ ok: true, value: value });
|
|
189
|
+
if (plain.length <= MAX_SERIALIZED_CHARS) return plain;
|
|
190
|
+
let head = READ_HEAD_CHARS;
|
|
191
|
+
let tail = READ_TAIL_CHARS;
|
|
192
|
+
while (true) {
|
|
193
|
+
const candidate = value.slice(0, head) + NL + "...[output clipped]..." + NL + value.slice(value.length - tail);
|
|
194
|
+
const out = JSON.stringify({ ok: true, value: candidate });
|
|
195
|
+
if (out.length <= MAX_SERIALIZED_CHARS) return out;
|
|
196
|
+
if (head <= 4000) return JSON.stringify({ ok: true, value: capText(value, 2000) });
|
|
197
|
+
head = Math.floor(head / 2);
|
|
198
|
+
tail = Math.floor(tail / 2);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function emitValue(value) {
|
|
203
|
+
if (Array.isArray(value)) return console.log(clampArray(value));
|
|
204
|
+
if (typeof value === "string") return console.log(clampString(value));
|
|
205
|
+
const out = JSON.stringify({ ok: true, value });
|
|
206
|
+
if (out.length <= MAX_SERIALIZED_CHARS) return console.log(out);
|
|
207
|
+
return console.log(JSON.stringify({ ok: false, error: "output_too_large" }));
|
|
208
|
+
}
|
|
209
|
+
function patternToRegex(pat) {
|
|
210
|
+
const escaped = pat.replace(/[-/\\\\^$+?.()|[\\]{}]/g, "\\\\$&");
|
|
211
|
+
const regexStr = "^" + escaped.replace(/\\*\\*/g, ".*").replace(/\\*/g, "[^/]*") + "$";
|
|
212
|
+
return new RegExp(regexStr);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async function collectFiles(dir, maxDepth = 15, currentDepth = 0) {
|
|
216
|
+
if (currentDepth > maxDepth) return [];
|
|
217
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
218
|
+
const results = [];
|
|
219
|
+
for (const entry of entries) {
|
|
220
|
+
const full = path.posix.join(dir, entry.name);
|
|
221
|
+
if (entry.isDirectory()) {
|
|
222
|
+
results.push(...await collectFiles(full, maxDepth, currentDepth + 1));
|
|
223
|
+
} else {
|
|
224
|
+
results.push(full);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return results;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async function main() {
|
|
231
|
+
const payloadRaw = process.argv[2];
|
|
232
|
+
if (!payloadRaw) {
|
|
233
|
+
console.log(JSON.stringify({ ok: false, error: "missing_payload" }));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
let payload;
|
|
237
|
+
try {
|
|
238
|
+
payload = JSON.parse(Buffer.from(payloadRaw, "base64").toString("utf-8"));
|
|
239
|
+
} catch {
|
|
240
|
+
console.log(JSON.stringify({ ok: false, error: "invalid_base64_payload" }));
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const { op, args } = payload;
|
|
245
|
+
try {
|
|
246
|
+
switch (op) {
|
|
247
|
+
case "readFile": {
|
|
248
|
+
const p = resolvePath(args.path);
|
|
249
|
+
if (!p.ok) return console.log(JSON.stringify({ ok: false, error: p.error }));
|
|
250
|
+
const content = await fs.readFile(p.path, "utf-8");
|
|
251
|
+
let result = content;
|
|
252
|
+
if (typeof args.lines === "string") {
|
|
253
|
+
const lines = content.split("\\n");
|
|
254
|
+
const m = args.lines.match(/^(-?\\d+)?(?:-(-?\\d+)?)?$/);
|
|
255
|
+
if (m) {
|
|
256
|
+
const start = m[1] ? parseInt(m[1], 10) : 1;
|
|
257
|
+
const end = m[2] ? parseInt(m[2], 10) : (args.lines.endsWith("-") ? lines.length : start);
|
|
258
|
+
if (args.lines.startsWith("-")) {
|
|
259
|
+
const count = Math.abs(parseInt(args.lines, 10));
|
|
260
|
+
result = lines.slice(-count).join("\\n");
|
|
261
|
+
} else {
|
|
262
|
+
result = lines.slice(Math.max(0, start - 1), Math.max(0, end)).join("\\n");
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return emitValue(truncateContent(result));
|
|
267
|
+
} case "writeFile": {
|
|
268
|
+
const p = resolvePath(args.path);
|
|
269
|
+
if (!p.ok) return console.log(JSON.stringify({ ok: false, error: p.error }));
|
|
270
|
+
if (Buffer.byteLength(args.content, "utf-8") > MAX_CONTENT_BYTES) {
|
|
271
|
+
return console.log(JSON.stringify({ ok: false, error: "content_too_large" }));
|
|
272
|
+
}
|
|
273
|
+
await fs.mkdir(path.posix.dirname(p.path), { recursive: true });
|
|
274
|
+
await fs.writeFile(p.path, args.content, "utf-8");
|
|
275
|
+
return console.log(JSON.stringify({ ok: true, value: { written: true, bytes: Buffer.byteLength(args.content) } }));
|
|
276
|
+
}
|
|
277
|
+
case "editFile": {
|
|
278
|
+
const p = resolvePath(args.path);
|
|
279
|
+
if (!p.ok) return console.log(JSON.stringify({ ok: false, error: p.error }));
|
|
280
|
+
if (Buffer.byteLength(args.newText, "utf-8") > MAX_CONTENT_BYTES) {
|
|
281
|
+
return console.log(JSON.stringify({ ok: false, error: "content_too_large" }));
|
|
282
|
+
}
|
|
283
|
+
const content = await fs.readFile(p.path, "utf-8");
|
|
284
|
+
if (!content.includes(args.oldText)) {
|
|
285
|
+
return console.log(JSON.stringify({ ok: false, error: "edit_old_text_not_found" }));
|
|
286
|
+
}
|
|
287
|
+
const replaced = content.replaceAll(args.oldText, args.newText);
|
|
288
|
+
await fs.writeFile(p.path, replaced, "utf-8");
|
|
289
|
+
return console.log(JSON.stringify({ ok: true, value: { replaced: true } }));
|
|
290
|
+
}
|
|
291
|
+
case "glob": {
|
|
292
|
+
const rootDir = args.path ? resolvePath(args.path) : { ok: true, path: ROOT };
|
|
293
|
+
if (!rootDir.ok) return console.log(JSON.stringify({ ok: false, error: rootDir.error }));
|
|
294
|
+
const allFiles = await collectFiles(rootDir.path);
|
|
295
|
+
const re = patternToRegex(args.pattern);
|
|
296
|
+
const matched = allFiles.filter(f => {
|
|
297
|
+
const rel = path.posix.relative(ROOT, f);
|
|
298
|
+
return re.test(rel) || re.test(f);
|
|
299
|
+
});
|
|
300
|
+
const capped = capPaths(matched);
|
|
301
|
+
return emitValue(withMarker(capped.items, capped.omitted));
|
|
302
|
+
}
|
|
303
|
+
case "grep": {
|
|
304
|
+
const rootDir = args.path ? resolvePath(args.path) : { ok: true, path: ROOT };
|
|
305
|
+
if (!rootDir.ok) return console.log(JSON.stringify({ ok: false, error: rootDir.error }));
|
|
306
|
+
const flags = args.flags === undefined ? "" : args.flags;
|
|
307
|
+
if (typeof flags !== "string" || !/^[imsu]*$/.test(flags)) {
|
|
308
|
+
return console.log(JSON.stringify({ ok: false, error: "unsupported_regex_flags" }));
|
|
309
|
+
}
|
|
310
|
+
const allFiles = await collectFiles(rootDir.path);
|
|
311
|
+
const re = new RegExp(args.pattern, flags);
|
|
312
|
+
const matches = [];
|
|
313
|
+
for (const file of allFiles) {
|
|
314
|
+
try {
|
|
315
|
+
const text = await fs.readFile(file, "utf-8");
|
|
316
|
+
const lines = text.split(NL);
|
|
317
|
+
for (let i = 0; i < lines.length; i++) {
|
|
318
|
+
if (re.test(lines[i])) {
|
|
319
|
+
matches.push({ file: path.posix.relative(ROOT, file), line: i + 1, text: lines[i].slice(0, 500) });
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
} catch {}
|
|
323
|
+
}
|
|
324
|
+
const capped = capMatches(matches);
|
|
325
|
+
return emitValue(withMarker(capped.items, capped.omitted));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
case "mkdir": {
|
|
329
|
+
const p = resolvePath(args.path);
|
|
330
|
+
if (!p.ok) return console.log(JSON.stringify({ ok: false, error: p.error }));
|
|
331
|
+
await fs.mkdir(p.path, { recursive: true });
|
|
332
|
+
return console.log(JSON.stringify({ ok: true, value: { created: true } }));
|
|
333
|
+
}
|
|
334
|
+
case "stat": {
|
|
335
|
+
const p = resolvePath(args.path);
|
|
336
|
+
if (!p.ok) return console.log(JSON.stringify({ ok: false, error: p.error }));
|
|
337
|
+
const st = await fs.stat(p.path);
|
|
338
|
+
return console.log(JSON.stringify({ ok: true, value: { isFile: st.isFile(), isDirectory: st.isDirectory(), size: st.size, mtimeMs: st.mtimeMs } }));
|
|
339
|
+
}
|
|
340
|
+
default:
|
|
341
|
+
return console.log(JSON.stringify({ ok: false, error: "unknown_op" }));
|
|
342
|
+
}
|
|
343
|
+
} catch (err) {
|
|
344
|
+
return console.log(JSON.stringify({ ok: false, error: err && err.message ? err.message : "operation_failed" }));
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
main();
|
|
348
|
+
`;
|
|
349
|
+
}
|
|
350
|
+
function buildToolInvocation(toolName, args) {
|
|
351
|
+
let op;
|
|
352
|
+
const validatedArgs = {};
|
|
353
|
+
switch (toolName) {
|
|
354
|
+
case "readFile": {
|
|
355
|
+
if (typeof args.path !== "string" || !args.path.trim()) {
|
|
356
|
+
return { ok: false, error: "missing_path" };
|
|
357
|
+
}
|
|
358
|
+
const res = resolveSandboxPath(args.path);
|
|
359
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
360
|
+
op = "readFile";
|
|
361
|
+
validatedArgs.path = res.path;
|
|
362
|
+
if (typeof args.lines === "string") validatedArgs.lines = args.lines;
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
case "writeFile": {
|
|
366
|
+
if (typeof args.path !== "string" || !args.path.trim()) {
|
|
367
|
+
return { ok: false, error: "missing_path" };
|
|
368
|
+
}
|
|
369
|
+
if (typeof args.content !== "string") {
|
|
370
|
+
return { ok: false, error: "missing_content" };
|
|
371
|
+
}
|
|
372
|
+
if (Buffer.byteLength(args.content, "utf-8") > SANDBOX_OUTPUT_LIMITS.maxContentBytes) {
|
|
373
|
+
return { ok: false, error: "content_too_large" };
|
|
374
|
+
}
|
|
375
|
+
const res = resolveSandboxPath(args.path);
|
|
376
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
377
|
+
op = "writeFile";
|
|
378
|
+
validatedArgs.path = res.path;
|
|
379
|
+
validatedArgs.content = args.content;
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
case "editFile": {
|
|
383
|
+
if (typeof args.path !== "string" || !args.path.trim()) {
|
|
384
|
+
return { ok: false, error: "missing_path" };
|
|
385
|
+
}
|
|
386
|
+
if (typeof args.oldText !== "string" || typeof args.newText !== "string") {
|
|
387
|
+
return { ok: false, error: "missing_edit_text" };
|
|
388
|
+
}
|
|
389
|
+
if (args.oldText === args.newText) {
|
|
390
|
+
return { ok: false, error: "edit_text_identical" };
|
|
391
|
+
}
|
|
392
|
+
if (Buffer.byteLength(args.newText, "utf-8") > SANDBOX_OUTPUT_LIMITS.maxContentBytes) {
|
|
393
|
+
return { ok: false, error: "content_too_large" };
|
|
394
|
+
}
|
|
395
|
+
const res = resolveSandboxPath(args.path);
|
|
396
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
397
|
+
op = "editFile";
|
|
398
|
+
validatedArgs.path = res.path;
|
|
399
|
+
validatedArgs.oldText = args.oldText;
|
|
400
|
+
validatedArgs.newText = args.newText;
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
case "glob":
|
|
404
|
+
case "globFiles": {
|
|
405
|
+
if (typeof args.pattern !== "string" || !args.pattern.trim()) {
|
|
406
|
+
return { ok: false, error: "missing_pattern" };
|
|
407
|
+
}
|
|
408
|
+
op = "glob";
|
|
409
|
+
validatedArgs.pattern = args.pattern;
|
|
410
|
+
if (typeof args.path === "string" && args.path.trim()) {
|
|
411
|
+
const res = resolveSandboxPath(args.path);
|
|
412
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
413
|
+
validatedArgs.path = res.path;
|
|
414
|
+
}
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
case "grep":
|
|
418
|
+
case "grepFiles": {
|
|
419
|
+
if (typeof args.pattern !== "string" || !args.pattern.trim()) {
|
|
420
|
+
return { ok: false, error: "missing_pattern" };
|
|
421
|
+
}
|
|
422
|
+
const flags = checkGrepFlags(args.flags);
|
|
423
|
+
if (!flags.ok) return { ok: false, error: flags.error };
|
|
424
|
+
try {
|
|
425
|
+
new RegExp(args.pattern, flags.value);
|
|
426
|
+
} catch {
|
|
427
|
+
return { ok: false, error: "invalid_regex_pattern" };
|
|
428
|
+
}
|
|
429
|
+
op = "grep";
|
|
430
|
+
validatedArgs.pattern = args.pattern;
|
|
431
|
+
if (flags.value) validatedArgs.flags = flags.value;
|
|
432
|
+
if (typeof args.path === "string" && args.path.trim()) {
|
|
433
|
+
const res = resolveSandboxPath(args.path);
|
|
434
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
435
|
+
validatedArgs.path = res.path;
|
|
436
|
+
}
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
case "mkdir": {
|
|
440
|
+
if (typeof args.path !== "string" || !args.path.trim()) {
|
|
441
|
+
return { ok: false, error: "missing_path" };
|
|
442
|
+
}
|
|
443
|
+
const res = resolveSandboxPath(args.path);
|
|
444
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
445
|
+
op = "mkdir";
|
|
446
|
+
validatedArgs.path = res.path;
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
case "stat": {
|
|
450
|
+
if (typeof args.path !== "string" || !args.path.trim()) {
|
|
451
|
+
return { ok: false, error: "missing_path" };
|
|
452
|
+
}
|
|
453
|
+
const res = resolveSandboxPath(args.path);
|
|
454
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
455
|
+
op = "stat";
|
|
456
|
+
validatedArgs.path = res.path;
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
default:
|
|
460
|
+
return { ok: false, error: "unsupported_tool" };
|
|
461
|
+
}
|
|
462
|
+
const payload = Buffer.from(JSON.stringify({ op, args: validatedArgs }), "utf-8").toString("base64");
|
|
463
|
+
if (payload.length > SANDBOX_OUTPUT_LIMITS.maxArgvBytes) {
|
|
464
|
+
return { ok: false, error: "content_too_large" };
|
|
465
|
+
}
|
|
466
|
+
return {
|
|
467
|
+
ok: true,
|
|
468
|
+
argv: ["bun", SANDBOX_HELPER_PATH, payload]
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function parseToolOutput(stdout) {
|
|
472
|
+
if (typeof stdout !== "string") {
|
|
473
|
+
return { ok: false, error: "invalid_tool_output" };
|
|
474
|
+
}
|
|
475
|
+
const NL = String.fromCharCode(10);
|
|
476
|
+
const lines = stdout.trim().split(NL).map((l) => l.trim()).filter(Boolean);
|
|
477
|
+
if (lines.length === 0) {
|
|
478
|
+
return { ok: false, error: "empty_tool_output" };
|
|
479
|
+
}
|
|
480
|
+
let parsed;
|
|
481
|
+
try {
|
|
482
|
+
parsed = JSON.parse(lines[lines.length - 1]);
|
|
483
|
+
} catch {
|
|
484
|
+
return { ok: false, error: "json_parse_failed" };
|
|
485
|
+
}
|
|
486
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
487
|
+
return { ok: false, error: "invalid_helper_output" };
|
|
488
|
+
}
|
|
489
|
+
const record = parsed;
|
|
490
|
+
const keys = Object.keys(record).sort();
|
|
491
|
+
if (record.ok === true) {
|
|
492
|
+
if (keys.length !== 2 || keys[0] !== "ok" || keys[1] !== "value") {
|
|
493
|
+
return { ok: false, error: "invalid_helper_output" };
|
|
494
|
+
}
|
|
495
|
+
return { ok: true, value: record.value };
|
|
496
|
+
}
|
|
497
|
+
if (record.ok === false) {
|
|
498
|
+
if (keys.length !== 2 || keys[0] !== "error" || keys[1] !== "ok" || typeof record.error !== "string" || !record.error) {
|
|
499
|
+
return { ok: false, error: "invalid_helper_output" };
|
|
500
|
+
}
|
|
501
|
+
return { ok: false, error: record.error };
|
|
502
|
+
}
|
|
503
|
+
return { ok: false, error: "invalid_helper_output" };
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// packages/agent-runtime/docker/toolRouting.ts
|
|
507
|
+
var dockerExecutionToolNames = [
|
|
508
|
+
"execShell",
|
|
509
|
+
"readFile",
|
|
510
|
+
"writeFile",
|
|
511
|
+
"editFile",
|
|
512
|
+
"globFiles",
|
|
513
|
+
"grepFiles"
|
|
514
|
+
];
|
|
515
|
+
var deny = (error) => JSON.stringify({ ok: false, error, workloadLocation: "docker" });
|
|
516
|
+
function describeDockerBackendFailure(record) {
|
|
517
|
+
if (record.exitCode === 0) {
|
|
518
|
+
return record.ok === false ? "docker_backend_rejected" : "docker_backend_invalid_envelope";
|
|
519
|
+
}
|
|
520
|
+
if (typeof record.error === "string" && record.error) return "docker_backend_rejected";
|
|
521
|
+
if (record.exitCode === 127) return "docker_helper_not_found";
|
|
522
|
+
if (record.exitCode === 126) return "docker_helper_not_executable";
|
|
523
|
+
if (typeof record.exitCode === "number" && Number.isSafeInteger(record.exitCode) && record.exitCode !== 0) {
|
|
524
|
+
return `docker_tool_exit_code:${record.exitCode}`;
|
|
525
|
+
}
|
|
526
|
+
return record.ok === false ? "docker_backend_rejected" : "docker_backend_invalid_envelope";
|
|
527
|
+
}
|
|
528
|
+
function createDockerToolChannel(runGrant, backend) {
|
|
529
|
+
const ticket = buildPrimaryExecutionTicket(runGrant, "oneshot");
|
|
530
|
+
return async (toolName, args, signal) => {
|
|
531
|
+
if (!dockerExecutionToolNames.includes(toolName)) {
|
|
532
|
+
return deny("docker_tool_not_supported");
|
|
533
|
+
}
|
|
534
|
+
if (!ticket.toolNames.includes(toolName)) {
|
|
535
|
+
return deny("docker_tool_not_authorized");
|
|
536
|
+
}
|
|
537
|
+
if (toolName === "execShell") {
|
|
538
|
+
if (!ticket.shellAllowed) {
|
|
539
|
+
return deny("docker_tool_not_authorized");
|
|
540
|
+
}
|
|
541
|
+
if (Object.keys(args).some((key) => !["command", "cwd"].includes(key)) || typeof args.command !== "string" || !args.command.trim() || args.cwd !== void 0 && typeof args.cwd !== "string") {
|
|
542
|
+
return deny("docker_tool_arguments_not_supported");
|
|
543
|
+
}
|
|
544
|
+
if (isDestructiveShellCommand({ command: args.command })) return deny("docker_destructive_command_not_supported");
|
|
545
|
+
if (signal?.aborted) return deny("docker_execution_aborted");
|
|
546
|
+
if (!backend) return deny("docker_execution_not_ready");
|
|
547
|
+
if (!backend.supportedToolNames.includes(toolName)) return deny("docker_backend_tool_not_supported");
|
|
548
|
+
try {
|
|
549
|
+
return await backend.execute({
|
|
550
|
+
ticket: structuredClone(ticket),
|
|
551
|
+
command: args.command,
|
|
552
|
+
...typeof args.cwd === "string" ? { cwd: args.cwd } : {},
|
|
553
|
+
...signal ? { signal } : {}
|
|
554
|
+
});
|
|
555
|
+
} catch {
|
|
556
|
+
return deny("docker_execution_failed");
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
const invocation = buildToolInvocation(toolName, args);
|
|
560
|
+
if (!invocation.ok) {
|
|
561
|
+
return deny(invocation.error);
|
|
562
|
+
}
|
|
563
|
+
if (signal?.aborted) return deny("docker_execution_aborted");
|
|
564
|
+
if (!backend) return deny("docker_execution_not_ready");
|
|
565
|
+
if (!backend.supportedToolNames.includes(toolName)) return deny("docker_backend_tool_not_supported");
|
|
566
|
+
try {
|
|
567
|
+
const rawResult = await backend.execute({
|
|
568
|
+
ticket: structuredClone(ticket),
|
|
569
|
+
kind: "command",
|
|
570
|
+
argv: invocation.argv,
|
|
571
|
+
command: invocation.argv.join(" "),
|
|
572
|
+
...signal ? { signal } : {}
|
|
573
|
+
});
|
|
574
|
+
let stdout = rawResult;
|
|
575
|
+
let parsedRaw;
|
|
576
|
+
try {
|
|
577
|
+
parsedRaw = JSON.parse(rawResult);
|
|
578
|
+
} catch {
|
|
579
|
+
parsedRaw = void 0;
|
|
580
|
+
}
|
|
581
|
+
if (parsedRaw !== void 0 && typeof parsedRaw === "object" && parsedRaw !== null && !Array.isArray(parsedRaw)) {
|
|
582
|
+
const record = parsedRaw;
|
|
583
|
+
const envelope = record.output;
|
|
584
|
+
if (typeof envelope === "object" && envelope !== null && !Array.isArray(envelope)) {
|
|
585
|
+
const stdoutField = envelope.stdout;
|
|
586
|
+
if (record.ok !== true || record.exitCode !== 0 || typeof stdoutField !== "string") {
|
|
587
|
+
return deny(describeDockerBackendFailure(record));
|
|
588
|
+
}
|
|
589
|
+
stdout = stdoutField;
|
|
590
|
+
} else if (record.ok === false) {
|
|
591
|
+
return deny(describeDockerBackendFailure(record));
|
|
592
|
+
} else if (typeof record.ok !== "boolean") {
|
|
593
|
+
return deny("invalid_helper_output");
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
const output = parseToolOutput(stdout);
|
|
597
|
+
if (!output.ok) {
|
|
598
|
+
return deny(output.error);
|
|
599
|
+
}
|
|
600
|
+
const payload = typeof output.value === "object" && output.value !== null ? { ok: true, ...output.value, value: output.value, workloadLocation: "docker" } : { ok: true, value: output.value, workloadLocation: "docker" };
|
|
601
|
+
return JSON.stringify(payload);
|
|
602
|
+
} catch {
|
|
603
|
+
return deny("docker_execution_failed");
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
export {
|
|
609
|
+
SANDBOX_WORKSPACE_ROOT,
|
|
610
|
+
buildSandboxHelperUploadArgv,
|
|
611
|
+
buildPrimaryExecutionTicket,
|
|
612
|
+
dockerExecutionToolNames,
|
|
613
|
+
createDockerToolChannel
|
|
614
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mergeAvailabilityDeadline,
|
|
3
3
|
resolveCredentialKeyWithFallback
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3MZAGMYY.js";
|
|
5
5
|
|
|
6
6
|
// packages/agent-runtime/credentialAvailability.ts
|
|
7
7
|
import { homedir } from "node:os";
|
|
@@ -51,12 +51,14 @@ function normalizeEntry(entry) {
|
|
|
51
51
|
if (!entry || typeof entry !== "object") return void 0;
|
|
52
52
|
const at = entry.nextAvailableAt;
|
|
53
53
|
if (typeof at !== "number" || !Number.isFinite(at)) return void 0;
|
|
54
|
+
const marked = entry.markedAt;
|
|
55
|
+
const markedAt = typeof marked === "number" && Number.isFinite(marked) ? { markedAt: marked } : {};
|
|
54
56
|
if ("lastProbeAt" in entry) {
|
|
55
57
|
const probe = entry.lastProbeAt;
|
|
56
58
|
if (typeof probe !== "number" || !Number.isFinite(probe)) return void 0;
|
|
57
|
-
return { nextAvailableAt: at, lastProbeAt: probe };
|
|
59
|
+
return { nextAvailableAt: at, ...markedAt, lastProbeAt: probe };
|
|
58
60
|
}
|
|
59
|
-
return { nextAvailableAt: at };
|
|
61
|
+
return { nextAvailableAt: at, ...markedAt };
|
|
60
62
|
}
|
|
61
63
|
async function readCredentialAvailability(env = process.env, now = Date.now()) {
|
|
62
64
|
const entries = await readCredentialEntries(env, now);
|
|
@@ -88,10 +90,19 @@ async function markCredentialUnavailable(credentialKey, nextAvailableAt, env = p
|
|
|
88
90
|
if (typeof merged !== "number" || !Number.isFinite(merged)) return;
|
|
89
91
|
live[credentialKey] = {
|
|
90
92
|
nextAvailableAt: merged,
|
|
93
|
+
markedAt: now,
|
|
91
94
|
...existing?.lastProbeAt !== void 0 ? { lastProbeAt: existing.lastProbeAt } : {}
|
|
92
95
|
};
|
|
93
96
|
await writeCredentialAvailability(live, env);
|
|
94
97
|
}
|
|
98
|
+
async function clearCredentialAvailabilityIfMarkedAt(credentialKey, expectedMarkedAt, env = process.env, now = Date.now()) {
|
|
99
|
+
if (!credentialKey) return;
|
|
100
|
+
const live = await readCredentialEntries(env, now);
|
|
101
|
+
const existing = live[credentialKey];
|
|
102
|
+
if (!existing || existing.markedAt !== expectedMarkedAt) return;
|
|
103
|
+
delete live[credentialKey];
|
|
104
|
+
await writeCredentialAvailability(live, env);
|
|
105
|
+
}
|
|
95
106
|
async function clearCredentialAvailability(credentialKey, env = process.env, now = Date.now()) {
|
|
96
107
|
if (!credentialKey) return;
|
|
97
108
|
const live = await readCredentialEntries(env, now);
|
|
@@ -129,6 +140,7 @@ export {
|
|
|
129
140
|
readCredentialAvailability,
|
|
130
141
|
readCredentialEntry,
|
|
131
142
|
markCredentialUnavailable,
|
|
143
|
+
clearCredentialAvailabilityIfMarkedAt,
|
|
132
144
|
clearCredentialAvailability,
|
|
133
145
|
recordCredentialProbe,
|
|
134
146
|
applyCredentialAvailability
|