nolo-cli 0.155.0-alpha.1 → 0.155.0
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-UWUM5QKW.js → _executeModel-3HHZYHHB.js} +54 -54
- package/{accountResolver-7RYB4D2P.js → accountResolver-55EDKEIK.js} +1 -1
- package/{action-SXJD5N5R.js → action-GPPJC5TI.js} +5 -5
- package/{addContentAction-65ONHX2T.js → addContentAction-XJQEJ4XW.js} +8 -8
- package/{addDialogAgentAction-WOLK7RB4.js → addDialogAgentAction-5WZX5CAY.js} +7 -7
- package/{agentDeleteCommand-FRPRYY4N.js → agentDeleteCommand-74EL5T7G.js} +74 -75
- package/{agentEmailCommands-TMP7BKVS.js → agentEmailCommands-ST7HL3E7.js} +77 -78
- package/{agentListCommands-G36AMSBR.js → agentListCommands-L33M3I6V.js} +35 -35
- package/{agentMachineCommands-CAWH6B4N.js → agentMachineCommands-JSQPNSS5.js} +34 -31
- package/{agentProviderCommands-X2HQE6HY.js → agentProviderCommands-CXBHNONN.js} +5 -5
- package/{agentPullCommand-FA43RBRU.js → agentPullCommand-GXXEDOSA.js} +4 -4
- package/{agentRecordCommands-NRUEGQO6.js → agentRecordCommands-JWW5NQQ7.js} +71 -72
- package/{agentRunCommand-MTUMHPBF.js → agentRunCommand-UTBBUSHP.js} +74 -74
- package/{agentRunControl-2C5GM3BW.js → agentRunControl-XBSNHHZE.js} +7 -7
- package/{agentRuntimeLocal-Q7ZOMZC7.js → agentRuntimeLocal-XCKO5FVP.js} +20 -18
- package/{agentSlice-RKEZWJZL.js → agentSlice-YT3VCCEW.js} +8 -8
- package/{appDeleteCommands-MMWT54BR.js → appDeleteCommands-2PJFNLAJ.js} +30 -28
- package/{appDeployCommands-OIFXVDOF.js → appDeployCommands-AZCMCMK6.js} +30 -28
- package/{appDeployStatusCommands-OTXMSDFB.js → appDeployStatusCommands-HSIKPVJN.js} +30 -28
- package/{appGetCommands-JPY36ANL.js → appGetCommands-IUZCPAP7.js} +30 -28
- package/{appListCommands-IHJGN36O.js → appListCommands-JLFVS44M.js} +30 -28
- package/{authCommand-J3XILHWW.js → authCommand-3Z52KJID.js} +22 -302
- package/{authCommands-77CHYBGF.js → authCommands-QOCKVPX3.js} +5 -5
- package/{builtinSkillRegistry-A6VSPJEJ.js → builtinSkillRegistry-LJV7FHNI.js} +4 -4
- package/{chromeCommands-OBBNJCLS.js → chromeCommands-IY4NVSXZ.js} +17 -10
- package/{chunk-SW4S4XYB.js → chunk-2AB2HA4M.js} +84 -34
- package/{chunk-FDT27L7S.js → chunk-2XDQAWBM.js} +18 -16
- package/{chunk-AHSHCC2V.js → chunk-2ZYCNT2O.js} +232 -76
- package/{chunk-QFEW2ULV.js → chunk-32ZKZET7.js} +1 -1
- package/{chunk-WHLTTNKZ.js → chunk-3GTVM7NJ.js} +22 -22
- package/{chunk-XPWGOTBQ.js → chunk-3L2WKC3W.js} +1 -8
- package/{chunk-LGCICX53.js → chunk-3L5MSPWX.js} +1 -1
- package/{chunk-4YRTZIVN.js → chunk-43OFVLWJ.js} +6 -6
- package/{chunk-6TF64IF2.js → chunk-4L4K6YR7.js} +16 -2
- package/{chunk-P5QACQDK.js → chunk-62TBKWTV.js} +1 -1
- package/{chunk-TRW43TSC.js → chunk-6EQD4AQL.js} +41 -1
- package/{chunk-YLMMECCH.js → chunk-6XIE5ZGI.js} +1 -1
- package/{chunk-UUPR3TD7.js → chunk-7RF4O6AT.js} +1 -3
- package/{chunk-OGI4JKBD.js → chunk-BAWAKW7X.js} +2 -2
- package/{chunk-2GGXHQIW.js → chunk-BLVSFYQ3.js} +4 -2
- package/{chunk-XZ6QGCBU.js → chunk-BMCPKNL2.js} +7 -7
- package/{chunk-RYCZTKFM.js → chunk-BO3ARJRK.js} +825 -688
- package/{chunk-A7HQF6YH.js → chunk-CDLP56BS.js} +9 -9
- package/{chunk-5MM7NNO6.js → chunk-CNWKLQRL.js} +8 -3
- package/{chunk-ITECOZFT.js → chunk-CXCMXNME.js} +134 -126
- package/{chunk-TJ2VPCBE.js → chunk-DD2EOI6S.js} +2 -2
- package/{chunk-36OMEXXR.js → chunk-DLV3H464.js} +8 -8
- package/{chunk-KO4VPOIN.js → chunk-DT7EWFTY.js} +6 -6
- package/{chunk-C5DLHL3R.js → chunk-ESMZW5PE.js} +3 -3
- package/{chunk-PSJWPSKS.js → chunk-EWO77ZGF.js} +9 -43
- package/{chunk-ZWG3C7VI.js → chunk-F3SOW2EU.js} +81 -1
- package/{chunk-ZJWUXAJ7.js → chunk-F5WASHQA.js} +271 -138
- package/{chunk-VOEJ7EMJ.js → chunk-FB5WLEOD.js} +21 -17
- package/{chunk-TENH5FPC.js → chunk-FCUKCVKN.js} +12 -8
- package/{chunk-FY4SDK2E.js → chunk-FDLDMJTM.js} +1 -1
- package/{chunk-EM3YOZJ4.js → chunk-FFHV45HO.js} +3 -3
- package/{chunk-D3AN5D3L.js → chunk-FZYKQFBQ.js} +3 -3
- package/{chunk-7KYVUFDG.js → chunk-G3VYRPTV.js} +5 -267
- package/{chunk-6MJNEXUU.js → chunk-HGDKT2D6.js} +4 -0
- package/{chunk-2KKTIPQ3.js → chunk-HW7EBEC5.js} +35 -207
- package/{chunk-B2EGWZJG.js → chunk-I7S63QUU.js} +1 -1
- package/{chunk-PDJ6ZODI.js → chunk-IF7V3CBU.js} +1 -1
- package/{chunk-T6CBQ6BN.js → chunk-INFHX73M.js} +1 -1
- package/{chunk-YBNHPX4S.js → chunk-IW64YHXL.js} +155 -31
- package/{chunk-RV3PVWWL.js → chunk-JDKSYQQN.js} +5 -5
- package/{chunk-K43ZF2C3.js → chunk-JPPQ3GUO.js} +1 -1
- package/{chunk-VEJFPTX7.js → chunk-JWEXJ573.js} +3 -3
- package/{chunk-ZG73GDYU.js → chunk-K25WQPP3.js} +253 -57
- package/{chunk-HKT6QXP3.js → chunk-KABQ74UQ.js} +5 -5
- package/{chunk-I2ZMGXXF.js → chunk-KFHREHUQ.js} +1 -1
- package/{chunk-3C2QLERX.js → chunk-KMDDG73K.js} +1 -1
- package/{chunk-AIZE5TDM.js → chunk-MAYW6V3E.js} +2 -2
- package/{chunk-IPAW7XLD.js → chunk-MFVOJ6KF.js} +2 -2
- package/{chunk-CBHGZRCE.js → chunk-MYOH447Z.js} +1 -1
- package/{chunk-TPG4CZHI.js → chunk-NHEWV5FD.js} +17 -3
- package/{chunk-G47IPDOK.js → chunk-O2IWR23M.js} +1 -1
- package/{chunk-H3KW6W64.js → chunk-OLVOR45M.js} +2 -2
- package/{chunk-OHUFHV3U.js → chunk-OWCHFPWR.js} +17 -16
- package/{chunk-SUKSWFLP.js → chunk-PIG2IUVZ.js} +1 -1
- package/{chunk-SEJ5OS6F.js → chunk-PXYBUFDB.js} +4 -0
- package/{chunk-2MTE2PEH.js → chunk-QA2C5NKI.js} +5 -739
- package/{chunk-TYND6RDQ.js → chunk-QI2WVWXV.js} +73 -2
- package/{chunk-L6EQV5OC.js → chunk-QXZH5UDF.js} +3 -3
- package/{chunk-4ZSZP7PY.js → chunk-QZIOZDM6.js} +10 -10
- package/{chunk-K2XCMQMM.js → chunk-R2KWTENX.js} +3 -3
- package/{chunk-TNIX77YM.js → chunk-R5GO3YZP.js} +34 -1
- package/{chunk-UTIMX333.js → chunk-RIHQGFFA.js} +1 -1
- package/{chunk-4Z245KOA.js → chunk-SH3XD4E2.js} +8 -4
- package/{chunk-MM3662RS.js → chunk-SNAWGDXT.js} +263 -4
- package/{chunk-JGRPBIZZ.js → chunk-SQX235S2.js} +1 -1
- package/chunk-TT644UJD.js +188 -0
- package/{chunk-IYBIRCQV.js → chunk-U34KT53V.js} +29 -11
- package/{chunk-ANJTRG52.js → chunk-ULQAD7ZY.js} +18 -43
- package/{chunk-I2RMFLLH.js → chunk-V7PCFWX3.js} +1 -1
- package/{chunk-KX6LPG7W.js → chunk-VXS4YYJ2.js} +8 -8
- package/{chunk-HXHSTRGH.js → chunk-VYNMQ6HW.js} +0 -27
- package/{chunk-IJERIUXS.js → chunk-WRCZXJ4N.js} +6 -3
- package/chunk-Y5GCAMGP.js +9 -0
- package/{chunk-JZX2XLKC.js → chunk-YCRROBDY.js} +1 -1
- package/{chunk-EYWJT7A2.js → chunk-YPG7TUQD.js} +3 -3
- package/chunk-YR47Y7CN.js +2685 -0
- package/{chunk-NS2WBMJT.js → chunk-ZAV4YVEA.js} +18 -2
- package/{chunk-YANF2RR4.js → chunk-ZPKUJROL.js} +1 -1
- package/{commandRegistry-O335ZA5D.js → commandRegistry-HPL2KOVB.js} +88 -96
- package/{contentThunks-6GWTLD5V.js → contentThunks-QBL5NK2W.js} +21 -21
- package/{createAgentAutomationAction-3WJWXWWA.js → createAgentAutomationAction-5UWBLR2N.js} +21 -21
- package/{createDialogAction-VEX236QX.js → createDialogAction-NJ2LE7KC.js} +25 -25
- package/{createPageAction-65CX7QH6.js → createPageAction-7T3RINS2.js} +24 -25
- package/{dbSlice-S2HYXURM.js → dbSlice-6PVPY44C.js} +7 -7
- package/{deleteFile-6JWDDRVP.js → deleteFile-YM6NDPAR.js} +5 -5
- package/{dialogCommands-H3K7PTF6.js → dialogCommands-KMECTGCW.js} +34 -31
- package/{dialogSlice-AHU5PNUQ.js → dialogSlice-GQMTD4HR.js} +20 -20
- package/{dist-NJC2W7I4.js → dist-Q2JSMAKA.js} +7 -361
- package/{docCreateCommands-KP64KMVL.js → docCreateCommands-4IT5PUAL.js} +31 -29
- package/{docDeleteCommands-C3F4SZSR.js → docDeleteCommands-QS66YNZV.js} +32 -30
- package/{docReadCommands-7H6BDOUR.js → docReadCommands-3SAI46YC.js} +31 -29
- package/{docStore-WROLAUBT.js → docStore-PM5PYKPZ.js} +8 -8
- package/{docUpdateCommands-JDW4BRBH.js → docUpdateCommands-OGYG5BRC.js} +31 -29
- package/{getPricing-TX35D7PI.js → getPricing-XQ3N3RBP.js} +2 -2
- package/{handleSendMessageAction-OK3GHWHR.js → handleSendMessageAction-EQ3U6K5N.js} +43 -39
- package/index.js +8 -8
- package/{localRuntimeAdapter-ARIAVQ4O.js → localRuntimeAdapter-74L7FLMW.js} +69 -68
- package/{localRuntimeAuthority-JDAD7CB6.js → localRuntimeAuthority-BPN5OAQG.js} +2 -2
- package/{localRuntimeDb-CVC62PM5.js → localRuntimeDb-QIVAXMUL.js} +1 -1
- package/{machineCommands-ZTAJYKQM.js → machineCommands-BUZTMLYD.js} +79 -78
- package/{machineWsRunDispatch-JIODLHZZ.js → machineWsRunDispatch-CCDVG5AO.js} +69 -70
- package/{memberThunks-VPTET5M2.js → memberThunks-AZINUM4S.js} +10 -10
- package/package.json +6 -2
- package/{profileConfig-ZGOFORWV.js → profileConfig-KN3N2BLF.js} +7 -1
- package/{providerPresetApply-CRZFMQD5.js → providerPresetApply-PKUOHQJT.js} +5 -5
- package/{providerRegistry-7IS43D3X.js → providerRegistry-HNQLIFN2.js} +5 -5
- package/{read-VMMIHEAK.js → read-7JPIWRBQ.js} +5 -5
- package/{readDocTool-4XSLKYSQ.js → readDocTool-AAQTB2Y3.js} +1 -1
- package/{readlineWorkspace-24O4OG6C.js → readlineWorkspace-MS2ZIQ2P.js} +374 -199
- package/{removeDialogAgentAction-YIV37ENV.js → removeDialogAgentAction-RMVRILLK.js} +9 -9
- package/{runAgentClientLoop-WWE753AB.js → runAgentClientLoop-EXIQDX7G.js} +58 -53
- package/{runtimeDoctorCommands-56NWKNON.js → runtimeDoctorCommands-MMCP4B4U.js} +12 -12
- package/{secretCommands-ZXZRLR3R.js → secretCommands-DNY56NSU.js} +11 -1
- package/{setDialogExtraReferencesAction-FWVD656I.js → setDialogExtraReferencesAction-L3V7JTMG.js} +8 -8
- package/{setPrimaryDialogAgentAction-HIPQTT6N.js → setPrimaryDialogAgentAction-X52JQGTJ.js} +9 -9
- package/settingThunks-N6XFWPOU.js +923 -0
- package/{spaceCommands-JQN7D4FE.js → spaceCommands-WQMUCGV7.js} +28 -26
- package/{streamAgentChatTurn-YD65RR4J.js → streamAgentChatTurn-DI2334G3.js} +153 -94
- package/{switchDialogAgentAction-SLTPB635.js → switchDialogAgentAction-ZJ5CGU7J.js} +7 -7
- package/{tableCommands-U3QDY4L6.js → tableCommands-IVC5S7Y3.js} +11 -11
- package/{toolApiClient-7WSJJJBV.js → toolApiClient-HGNO53TC.js} +2 -2
- package/{tools-ZDLAPPTQ.js → tools-23VQGJOX.js} +42 -43
- package/{tuiSummaryLlmCaller-KLK6K3Q3.js → tuiSummaryLlmCaller-FESHBDTT.js} +7 -7
- package/{updateCommands-NQXAGFM7.js → updateCommands-FJHGWD3Q.js} +5 -3
- package/{updateDialogTitleAction-RQEO5PNQ.js → updateDialogTitleAction-AGAYHWS7.js} +21 -21
- package/{workloadLifecycle-36DXRZKU.js → workloadLifecycle-6O6PMISX.js} +2 -2
- package/chunk-GW7LIREE.js +0 -7012
- package/chunk-IA7TRNNR.js +0 -11
- package/chunk-UKZX3NHN.js +0 -48
- package/chunk-W4S6OTSC.js +0 -35
- package/clipboardy-GCO3GT3I.js +0 -11793
- package/settingThunks-SB37UY4C.js +0 -1371
- package/{agentGrantCommands-HOJ3JBBQ.js → agentGrantCommands-5DPHYEKP.js} +3 -3
- package/{chromeOpsCommands-3Z34RKSE.js → chromeOpsCommands-GZVVK7HU.js} +4 -4
- package/{chunk-XETG4RIX.js → chunk-AETZ7AD6.js} +4 -4
- package/{chunk-2IXDJNZI.js → chunk-GAGGEA7D.js} +3 -3
- package/{memoryCommands-CUNBFRVS.js → memoryCommands-ZS3VQJAL.js} +3 -3
- package/{offlineMarxistsAgentCommand-2QTHJCHV.js → offlineMarxistsAgentCommand-3GLX4QQY.js} +3 -3
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
anthropicRefresh,
|
|
3
3
|
cursorRefresh,
|
|
4
|
-
getWorkBuddyHeaders,
|
|
5
4
|
refreshAntigravityOAuthToken,
|
|
6
5
|
refreshOpenAiCodexToken,
|
|
7
6
|
resolveServerSyncConfig,
|
|
8
|
-
workbuddyRefresh,
|
|
9
7
|
xaiRefresh
|
|
10
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-G3VYRPTV.js";
|
|
11
9
|
import {
|
|
12
10
|
clearCredentialAvailability,
|
|
13
11
|
markCredentialUnavailable,
|
|
@@ -18,14 +16,14 @@ import {
|
|
|
18
16
|
import {
|
|
19
17
|
agentRunCardLabels,
|
|
20
18
|
t
|
|
21
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-2AB2HA4M.js";
|
|
22
20
|
import {
|
|
23
21
|
defaultLoopbackRequest
|
|
24
22
|
} from "./chunk-VP3BINY7.js";
|
|
25
23
|
import {
|
|
26
24
|
OAUTH_PROVIDER_REFS,
|
|
27
25
|
buildLocalAgentLookupKeys
|
|
28
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-7RF4O6AT.js";
|
|
29
27
|
import {
|
|
30
28
|
LOCAL_CODEX_AGENT_ID,
|
|
31
29
|
LOCAL_CODEX_AGENT_KEY,
|
|
@@ -41,10 +39,14 @@ import {
|
|
|
41
39
|
isCursorOAuthAgent
|
|
42
40
|
} from "./chunk-VIWDGTDA.js";
|
|
43
41
|
import {
|
|
42
|
+
SANDBOX_HELPER_PATH,
|
|
43
|
+
SANDBOX_OUTPUT_LIMITS,
|
|
44
44
|
SANDBOX_WORKSPACE_ROOT,
|
|
45
45
|
buildSandboxHelperUploadArgv,
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
buildWorkspaceHelperSource,
|
|
47
|
+
dockerExecutionToolNames,
|
|
48
|
+
parseToolOutput
|
|
49
|
+
} from "./chunk-HGDKT2D6.js";
|
|
48
50
|
import {
|
|
49
51
|
createChromeConnectorClientResolver,
|
|
50
52
|
createVerifiedChromeConnectorClient,
|
|
@@ -52,17 +54,17 @@ import {
|
|
|
52
54
|
} from "./chunk-BU2YQBV4.js";
|
|
53
55
|
import {
|
|
54
56
|
applyPublicAgentCatalogOverride
|
|
55
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-MFVOJ6KF.js";
|
|
56
58
|
import {
|
|
57
59
|
buildCliPrompt
|
|
58
60
|
} from "./chunk-ATNTHIZI.js";
|
|
59
61
|
import {
|
|
60
62
|
inferCaptureIntent
|
|
61
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-INFHX73M.js";
|
|
62
64
|
import {
|
|
63
65
|
inlineImageUrlsForCustomProvider,
|
|
64
66
|
prepareTools
|
|
65
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-OLVOR45M.js";
|
|
66
68
|
import {
|
|
67
69
|
getServerProviderSecret
|
|
68
70
|
} from "./chunk-HS7MLR74.js";
|
|
@@ -84,18 +86,18 @@ import {
|
|
|
84
86
|
resolveCliLocalRuntimeKeyCapability,
|
|
85
87
|
resolveCliLocalSpawnDispatch,
|
|
86
88
|
resolveStartAgentRunCwd
|
|
87
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-2ZYCNT2O.js";
|
|
88
90
|
import {
|
|
89
91
|
deriveCredentialGroup,
|
|
90
92
|
deriveCustomProviderCredentialGroup
|
|
91
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-VXS4YYJ2.js";
|
|
92
94
|
import {
|
|
93
95
|
fetchWithTransientRetry,
|
|
94
96
|
isTransientFetchError
|
|
95
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-KFHREHUQ.js";
|
|
96
98
|
import {
|
|
97
99
|
resolveAgentRequiredPackIds
|
|
98
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-FCUKCVKN.js";
|
|
99
101
|
import {
|
|
100
102
|
applyBuiltinAgentRuntimeOverride,
|
|
101
103
|
applyTokenUsageToDayStats,
|
|
@@ -104,17 +106,14 @@ import {
|
|
|
104
106
|
resolveBuiltinPlatformAgentConfig,
|
|
105
107
|
runKeyed,
|
|
106
108
|
validateAskChoiceInput
|
|
107
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-F5WASHQA.js";
|
|
108
110
|
import {
|
|
109
111
|
BUILTIN_DIALOG_LLM_CHAT_FALLBACK_MODEL,
|
|
110
112
|
BUILTIN_TITLE_LLM_CONFIG
|
|
111
113
|
} from "./chunk-523DITKR.js";
|
|
112
|
-
import {
|
|
113
|
-
isOAuthApiKeyRef
|
|
114
|
-
} from "./chunk-UKZX3NHN.js";
|
|
115
114
|
import {
|
|
116
115
|
fetchServerSyncedCredential
|
|
117
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-DT7EWFTY.js";
|
|
118
117
|
import {
|
|
119
118
|
isTombstoneRecord
|
|
120
119
|
} from "./chunk-D2MDMY2M.js";
|
|
@@ -127,7 +126,7 @@ import {
|
|
|
127
126
|
applySystemBuiltinSkillFilter,
|
|
128
127
|
expandEnabledPacks,
|
|
129
128
|
resolveEffectiveEnabledPacks
|
|
130
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-YCRROBDY.js";
|
|
131
130
|
import {
|
|
132
131
|
DEFAULT_HYBRID_READ_TIMEOUT_MS,
|
|
133
132
|
Duration_exports,
|
|
@@ -171,7 +170,7 @@ import {
|
|
|
171
170
|
runExecShellGates,
|
|
172
171
|
validateConfiguredRootExecutionLease,
|
|
173
172
|
verifyOwnerRouteAck
|
|
174
|
-
} from "./chunk-
|
|
173
|
+
} from "./chunk-K25WQPP3.js";
|
|
175
174
|
import {
|
|
176
175
|
accumulateGeminiChunks,
|
|
177
176
|
buildGeminiGenerateContentRequest,
|
|
@@ -183,7 +182,7 @@ import {
|
|
|
183
182
|
resolveAntigravityFinishReason,
|
|
184
183
|
resolveGeminiModelQuirks,
|
|
185
184
|
shouldUseGeminiNativeToolRoute
|
|
186
|
-
} from "./chunk-
|
|
185
|
+
} from "./chunk-KMDDG73K.js";
|
|
187
186
|
import {
|
|
188
187
|
PlatformStreamInterruptedError,
|
|
189
188
|
buildPlatformChatCompletionRequest,
|
|
@@ -194,27 +193,24 @@ import {
|
|
|
194
193
|
readPlatformChatSseCompletion,
|
|
195
194
|
resolvePlatformChatProviderConfig,
|
|
196
195
|
shouldUsePlatformChatProvider
|
|
197
|
-
} from "./chunk-
|
|
196
|
+
} from "./chunk-QXZH5UDF.js";
|
|
198
197
|
import {
|
|
199
198
|
readSseDataValues,
|
|
200
199
|
readSseFrames
|
|
201
200
|
} from "./chunk-HNUWUO75.js";
|
|
202
201
|
import {
|
|
203
202
|
resolveAgentRuntimeConfigFromRecord
|
|
204
|
-
} from "./chunk-
|
|
205
|
-
import {
|
|
206
|
-
isDevinOAuthAgent
|
|
207
|
-
} from "./chunk-5ZUL4CUO.js";
|
|
203
|
+
} from "./chunk-ULQAD7ZY.js";
|
|
208
204
|
import {
|
|
209
205
|
resolveHistoricalToolContentCap
|
|
210
|
-
} from "./chunk-
|
|
206
|
+
} from "./chunk-U34KT53V.js";
|
|
211
207
|
import {
|
|
212
208
|
collectStablePromptPrefix,
|
|
213
209
|
convertMessagesToResponsesInput,
|
|
214
210
|
findAgentStatePairingIssues,
|
|
215
211
|
stablePromptCacheKey,
|
|
216
212
|
toResponsesTools
|
|
217
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-4L4K6YR7.js";
|
|
218
214
|
import {
|
|
219
215
|
buildNoloWorkspaceOpenAiTools,
|
|
220
216
|
parseNoloWorkspaceToolArguments,
|
|
@@ -231,15 +227,19 @@ import {
|
|
|
231
227
|
normalizeDialogTitle
|
|
232
228
|
} from "./chunk-2MBTWINN.js";
|
|
233
229
|
import {
|
|
230
|
+
isOAuthApiKeyRef,
|
|
234
231
|
normalizeUsage
|
|
235
|
-
} from "./chunk-
|
|
232
|
+
} from "./chunk-F3SOW2EU.js";
|
|
233
|
+
import {
|
|
234
|
+
isDevinOAuthAgent
|
|
235
|
+
} from "./chunk-5ZUL4CUO.js";
|
|
236
236
|
import {
|
|
237
237
|
createProviderCallTimingTracker,
|
|
238
238
|
finalizeProviderCallTiming,
|
|
239
239
|
observeMeaningfulProviderResponse,
|
|
240
240
|
observeMeaningfulProviderResponseAt,
|
|
241
241
|
withProviderCallTimingFields
|
|
242
|
-
} from "./chunk-
|
|
242
|
+
} from "./chunk-QA2C5NKI.js";
|
|
243
243
|
import {
|
|
244
244
|
clipCompactText
|
|
245
245
|
} from "./chunk-5MMAK75Q.js";
|
|
@@ -278,9 +278,6 @@ import {
|
|
|
278
278
|
dialogMessagePrefix,
|
|
279
279
|
dialogMessageRange
|
|
280
280
|
} from "./chunk-5EMSBTQ6.js";
|
|
281
|
-
import {
|
|
282
|
-
isAntigravityOAuthAgent
|
|
283
|
-
} from "./chunk-JGRPBIZZ.js";
|
|
284
281
|
import {
|
|
285
282
|
ackRunRecord,
|
|
286
283
|
appendRunQueue,
|
|
@@ -301,7 +298,7 @@ import {
|
|
|
301
298
|
terminateRunProcess,
|
|
302
299
|
transitionRunToTerminal,
|
|
303
300
|
withQueueLock
|
|
304
|
-
} from "./chunk-
|
|
301
|
+
} from "./chunk-SNAWGDXT.js";
|
|
305
302
|
import {
|
|
306
303
|
TASK_PREVIEW_MAX,
|
|
307
304
|
formatListRunsCard,
|
|
@@ -318,15 +315,36 @@ import {
|
|
|
318
315
|
import {
|
|
319
316
|
estimateTokenCount
|
|
320
317
|
} from "./chunk-PSCNXBYA.js";
|
|
318
|
+
import {
|
|
319
|
+
getDefaultCliLocalRuntimeDb
|
|
320
|
+
} from "./chunk-FDLDMJTM.js";
|
|
321
|
+
import {
|
|
322
|
+
getLogger
|
|
323
|
+
} from "./chunk-EYLGAEB4.js";
|
|
324
|
+
import {
|
|
325
|
+
isCompiledBinary,
|
|
326
|
+
parseUserIdFromAuthToken,
|
|
327
|
+
resolveAuthToken,
|
|
328
|
+
resolveServerUrl
|
|
329
|
+
} from "./chunk-A7GB5UGH.js";
|
|
330
|
+
import {
|
|
331
|
+
DEFAULT_NOLO_SERVER_URL
|
|
332
|
+
} from "./chunk-OLZBQWZU.js";
|
|
333
|
+
import {
|
|
334
|
+
NOLO_CLUSTER_SERVERS
|
|
335
|
+
} from "./chunk-LCBAMY2M.js";
|
|
336
|
+
import {
|
|
337
|
+
isAntigravityOAuthAgent
|
|
338
|
+
} from "./chunk-SQX235S2.js";
|
|
321
339
|
import {
|
|
322
340
|
buildProviderSessionHeaders,
|
|
323
341
|
resolvePlatformAuthToken
|
|
324
|
-
} from "./chunk-
|
|
342
|
+
} from "./chunk-PIG2IUVZ.js";
|
|
325
343
|
import {
|
|
326
344
|
anthropicOAuthModelMaxOutputTokens,
|
|
327
345
|
findModelConfig,
|
|
328
346
|
isAdaptiveThinkingModelId
|
|
329
|
-
} from "./chunk-
|
|
347
|
+
} from "./chunk-6EQD4AQL.js";
|
|
330
348
|
import {
|
|
331
349
|
CLI_PROVIDER_VALUES,
|
|
332
350
|
isCliProvider
|
|
@@ -340,24 +358,6 @@ import {
|
|
|
340
358
|
import {
|
|
341
359
|
toErrorMessage
|
|
342
360
|
} from "./chunk-HNMXYYJR.js";
|
|
343
|
-
import {
|
|
344
|
-
getDefaultCliLocalRuntimeDb
|
|
345
|
-
} from "./chunk-FY4SDK2E.js";
|
|
346
|
-
import {
|
|
347
|
-
getLogger
|
|
348
|
-
} from "./chunk-EYLGAEB4.js";
|
|
349
|
-
import {
|
|
350
|
-
isCompiledBinary,
|
|
351
|
-
parseUserIdFromAuthToken,
|
|
352
|
-
resolveAuthToken,
|
|
353
|
-
resolveServerUrl
|
|
354
|
-
} from "./chunk-A7GB5UGH.js";
|
|
355
|
-
import {
|
|
356
|
-
DEFAULT_NOLO_SERVER_URL
|
|
357
|
-
} from "./chunk-OLZBQWZU.js";
|
|
358
|
-
import {
|
|
359
|
-
NOLO_CLUSTER_SERVERS
|
|
360
|
-
} from "./chunk-LCBAMY2M.js";
|
|
361
361
|
import {
|
|
362
362
|
isLoopbackUrl
|
|
363
363
|
} from "./chunk-4SN6J65J.js";
|
|
@@ -3301,447 +3301,6 @@ var resolveDevinTransport = async (ctx) => {
|
|
|
3301
3301
|
return null;
|
|
3302
3302
|
};
|
|
3303
3303
|
|
|
3304
|
-
// packages/agent-runtime/workbuddyRequestAdapter.ts
|
|
3305
|
-
var DEFAULT_SYSTEM = "You are a helpful assistant.";
|
|
3306
|
-
var SAFE_NAME = /^[A-Za-z0-9_-]{1,64}$/;
|
|
3307
|
-
function record(value) {
|
|
3308
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3309
|
-
}
|
|
3310
|
-
function safeName(name, reserved) {
|
|
3311
|
-
const stem = name.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 48) || "tool";
|
|
3312
|
-
let candidate = stem;
|
|
3313
|
-
if (reserved.has(candidate)) {
|
|
3314
|
-
let suffix = 1;
|
|
3315
|
-
do
|
|
3316
|
-
candidate = `${stem.slice(0, 64 - String(suffix).length - 1)}_${suffix++}`;
|
|
3317
|
-
while (reserved.has(candidate));
|
|
3318
|
-
}
|
|
3319
|
-
reserved.add(candidate);
|
|
3320
|
-
return candidate;
|
|
3321
|
-
}
|
|
3322
|
-
function adaptSchema(schema, path) {
|
|
3323
|
-
if (!record(schema)) throw new TypeError(`${path} must be a JSON Schema object`);
|
|
3324
|
-
if (schema.type !== "object" && schema.type !== "array" && schema.type !== "string" && schema.type !== "number" && schema.type !== "integer" && schema.type !== "boolean" && schema.type !== "null" && schema.type !== void 0) throw new TypeError(`${path}.type is unsupported`);
|
|
3325
|
-
if (schema.properties !== void 0) {
|
|
3326
|
-
if (!record(schema.properties)) throw new TypeError(`${path}.properties must be an object`);
|
|
3327
|
-
for (const [key, value] of Object.entries(schema.properties)) adaptSchema(value, `${path}.properties.${key}`);
|
|
3328
|
-
}
|
|
3329
|
-
for (const key of ["items", "additionalProperties", "not", "if", "then", "else"]) {
|
|
3330
|
-
const value = schema[key];
|
|
3331
|
-
if (value === false || value === true) continue;
|
|
3332
|
-
if (record(value)) adaptSchema(value, `${path}.${key}`);
|
|
3333
|
-
else if (Array.isArray(value)) value.forEach((item, i) => adaptSchema(item, `${path}.${key}[${i}]`));
|
|
3334
|
-
}
|
|
3335
|
-
for (const key of ["oneOf", "anyOf", "allOf", "prefixItems"]) {
|
|
3336
|
-
if (schema[key] !== void 0) {
|
|
3337
|
-
if (!Array.isArray(schema[key])) throw new TypeError(`${path}.${key} must be an array`);
|
|
3338
|
-
schema[key].forEach((item, i) => adaptSchema(item, `${path}.${key}[${i}]`));
|
|
3339
|
-
}
|
|
3340
|
-
}
|
|
3341
|
-
}
|
|
3342
|
-
function adaptWorkBuddyRequest(body) {
|
|
3343
|
-
const adapted = structuredClone(body);
|
|
3344
|
-
const originalNames = /* @__PURE__ */ Object.create(null);
|
|
3345
|
-
const safeToOriginal = /* @__PURE__ */ new Map();
|
|
3346
|
-
const tools = adapted.tools;
|
|
3347
|
-
if (tools !== void 0 && !Array.isArray(tools)) throw new TypeError("tools must be an array");
|
|
3348
|
-
const reserved = /* @__PURE__ */ new Set();
|
|
3349
|
-
for (const tool of tools ?? []) {
|
|
3350
|
-
if (!record(tool) || !record(tool.function) || typeof tool.function.name !== "string") throw new TypeError("Each tool must have a named function");
|
|
3351
|
-
if (SAFE_NAME.test(tool.function.name)) reserved.add(tool.function.name);
|
|
3352
|
-
}
|
|
3353
|
-
for (const tool of tools ?? []) {
|
|
3354
|
-
const fn = tool.function;
|
|
3355
|
-
const original = fn.name;
|
|
3356
|
-
if (!SAFE_NAME.test(original)) {
|
|
3357
|
-
const safe = safeName(original, reserved);
|
|
3358
|
-
Object.defineProperty(originalNames, safe, { value: original, enumerable: true, configurable: true, writable: true });
|
|
3359
|
-
safeToOriginal.set(safe, original);
|
|
3360
|
-
fn.name = safe;
|
|
3361
|
-
}
|
|
3362
|
-
if (fn.parameters !== void 0) {
|
|
3363
|
-
if (!record(fn.parameters)) throw new TypeError(`Tool ${original} parameters must be a JSON Schema object`);
|
|
3364
|
-
adaptSchema(fn.parameters, `Tool ${original} parameters`);
|
|
3365
|
-
if (fn.parameters.type !== "object") throw new TypeError(`Tool ${original} parameters root must be type object`);
|
|
3366
|
-
}
|
|
3367
|
-
}
|
|
3368
|
-
const safeFor = (name) => typeof name === "string" ? [...safeToOriginal].find(([, original]) => original === name)?.[0] : void 0;
|
|
3369
|
-
if (Array.isArray(adapted.messages)) {
|
|
3370
|
-
for (const message of adapted.messages) {
|
|
3371
|
-
if (!record(message)) continue;
|
|
3372
|
-
if (message.role === "developer") message.role = "system";
|
|
3373
|
-
if (Array.isArray(message.tool_calls)) for (const call of message.tool_calls) {
|
|
3374
|
-
if (record(call) && record(call.function)) call.function.name = safeFor(call.function.name) ?? call.function.name;
|
|
3375
|
-
}
|
|
3376
|
-
if (message.role === "tool") message.name = safeFor(message.name) ?? message.name;
|
|
3377
|
-
}
|
|
3378
|
-
if (!adapted.messages.some((message) => record(message) && message.role === "system")) adapted.messages.unshift({ role: "system", content: DEFAULT_SYSTEM });
|
|
3379
|
-
} else adapted.messages = [{ role: "system", content: DEFAULT_SYSTEM }];
|
|
3380
|
-
const choice = adapted.tool_choice;
|
|
3381
|
-
if (choice === "none") delete adapted.tools;
|
|
3382
|
-
else if (record(choice) && record(choice.function)) choice.function.name = safeFor(choice.function.name) ?? choice.function.name;
|
|
3383
|
-
else if (typeof choice === "string" && !["auto", "required", "none"].includes(choice)) adapted.tool_choice = { type: "function", function: { name: safeFor(choice) ?? choice } };
|
|
3384
|
-
if (adapted.max_completion_tokens !== void 0) {
|
|
3385
|
-
if (adapted.max_tokens === void 0) adapted.max_tokens = adapted.max_completion_tokens;
|
|
3386
|
-
delete adapted.max_completion_tokens;
|
|
3387
|
-
}
|
|
3388
|
-
adapted.stream = true;
|
|
3389
|
-
return { body: adapted, originalNames };
|
|
3390
|
-
}
|
|
3391
|
-
function restoreWorkBuddyToolNames(payload, originalNames) {
|
|
3392
|
-
const copy = structuredClone(payload);
|
|
3393
|
-
if (!record(copy) || !Array.isArray(copy.choices)) return copy;
|
|
3394
|
-
for (const choice of copy.choices) for (const part of [choice?.delta, choice?.message]) {
|
|
3395
|
-
if (!record(part) || !Array.isArray(part.tool_calls)) continue;
|
|
3396
|
-
for (const call of part.tool_calls) {
|
|
3397
|
-
if (!record(call) || !record(call.function) || typeof call.function.name !== "string") continue;
|
|
3398
|
-
if (Object.prototype.hasOwnProperty.call(originalNames, call.function.name)) call.function.name = originalNames[call.function.name];
|
|
3399
|
-
}
|
|
3400
|
-
}
|
|
3401
|
-
return copy;
|
|
3402
|
-
}
|
|
3403
|
-
|
|
3404
|
-
// packages/cli/client/providerResolution/workbuddyTransport.ts
|
|
3405
|
-
var WORKBUDDY_ENDPOINTS = {
|
|
3406
|
-
workbuddy: "https://copilot.tencent.com/v2/chat/completions",
|
|
3407
|
-
"workbuddy-ai": "https://www.workbuddy.ai/v2/chat/completions"
|
|
3408
|
-
};
|
|
3409
|
-
function resolveWorkBuddySite(agentConfig) {
|
|
3410
|
-
const ref = agentConfig.apiKeyRef?.trim().toLowerCase();
|
|
3411
|
-
const prov = agentConfig.provider?.trim().toLowerCase();
|
|
3412
|
-
if (ref === "workbuddy-ai" || ref?.startsWith(["api-key", "workbuddy-ai"].join(":")) || prov === "workbuddy-ai") {
|
|
3413
|
-
return "workbuddy-ai";
|
|
3414
|
-
}
|
|
3415
|
-
if (ref === "workbuddy" || ref?.startsWith(["api-key", "workbuddy"].join(":")) || prov === "workbuddy") {
|
|
3416
|
-
return "workbuddy";
|
|
3417
|
-
}
|
|
3418
|
-
return null;
|
|
3419
|
-
}
|
|
3420
|
-
function record2(value) {
|
|
3421
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3422
|
-
}
|
|
3423
|
-
var QUOTA_EXCEEDED_MESSAGE = "WorkBuddy \u989D\u5EA6\u4E0D\u8DB3 (14018)\uFF1AWorkBuddy \u975E\u65E0\u9650\u514D\u8D39\u670D\u52A1\uFF0C\u5F53\u524D\u8D26\u53F7\u989D\u5EA6\u5DF2\u8017\u5C3D\u3002";
|
|
3424
|
-
function wrapWorkBuddySseResponse(response, names) {
|
|
3425
|
-
if (!response.body) return response;
|
|
3426
|
-
const decoder = new TextDecoder("utf-8");
|
|
3427
|
-
const encoder = new TextEncoder();
|
|
3428
|
-
let pending = "";
|
|
3429
|
-
let lines = [];
|
|
3430
|
-
const fragments = /* @__PURE__ */ new Map();
|
|
3431
|
-
const processEvent = () => {
|
|
3432
|
-
const dataLines = lines.filter((line) => line.startsWith("data:")).map((line) => line.slice(5).replace(/^ /, ""));
|
|
3433
|
-
const data = dataLines.join("\n");
|
|
3434
|
-
if (!data || data === "[DONE]") {
|
|
3435
|
-
const result = lines.join("\n") + "\n\n";
|
|
3436
|
-
lines = [];
|
|
3437
|
-
return result;
|
|
3438
|
-
}
|
|
3439
|
-
let payload;
|
|
3440
|
-
try {
|
|
3441
|
-
payload = JSON.parse(data);
|
|
3442
|
-
} catch {
|
|
3443
|
-
const result = lines.join("\n") + "\n\n";
|
|
3444
|
-
lines = [];
|
|
3445
|
-
return result;
|
|
3446
|
-
}
|
|
3447
|
-
if (record2(payload)) {
|
|
3448
|
-
if (payload.code === 14018 || payload.errcode === 14018 || record2(payload.error) && payload.error.code === 14018) {
|
|
3449
|
-
throw new Error(QUOTA_EXCEEDED_MESSAGE);
|
|
3450
|
-
}
|
|
3451
|
-
const choices = Array.isArray(payload.choices) ? payload.choices : [];
|
|
3452
|
-
for (const choice of choices) {
|
|
3453
|
-
if (!record2(choice)) continue;
|
|
3454
|
-
const delta = record2(choice.delta) ? choice.delta : void 0;
|
|
3455
|
-
const toolCalls = delta && Array.isArray(delta.tool_calls) ? delta.tool_calls : [];
|
|
3456
|
-
for (const call of toolCalls) {
|
|
3457
|
-
if (!record2(call) || !record2(call.function) || typeof call.function.name !== "string") {
|
|
3458
|
-
continue;
|
|
3459
|
-
}
|
|
3460
|
-
const key = `${choice.index ?? 0}:${call.index ?? 0}`;
|
|
3461
|
-
const accumulated = (fragments.get(key) ?? "") + call.function.name;
|
|
3462
|
-
if (Object.prototype.hasOwnProperty.call(names, accumulated)) {
|
|
3463
|
-
call.function.name = accumulated;
|
|
3464
|
-
fragments.delete(key);
|
|
3465
|
-
} else if (Object.keys(names).some((safe) => safe.startsWith(accumulated))) {
|
|
3466
|
-
fragments.set(key, accumulated);
|
|
3467
|
-
call.function.name = "";
|
|
3468
|
-
} else {
|
|
3469
|
-
call.function.name = accumulated;
|
|
3470
|
-
fragments.delete(key);
|
|
3471
|
-
}
|
|
3472
|
-
}
|
|
3473
|
-
}
|
|
3474
|
-
}
|
|
3475
|
-
const restored = restoreWorkBuddyToolNames(payload, names);
|
|
3476
|
-
const nonDataFields = lines.filter((line) => !line.startsWith("data:"));
|
|
3477
|
-
lines = [];
|
|
3478
|
-
return [...nonDataFields, `data: ${JSON.stringify(restored)}`, "", ""].join(
|
|
3479
|
-
"\n"
|
|
3480
|
-
);
|
|
3481
|
-
};
|
|
3482
|
-
const drain = (final) => {
|
|
3483
|
-
let output = "";
|
|
3484
|
-
while (true) {
|
|
3485
|
-
const match = /[\r\n]/.exec(pending);
|
|
3486
|
-
if (!match) break;
|
|
3487
|
-
const i = match.index;
|
|
3488
|
-
if (!final && pending[i] === "\r" && i === pending.length - 1) break;
|
|
3489
|
-
const line = pending.slice(0, i);
|
|
3490
|
-
pending = pending.slice(
|
|
3491
|
-
i + (pending[i] === "\r" && pending[i + 1] === "\n" ? 2 : 1)
|
|
3492
|
-
);
|
|
3493
|
-
if (line === "") {
|
|
3494
|
-
output += processEvent();
|
|
3495
|
-
} else {
|
|
3496
|
-
lines.push(line);
|
|
3497
|
-
}
|
|
3498
|
-
}
|
|
3499
|
-
if (final) {
|
|
3500
|
-
if (pending) {
|
|
3501
|
-
lines.push(pending);
|
|
3502
|
-
pending = "";
|
|
3503
|
-
}
|
|
3504
|
-
if (lines.length > 0) {
|
|
3505
|
-
output += processEvent();
|
|
3506
|
-
}
|
|
3507
|
-
}
|
|
3508
|
-
return output;
|
|
3509
|
-
};
|
|
3510
|
-
const transformStream = new TransformStream({
|
|
3511
|
-
transform: (chunk, controller) => {
|
|
3512
|
-
pending += decoder.decode(chunk, { stream: true });
|
|
3513
|
-
const output = drain(false);
|
|
3514
|
-
if (output) controller.enqueue(encoder.encode(output));
|
|
3515
|
-
},
|
|
3516
|
-
flush: (controller) => {
|
|
3517
|
-
pending += decoder.decode();
|
|
3518
|
-
const output = drain(true);
|
|
3519
|
-
if (output) controller.enqueue(encoder.encode(output));
|
|
3520
|
-
}
|
|
3521
|
-
});
|
|
3522
|
-
const body = response.body.pipeThrough(transformStream);
|
|
3523
|
-
const headers = new Headers(response.headers);
|
|
3524
|
-
headers.delete("content-length");
|
|
3525
|
-
headers.delete("content-encoding");
|
|
3526
|
-
return new Response(body, {
|
|
3527
|
-
status: response.status,
|
|
3528
|
-
statusText: response.statusText,
|
|
3529
|
-
headers
|
|
3530
|
-
});
|
|
3531
|
-
}
|
|
3532
|
-
async function wrapWorkBuddyJsonResponse(response, names) {
|
|
3533
|
-
const rawText = await response.text();
|
|
3534
|
-
let json;
|
|
3535
|
-
try {
|
|
3536
|
-
json = JSON.parse(rawText);
|
|
3537
|
-
} catch {
|
|
3538
|
-
return new Response(rawText, {
|
|
3539
|
-
status: response.status,
|
|
3540
|
-
statusText: response.statusText,
|
|
3541
|
-
headers: response.headers
|
|
3542
|
-
});
|
|
3543
|
-
}
|
|
3544
|
-
if (record2(json) && (json.code === 14018 || json.errcode === 14018 || record2(json.error) && json.error.code === 14018 || rawText.includes("14018"))) {
|
|
3545
|
-
throw new Error(QUOTA_EXCEEDED_MESSAGE);
|
|
3546
|
-
}
|
|
3547
|
-
const restored = restoreWorkBuddyToolNames(json, names);
|
|
3548
|
-
return new Response(JSON.stringify(restored), {
|
|
3549
|
-
status: response.status,
|
|
3550
|
-
statusText: response.statusText,
|
|
3551
|
-
headers: response.headers
|
|
3552
|
-
});
|
|
3553
|
-
}
|
|
3554
|
-
var resolveWorkbuddyTransport = async (ctx) => {
|
|
3555
|
-
const {
|
|
3556
|
-
agentConfig,
|
|
3557
|
-
deps,
|
|
3558
|
-
fetchImpl,
|
|
3559
|
-
additionalToolNames,
|
|
3560
|
-
buildProviderOpenAiTools,
|
|
3561
|
-
recordLocalAvailability,
|
|
3562
|
-
apiKeyRefResolver
|
|
3563
|
-
} = ctx;
|
|
3564
|
-
const site = resolveWorkBuddySite(agentConfig);
|
|
3565
|
-
if (!site) return null;
|
|
3566
|
-
const fixedEndpoint = WORKBUDDY_ENDPOINTS[site];
|
|
3567
|
-
if (agentConfig.customProviderUrl) {
|
|
3568
|
-
const trimmedUrl = agentConfig.customProviderUrl.trim();
|
|
3569
|
-
if (trimmedUrl && trimmedUrl !== fixedEndpoint) {
|
|
3570
|
-
throw new Error(
|
|
3571
|
-
`Custom provider URL "${trimmedUrl}" is forbidden for WorkBuddy (${site}). Requests must only target ${fixedEndpoint}.`
|
|
3572
|
-
);
|
|
3573
|
-
}
|
|
3574
|
-
}
|
|
3575
|
-
const rawRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
|
|
3576
|
-
const isApiKeyRef = rawRef.startsWith("api-key:");
|
|
3577
|
-
const providerRef = isApiKeyRef ? rawRef : site;
|
|
3578
|
-
const initialToken = await apiKeyRefResolver(providerRef);
|
|
3579
|
-
if (!initialToken) {
|
|
3580
|
-
throw new Error(
|
|
3581
|
-
`OAuth credential for "${site}" not found locally. Run \`nolo auth ${site}\`.`
|
|
3582
|
-
);
|
|
3583
|
-
}
|
|
3584
|
-
const legacyCredentialMigration = { enableLegacyMigration: true };
|
|
3585
|
-
let currentCredential = readOAuthCredential(
|
|
3586
|
-
site,
|
|
3587
|
-
void 0,
|
|
3588
|
-
legacyCredentialMigration
|
|
3589
|
-
);
|
|
3590
|
-
if (!currentCredential || !currentCredential.accessToken) {
|
|
3591
|
-
throw new Error(
|
|
3592
|
-
`OAuth credential for "${site}" not found locally. Run \`nolo auth ${site}\`.`
|
|
3593
|
-
);
|
|
3594
|
-
}
|
|
3595
|
-
const uid = typeof currentCredential.metadata?.uid === "string" && currentCredential.metadata.uid.trim() || typeof currentCredential.accountId === "string" && currentCredential.accountId.trim() || "";
|
|
3596
|
-
if (!uid) {
|
|
3597
|
-
throw new Error(
|
|
3598
|
-
`WorkBuddy credential for "${site}" is missing uid. Re-run \`nolo auth ${site}\`.`
|
|
3599
|
-
);
|
|
3600
|
-
}
|
|
3601
|
-
if (currentCredential.accessToken !== initialToken) {
|
|
3602
|
-
currentCredential = { ...currentCredential, accessToken: initialToken };
|
|
3603
|
-
}
|
|
3604
|
-
const { requestedToolNames, tools } = resolveProviderOpenAiToolBundle(
|
|
3605
|
-
agentConfig,
|
|
3606
|
-
deps.env,
|
|
3607
|
-
buildProviderOpenAiTools,
|
|
3608
|
-
additionalToolNames
|
|
3609
|
-
);
|
|
3610
|
-
const resolveRequestApiKey = async ({
|
|
3611
|
-
force
|
|
3612
|
-
}) => {
|
|
3613
|
-
if (isApiKeyRef && force) {
|
|
3614
|
-
return currentCredential.accessToken;
|
|
3615
|
-
}
|
|
3616
|
-
const before = readOAuthCredential(
|
|
3617
|
-
site,
|
|
3618
|
-
void 0,
|
|
3619
|
-
legacyCredentialMigration
|
|
3620
|
-
);
|
|
3621
|
-
if (before) {
|
|
3622
|
-
currentCredential = before;
|
|
3623
|
-
}
|
|
3624
|
-
if (!force) {
|
|
3625
|
-
return currentCredential.accessToken;
|
|
3626
|
-
}
|
|
3627
|
-
const refreshedToken = await apiKeyRefResolver(providerRef, {
|
|
3628
|
-
force: true
|
|
3629
|
-
});
|
|
3630
|
-
const after = readOAuthCredential(
|
|
3631
|
-
site,
|
|
3632
|
-
void 0,
|
|
3633
|
-
legacyCredentialMigration
|
|
3634
|
-
);
|
|
3635
|
-
if (after) {
|
|
3636
|
-
currentCredential = after;
|
|
3637
|
-
}
|
|
3638
|
-
if (refreshedToken && currentCredential.accessToken !== refreshedToken) {
|
|
3639
|
-
currentCredential = {
|
|
3640
|
-
...currentCredential,
|
|
3641
|
-
accessToken: refreshedToken
|
|
3642
|
-
};
|
|
3643
|
-
}
|
|
3644
|
-
return refreshedToken ?? currentCredential.accessToken;
|
|
3645
|
-
};
|
|
3646
|
-
const wrappedFetch = async (inputUrl, init) => {
|
|
3647
|
-
const targetUrl = typeof inputUrl === "string" ? inputUrl : inputUrl instanceof URL ? inputUrl.toString() : inputUrl.url;
|
|
3648
|
-
if (targetUrl !== fixedEndpoint) {
|
|
3649
|
-
throw new Error(
|
|
3650
|
-
`WorkBuddy request blocked: target URL "${targetUrl}" does not match fixed endpoint "${fixedEndpoint}". Token will not be sent.`
|
|
3651
|
-
);
|
|
3652
|
-
}
|
|
3653
|
-
let originalNames = {};
|
|
3654
|
-
let body = init?.body;
|
|
3655
|
-
if (typeof body === "string") {
|
|
3656
|
-
try {
|
|
3657
|
-
const parsed = JSON.parse(body);
|
|
3658
|
-
const adapted = adaptWorkBuddyRequest(parsed);
|
|
3659
|
-
originalNames = adapted.originalNames;
|
|
3660
|
-
body = JSON.stringify(adapted.body);
|
|
3661
|
-
} catch {
|
|
3662
|
-
}
|
|
3663
|
-
}
|
|
3664
|
-
const wbHeaders = getWorkBuddyHeaders(currentCredential);
|
|
3665
|
-
const mergedHeaders = new Headers(init?.headers);
|
|
3666
|
-
for (const [key, value] of Object.entries(wbHeaders)) {
|
|
3667
|
-
mergedHeaders.set(key, value);
|
|
3668
|
-
}
|
|
3669
|
-
mergedHeaders.set("Content-Type", "application/json");
|
|
3670
|
-
const upstreamRes = await fetchImpl(fixedEndpoint, {
|
|
3671
|
-
...init,
|
|
3672
|
-
body,
|
|
3673
|
-
headers: mergedHeaders,
|
|
3674
|
-
redirect: "error"
|
|
3675
|
-
});
|
|
3676
|
-
if (upstreamRes.status === 401) {
|
|
3677
|
-
return upstreamRes;
|
|
3678
|
-
}
|
|
3679
|
-
if (!upstreamRes.ok) {
|
|
3680
|
-
const clone = upstreamRes.clone();
|
|
3681
|
-
const errorText = await clone.text().catch(() => "");
|
|
3682
|
-
if (errorText.includes("14018")) {
|
|
3683
|
-
throw new Error(QUOTA_EXCEEDED_MESSAGE);
|
|
3684
|
-
}
|
|
3685
|
-
return upstreamRes;
|
|
3686
|
-
}
|
|
3687
|
-
const contentType = upstreamRes.headers.get("content-type") ?? "";
|
|
3688
|
-
if (contentType.includes("text/event-stream")) {
|
|
3689
|
-
return wrapWorkBuddySseResponse(upstreamRes, originalNames);
|
|
3690
|
-
} else {
|
|
3691
|
-
return wrapWorkBuddyJsonResponse(upstreamRes, originalNames);
|
|
3692
|
-
}
|
|
3693
|
-
};
|
|
3694
|
-
return {
|
|
3695
|
-
model: agentConfig.model || "gpt-4o",
|
|
3696
|
-
complete: async (messages, options) => {
|
|
3697
|
-
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
3698
|
-
agentKey: agentConfig.key,
|
|
3699
|
-
transport: "workbuddy",
|
|
3700
|
-
model: agentConfig.model ?? "gpt-4o",
|
|
3701
|
-
messageCount: messages.length,
|
|
3702
|
-
toolCount: tools.length,
|
|
3703
|
-
requestedToolNames,
|
|
3704
|
-
openAiToolNames: summarizeOpenAiToolNames(tools),
|
|
3705
|
-
stream: true
|
|
3706
|
-
});
|
|
3707
|
-
try {
|
|
3708
|
-
const result = await executeOpenAiCompatibleChatCompletion({
|
|
3709
|
-
providerConfig: {
|
|
3710
|
-
endpoint: fixedEndpoint,
|
|
3711
|
-
apiKey: currentCredential.accessToken,
|
|
3712
|
-
model: agentConfig.model || "gpt-4o",
|
|
3713
|
-
provider: site
|
|
3714
|
-
},
|
|
3715
|
-
messages,
|
|
3716
|
-
tools,
|
|
3717
|
-
fetchImpl: wrappedFetch,
|
|
3718
|
-
stream: true,
|
|
3719
|
-
sessionId: asOptionalTrimmedString(options?.dialogId) ?? asOptionalTrimmedString(agentConfig.key),
|
|
3720
|
-
onTextDelta: options?.onTextDelta,
|
|
3721
|
-
onReasoningDelta: options?.onReasoningDelta,
|
|
3722
|
-
onHttpResult: ({ status, body }) => recordLocalAvailability(status, body),
|
|
3723
|
-
resolveApiKey: resolveRequestApiKey
|
|
3724
|
-
});
|
|
3725
|
-
await recordLocalAvailability(200);
|
|
3726
|
-
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
3727
|
-
agentKey: agentConfig.key,
|
|
3728
|
-
transport: "workbuddy",
|
|
3729
|
-
ok: true,
|
|
3730
|
-
contentChars: result.content.length,
|
|
3731
|
-
toolCallCount: result.tool_calls?.length ?? 0
|
|
3732
|
-
});
|
|
3733
|
-
return result;
|
|
3734
|
-
} catch (error) {
|
|
3735
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3736
|
-
if (message.includes("14018")) {
|
|
3737
|
-
throw new Error(QUOTA_EXCEEDED_MESSAGE);
|
|
3738
|
-
}
|
|
3739
|
-
throw error;
|
|
3740
|
-
}
|
|
3741
|
-
}
|
|
3742
|
-
};
|
|
3743
|
-
};
|
|
3744
|
-
|
|
3745
3304
|
// packages/cli/client/providerResolution/directOpenAiCompatibleTransport.ts
|
|
3746
3305
|
var resolveDirectOpenAiCompatibleTransport = async (ctx) => {
|
|
3747
3306
|
const { agentConfig, deps, fetchImpl, loopbackRequest, additionalToolNames, buildProviderOpenAiTools, recordLocalAvailability, apiKeyRefResolver, credentialBroker, syncFetcher, serverUrl, authToken } = ctx;
|
|
@@ -3973,6 +3532,77 @@ var OWNER_PROXY_BODY_FORBIDDEN_KEYS = [
|
|
|
3973
3532
|
"agentHydratedKey",
|
|
3974
3533
|
"credentialPolicy"
|
|
3975
3534
|
];
|
|
3535
|
+
var OWNER_PROXY_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 503]);
|
|
3536
|
+
var OWNER_PROXY_TOTAL_MAX_ATTEMPTS = 30;
|
|
3537
|
+
var OWNER_PROXY_GENERIC_MAX_ATTEMPTS = 3;
|
|
3538
|
+
var OWNER_PROXY_CORE_DRAINING_MAX_ATTEMPTS = 30;
|
|
3539
|
+
async function readStructuredErrorCode(response) {
|
|
3540
|
+
try {
|
|
3541
|
+
const body = await response.clone().json();
|
|
3542
|
+
const nested = body?.error?.code;
|
|
3543
|
+
if (typeof nested === "string") return nested;
|
|
3544
|
+
return typeof body?.code === "string" ? body.code : null;
|
|
3545
|
+
} catch {
|
|
3546
|
+
return null;
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
async function shouldRetryOwnerProxyResponse(response) {
|
|
3550
|
+
if (response.status === 503) {
|
|
3551
|
+
try {
|
|
3552
|
+
const body = await response.clone().json();
|
|
3553
|
+
return body?.reason === "core_draining" || body?.retryable === true;
|
|
3554
|
+
} catch {
|
|
3555
|
+
return false;
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
return false;
|
|
3559
|
+
}
|
|
3560
|
+
var OWNER_ORIGIN_MISMATCH_RETRY_BUDGET = {
|
|
3561
|
+
/** 额外尝试次数上限(不含首次请求)。 */
|
|
3562
|
+
maxExtraAttempts: 2,
|
|
3563
|
+
/** 每次额外尝试前的等待时长(ms),按序使用。 */
|
|
3564
|
+
delaysMs: [5e3, 15e3]
|
|
3565
|
+
};
|
|
3566
|
+
function waitWithAbort(ms, signal) {
|
|
3567
|
+
if (signal?.aborted) {
|
|
3568
|
+
return Promise.reject(signal.reason ?? new Error("owner-required proxy aborted"));
|
|
3569
|
+
}
|
|
3570
|
+
return new Promise((resolve4, reject) => {
|
|
3571
|
+
let timer;
|
|
3572
|
+
const cleanup = () => {
|
|
3573
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
3574
|
+
signal?.removeEventListener("abort", onAbort);
|
|
3575
|
+
};
|
|
3576
|
+
const onAbort = () => {
|
|
3577
|
+
cleanup();
|
|
3578
|
+
reject(signal?.reason ?? new Error("owner-required proxy aborted"));
|
|
3579
|
+
};
|
|
3580
|
+
timer = setTimeout(() => {
|
|
3581
|
+
cleanup();
|
|
3582
|
+
resolve4();
|
|
3583
|
+
}, ms);
|
|
3584
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3587
|
+
async function sendWithOwnerOriginMismatchRetry(send, signal, onRetry) {
|
|
3588
|
+
let attempt = await send();
|
|
3589
|
+
for (let extra = 0; extra < OWNER_ORIGIN_MISMATCH_RETRY_BUDGET.maxExtraAttempts; extra += 1) {
|
|
3590
|
+
const response = attempt.response;
|
|
3591
|
+
if (response.status !== 403) return response;
|
|
3592
|
+
const code = await readStructuredErrorCode(response);
|
|
3593
|
+
if (code !== "owner_origin_mismatch") return response;
|
|
3594
|
+
if (attempt.innerRetried) return response;
|
|
3595
|
+
const delayMs = OWNER_ORIGIN_MISMATCH_RETRY_BUDGET.delaysMs[extra] ?? 0;
|
|
3596
|
+
onRetry?.({
|
|
3597
|
+
attempt: extra + 1,
|
|
3598
|
+
maxAttempts: OWNER_ORIGIN_MISMATCH_RETRY_BUDGET.maxExtraAttempts,
|
|
3599
|
+
delayMs
|
|
3600
|
+
});
|
|
3601
|
+
await waitWithAbort(delayMs, signal);
|
|
3602
|
+
attempt = await send();
|
|
3603
|
+
}
|
|
3604
|
+
return attempt.response;
|
|
3605
|
+
}
|
|
3976
3606
|
var resolveOwnerOAuthProxyTransport = async (ctx) => {
|
|
3977
3607
|
const {
|
|
3978
3608
|
agentConfig,
|
|
@@ -4051,32 +3681,57 @@ var resolveOwnerOAuthProxyTransport = async (ctx) => {
|
|
|
4051
3681
|
originSessionId: ownerOriginExecution.origin.sessionId
|
|
4052
3682
|
});
|
|
4053
3683
|
try {
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
3684
|
+
let usedAttempts = 0;
|
|
3685
|
+
const send = async () => {
|
|
3686
|
+
const remaining = Math.max(
|
|
3687
|
+
1,
|
|
3688
|
+
OWNER_PROXY_TOTAL_MAX_ATTEMPTS - usedAttempts
|
|
3689
|
+
);
|
|
3690
|
+
let innerRetries = 0;
|
|
3691
|
+
const response = await fetchWithTransientRetry(
|
|
3692
|
+
fetchImpl,
|
|
3693
|
+
request.url,
|
|
3694
|
+
init,
|
|
3695
|
+
{
|
|
3696
|
+
sleep: deps.sleep,
|
|
3697
|
+
loopbackRequest,
|
|
3698
|
+
// 与 platform-proxy 同口径:网络错误不重放(服务端可能已受理,重放会
|
|
3699
|
+
// 产生重复扣费/重复 tool_calls)。
|
|
3700
|
+
retryableStatuses: OWNER_PROXY_RETRYABLE_STATUSES,
|
|
3701
|
+
shouldRetryResponse: shouldRetryOwnerProxyResponse,
|
|
3702
|
+
retryNetworkErrors: false,
|
|
3703
|
+
// 内层预算按「剩余总额度」裁剪:普通可重试状态码 ≤ 3 次、503
|
|
3704
|
+
// core_draining 排空窗口 ≤ 30 次,且都不超过剩余总额度。
|
|
3705
|
+
maxAttempts: Math.min(
|
|
3706
|
+
OWNER_PROXY_GENERIC_MAX_ATTEMPTS,
|
|
3707
|
+
remaining
|
|
3708
|
+
),
|
|
3709
|
+
coreDrainingMaxAttempts: Math.min(
|
|
3710
|
+
OWNER_PROXY_CORE_DRAINING_MAX_ATTEMPTS,
|
|
3711
|
+
remaining
|
|
3712
|
+
),
|
|
3713
|
+
// 注意:计数必须**无条件**挂在 onRetry 上——若只在有 activityReporter
|
|
3714
|
+
// 时才挂,innerRetries / usedAttempts 会漏计,重试预算就形同虚设。
|
|
3715
|
+
onRetry: ({ attempt, maxAttempts, delayMs }) => {
|
|
3716
|
+
innerRetries += 1;
|
|
3717
|
+
usedAttempts += 1;
|
|
3718
|
+
deps.activityReporter?.(
|
|
3719
|
+
`\u81EA\u52A8\u91CD\u8BD5 ${attempt}/${maxAttempts} \xB7 ${Math.ceil(delayMs / 1e3)}s`
|
|
3720
|
+
);
|
|
4071
3721
|
}
|
|
4072
|
-
}
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
3722
|
+
}
|
|
3723
|
+
);
|
|
3724
|
+
usedAttempts += 1;
|
|
3725
|
+
return { response, innerRetried: innerRetries > 0 };
|
|
3726
|
+
};
|
|
3727
|
+
const res = await sendWithOwnerOriginMismatchRetry(
|
|
3728
|
+
send,
|
|
3729
|
+
init.signal ?? void 0,
|
|
3730
|
+
deps.activityReporter ? ({ attempt, maxAttempts, delayMs }) => {
|
|
3731
|
+
deps.activityReporter(
|
|
3732
|
+
`\u81EA\u52A8\u91CD\u8BD5 ${attempt}/${maxAttempts} \xB7 ${Math.ceil(delayMs / 1e3)}s`
|
|
3733
|
+
);
|
|
3734
|
+
} : void 0
|
|
4080
3735
|
);
|
|
4081
3736
|
if (!res.ok) {
|
|
4082
3737
|
const raw2 = await res.text().catch(() => "");
|
|
@@ -4385,7 +4040,6 @@ var TRANSPORTS = [
|
|
|
4385
4040
|
resolveCodexOAuthTransport,
|
|
4386
4041
|
resolveCursorTransport,
|
|
4387
4042
|
resolveDevinTransport,
|
|
4388
|
-
resolveWorkbuddyTransport,
|
|
4389
4043
|
resolveGeminiNativeToolTransport,
|
|
4390
4044
|
// 三条 custom native wire(gemini / openai-responses / anthropic-messages)由
|
|
4391
4045
|
// 这一个 resolver 按目录 `nativeProtocol` 分派:三种 wire 互斥(一个模型的
|
|
@@ -4556,11 +4210,11 @@ function withProviderStreamRetry(provider, deps) {
|
|
|
4556
4210
|
|
|
4557
4211
|
// packages/cli/client/cliRemoteDialogSync.ts
|
|
4558
4212
|
function prepareRemoteDialogEvidenceRecord(key, value) {
|
|
4559
|
-
const
|
|
4560
|
-
if (key.includes("-msg-") && typeof
|
|
4561
|
-
|
|
4213
|
+
const record = isRecord(value) ? { ...value } : {};
|
|
4214
|
+
if (key.includes("-msg-") && typeof record.type !== "string") {
|
|
4215
|
+
record.type = "msg";
|
|
4562
4216
|
}
|
|
4563
|
-
return
|
|
4217
|
+
return record;
|
|
4564
4218
|
}
|
|
4565
4219
|
function normalizeRemoteSubjectRef(value) {
|
|
4566
4220
|
if (!isRecord(value)) return null;
|
|
@@ -4852,13 +4506,13 @@ function resolveBuiltinLocalCliAgentConfig(agentRef, userId) {
|
|
|
4852
4506
|
}
|
|
4853
4507
|
async function readAgentFromStore(args) {
|
|
4854
4508
|
for (const key of buildLocalAgentLookupKeys(args)) {
|
|
4855
|
-
const
|
|
4856
|
-
if (!
|
|
4509
|
+
const record = await args.store.read(key);
|
|
4510
|
+
if (!record || typeof record !== "object") continue;
|
|
4857
4511
|
return applyBuiltinAgentRuntimeOverride(
|
|
4858
4512
|
args.agentRef,
|
|
4859
4513
|
resolveAgentRuntimeConfigFromRecord(
|
|
4860
4514
|
key,
|
|
4861
|
-
applyPublicAgentCatalogOverride(
|
|
4515
|
+
applyPublicAgentCatalogOverride(record)
|
|
4862
4516
|
)
|
|
4863
4517
|
);
|
|
4864
4518
|
}
|
|
@@ -4893,8 +4547,8 @@ async function readDialogMessages(args) {
|
|
|
4893
4547
|
function createChildShellApprovalHostResolver(args) {
|
|
4894
4548
|
return async (agentKey) => {
|
|
4895
4549
|
const config = await args.readAgentConfig(agentKey);
|
|
4896
|
-
const
|
|
4897
|
-
const ownerUserId = asOptionalTrimmedString(
|
|
4550
|
+
const record = config?.rawRecord;
|
|
4551
|
+
const ownerUserId = asOptionalTrimmedString(record?.userId) ?? asOptionalTrimmedString(record?.ownerUserId);
|
|
4898
4552
|
if (!ownerUserId) return void 0;
|
|
4899
4553
|
const deviceId = asOptionalTrimmedString(await args.resolveDeviceId());
|
|
4900
4554
|
if (!deviceId) return void 0;
|
|
@@ -5161,8 +4815,8 @@ function describeIssues(issues) {
|
|
|
5161
4815
|
function asNonEmptyString(value) {
|
|
5162
4816
|
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
5163
4817
|
}
|
|
5164
|
-
function resolveCreatedAtMs(
|
|
5165
|
-
const raw =
|
|
4818
|
+
function resolveCreatedAtMs(record) {
|
|
4819
|
+
const raw = record.createdAt;
|
|
5166
4820
|
const ms = typeof raw === "number" ? raw : typeof raw === "string" ? Date.parse(raw) : Number.NaN;
|
|
5167
4821
|
return Number.isFinite(ms) ? ms : null;
|
|
5168
4822
|
}
|
|
@@ -5222,18 +4876,18 @@ function analyzeRemoteDialogRecords(args) {
|
|
|
5222
4876
|
}
|
|
5223
4877
|
seenIds.add(messageId);
|
|
5224
4878
|
const key = dialogMessageKey(args.dialogId, messageId);
|
|
5225
|
-
const
|
|
4879
|
+
const record = {
|
|
5226
4880
|
...raw,
|
|
5227
4881
|
id: messageId,
|
|
5228
4882
|
dbKey: key,
|
|
5229
4883
|
...asNonEmptyString(raw.dialogId) ? {} : { dialogId: args.dialogId }
|
|
5230
4884
|
};
|
|
5231
|
-
const message = dialogMessageRecordToAgentRuntimeMessage(
|
|
4885
|
+
const message = dialogMessageRecordToAgentRuntimeMessage(record);
|
|
5232
4886
|
if (!message) {
|
|
5233
4887
|
issues.push({ code: "unconvertible-record", detail: `${role} index ${index}` });
|
|
5234
4888
|
continue;
|
|
5235
4889
|
}
|
|
5236
|
-
entries.push({ key, messageId, record
|
|
4890
|
+
entries.push({ key, messageId, record, message });
|
|
5237
4891
|
}
|
|
5238
4892
|
const messages = entries.map((entry) => entry.message);
|
|
5239
4893
|
for (const detail of findAgentStatePairingIssues(messages)) {
|
|
@@ -5507,14 +5161,27 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
5507
5161
|
}
|
|
5508
5162
|
const body = {
|
|
5509
5163
|
query: parsed.query,
|
|
5510
|
-
numResults: parsed.numResults
|
|
5511
|
-
useAutoprompt: parsed.useAutoprompt ?? true,
|
|
5512
|
-
type: parsed.type ?? "neural",
|
|
5513
|
-
// Model schema uses `includeContent` (boolean); the Exa API
|
|
5514
|
-
// expects `contents: { text: true }`. Mirror exaSearchFunc's
|
|
5515
|
-
// conversion so CLI proxy results match web behavior.
|
|
5516
|
-
contents: parsed.includeContent !== false ? { text: true } : void 0
|
|
5164
|
+
...parsed.numResults !== void 0 ? { numResults: parsed.numResults } : {}
|
|
5517
5165
|
};
|
|
5166
|
+
if (typeof parsed.intent === "string" && parsed.intent) {
|
|
5167
|
+
body.intent = parsed.intent;
|
|
5168
|
+
}
|
|
5169
|
+
if (typeof parsed.category === "string" && parsed.category) {
|
|
5170
|
+
body.category = parsed.category;
|
|
5171
|
+
}
|
|
5172
|
+
if (typeof parsed.timeRange === "string" && parsed.timeRange) {
|
|
5173
|
+
body.timeRange = parsed.timeRange;
|
|
5174
|
+
}
|
|
5175
|
+
if (Array.isArray(parsed.includeDomains) && parsed.includeDomains.length > 0) {
|
|
5176
|
+
body.includeDomains = parsed.includeDomains;
|
|
5177
|
+
}
|
|
5178
|
+
if (Array.isArray(parsed.excludeDomains) && parsed.excludeDomains.length > 0) {
|
|
5179
|
+
body.excludeDomains = parsed.excludeDomains;
|
|
5180
|
+
}
|
|
5181
|
+
if (typeof parsed.includeContent === "boolean") {
|
|
5182
|
+
body.includeContent = parsed.includeContent;
|
|
5183
|
+
}
|
|
5184
|
+
if (call?.origin) body.origin = call.origin;
|
|
5518
5185
|
const content = await postServer("/api/exa-search", body);
|
|
5519
5186
|
return {
|
|
5520
5187
|
content,
|
|
@@ -6094,9 +5761,9 @@ var boundedOutputPage = (items, total, offset, budget = 8 * 1024) => {
|
|
|
6094
5761
|
return { items, hasMore: offset + items.length < total, nextOffset: offset + items.length };
|
|
6095
5762
|
};
|
|
6096
5763
|
var resolveNowMs = (deps) => typeof deps.nowMs === "function" ? deps.nowMs() : Date.now();
|
|
6097
|
-
function buildProgressField(
|
|
6098
|
-
const activity =
|
|
6099
|
-
if (!activity || isAgentRunTerminalStatus(
|
|
5764
|
+
function buildProgressField(record, nowMs) {
|
|
5765
|
+
const activity = record.activity;
|
|
5766
|
+
if (!activity || isAgentRunTerminalStatus(record.status)) return {};
|
|
6100
5767
|
const lastEventAt = Date.parse(activity.lastEventAt ?? "");
|
|
6101
5768
|
const inFlight = activity.inFlight;
|
|
6102
5769
|
const progress = {
|
|
@@ -6193,15 +5860,15 @@ async function assertCredentialFanoutAllowed(deps, args) {
|
|
|
6193
5860
|
}
|
|
6194
5861
|
const { batchId, parentDialogId } = args;
|
|
6195
5862
|
if (!batchId && !parentDialogId) return candidateGroup;
|
|
6196
|
-
const active = queryRunRecords({ limit: 500 }, deps).runs.filter((
|
|
6197
|
-
if (isRunTerminalStatus(
|
|
6198
|
-
if (batchId &&
|
|
6199
|
-
if (parentDialogId &&
|
|
5863
|
+
const active = queryRunRecords({ limit: 500 }, deps).runs.filter((record) => {
|
|
5864
|
+
if (isRunTerminalStatus(record.status)) return false;
|
|
5865
|
+
if (batchId && record.batchId === batchId) return true;
|
|
5866
|
+
if (parentDialogId && record.parentDialogId === parentDialogId) return true;
|
|
6200
5867
|
return false;
|
|
6201
|
-
}).map((
|
|
6202
|
-
runId:
|
|
6203
|
-
agentKey:
|
|
6204
|
-
credentialGroup:
|
|
5868
|
+
}).map((record) => ({
|
|
5869
|
+
runId: record.runId,
|
|
5870
|
+
agentKey: record.agentKey,
|
|
5871
|
+
credentialGroup: record.credentialGroup
|
|
6205
5872
|
}));
|
|
6206
5873
|
if (active.length === 0) return candidateGroup;
|
|
6207
5874
|
const verdict = checkCredentialFanout({
|
|
@@ -6230,6 +5897,12 @@ function createCliStartAgentRunExecutor(deps = {}) {
|
|
|
6230
5897
|
// F1:runtimeKey=local 是「在宿主文件系统上改代码」,需要调用方的显式确认
|
|
6231
5898
|
// (allowHostWrites: true);缺失即派发前拒绝(零 spawn、零 run 记录)。
|
|
6232
5899
|
allowHostWrites: args.allowHostWrites,
|
|
5900
|
+
// 政策第 5 条:显式宿主 cwd × 沙盒落点必须在派发前失败(沙盒不兑现宿主
|
|
5901
|
+
// 路径,cwd 会被静默替换、改动随沙盒消失)。这里传的是调用方**原始**
|
|
5902
|
+
// args.cwd —— `requestedCwd` 走 resolveStartAgentRunCwd,要读 fs 探测,
|
|
5903
|
+
// 排在这条判定之后;守卫自己只认宿主绝对路径(相对/空白自行跳过,交给
|
|
5904
|
+
// resolveStartAgentRunCwd 报「必须是绝对路径」)。
|
|
5905
|
+
...typeof args.cwd === "string" && args.cwd.trim() ? { cwd: args.cwd } : {},
|
|
6233
5906
|
...bindingMachineId ? { bindingMachineId } : {},
|
|
6234
5907
|
...localMachineId ? { localMachineId } : {}
|
|
6235
5908
|
});
|
|
@@ -6438,16 +6111,16 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
6438
6111
|
},
|
|
6439
6112
|
deps
|
|
6440
6113
|
);
|
|
6441
|
-
const runs = records.map((
|
|
6114
|
+
const runs = records.map((record2) => {
|
|
6442
6115
|
return {
|
|
6443
|
-
runId:
|
|
6444
|
-
status:
|
|
6445
|
-
agentKey:
|
|
6446
|
-
...
|
|
6447
|
-
...typeof
|
|
6448
|
-
...
|
|
6449
|
-
pid:
|
|
6450
|
-
startedAt:
|
|
6116
|
+
runId: record2.runId,
|
|
6117
|
+
status: record2.status,
|
|
6118
|
+
agentKey: record2.agentKey,
|
|
6119
|
+
...record2.agentName ? { agentName: record2.agentName.slice(0, 120) } : {},
|
|
6120
|
+
...typeof record2.title === "string" ? { title: record2.title.slice(0, 160) } : {},
|
|
6121
|
+
...record2.batchId ? { batchId: record2.batchId } : {},
|
|
6122
|
+
pid: record2.pid ?? null,
|
|
6123
|
+
startedAt: record2.startedAt
|
|
6451
6124
|
};
|
|
6452
6125
|
});
|
|
6453
6126
|
const outputBudgetBytes = 8 * 1024;
|
|
@@ -6533,15 +6206,15 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
6533
6206
|
if (!args.runId) throw new Error(t("agentRunTool.appendMissingRunId"));
|
|
6534
6207
|
const userInput = typeof args.userInput === "string" ? args.userInput.trim() : "";
|
|
6535
6208
|
if (!userInput) throw new Error(t("agentRunTool.appendMissingUserInput"));
|
|
6536
|
-
const
|
|
6537
|
-
if (!
|
|
6209
|
+
const record2 = findRunRecord(String(args.runId), deps);
|
|
6210
|
+
if (!record2) {
|
|
6538
6211
|
const labels2 = agentRunCardLabels();
|
|
6539
6212
|
return {
|
|
6540
6213
|
content: JSON.stringify({ runId: args.runId, found: false }),
|
|
6541
6214
|
metadata: { displayData: formatNotFoundRunCard(labels2) }
|
|
6542
6215
|
};
|
|
6543
6216
|
}
|
|
6544
|
-
let reconciled2 = checkStaleRun(
|
|
6217
|
+
let reconciled2 = checkStaleRun(record2.runId, deps) ?? record2;
|
|
6545
6218
|
if (!isAgentRunTerminalStatus(reconciled2.status)) {
|
|
6546
6219
|
if (!reconciled2.queuePath) {
|
|
6547
6220
|
throw new Error(t("agentRunTool.appendQueueUnsupported"));
|
|
@@ -6621,8 +6294,8 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
6621
6294
|
throw new Error(t("agentRunTool.unknownAction", String(action)));
|
|
6622
6295
|
}
|
|
6623
6296
|
if (!args.runId) throw new Error(t("agentRunTool.missingRunId", String(action)));
|
|
6624
|
-
const
|
|
6625
|
-
if (!
|
|
6297
|
+
const record = findRunRecord(String(args.runId), deps);
|
|
6298
|
+
if (!record) {
|
|
6626
6299
|
const labels2 = agentRunCardLabels();
|
|
6627
6300
|
return {
|
|
6628
6301
|
content: JSON.stringify({ runId: args.runId, found: false }),
|
|
@@ -6630,15 +6303,15 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
6630
6303
|
};
|
|
6631
6304
|
}
|
|
6632
6305
|
if (action === "status") {
|
|
6633
|
-
const reconciled2 = checkStaleRun(
|
|
6634
|
-
const logTail = tailLines > 0 ? tailFile(
|
|
6306
|
+
const reconciled2 = checkStaleRun(record.runId, deps) ?? record;
|
|
6307
|
+
const logTail = tailLines > 0 ? tailFile(record.logPath, tailLines, resolveFs(deps)) : void 0;
|
|
6635
6308
|
return buildRunStatusPayload(reconciled2, deps, { logTail });
|
|
6636
6309
|
}
|
|
6637
6310
|
if (action === "wait") {
|
|
6638
6311
|
const timeoutMs = typeof args.timeoutMs === "number" && args.timeoutMs > 0 ? args.timeoutMs : DEFAULT_WAIT_TIMEOUT_MS;
|
|
6639
6312
|
let claimToken = null;
|
|
6640
6313
|
const result = await waitForRunTerminal({
|
|
6641
|
-
read: () => checkStaleRun(
|
|
6314
|
+
read: () => checkStaleRun(record.runId, deps) ?? record,
|
|
6642
6315
|
isTerminal: (state) => isAgentRunTerminalStatus(state.status),
|
|
6643
6316
|
pollIntervalMs: WAIT_POLL_INTERVAL_MS,
|
|
6644
6317
|
timeoutMs,
|
|
@@ -6646,28 +6319,28 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
6646
6319
|
sleep: deps.sleep,
|
|
6647
6320
|
claim: {
|
|
6648
6321
|
acquire: () => {
|
|
6649
|
-
claimToken = claimRunRecord(
|
|
6322
|
+
claimToken = claimRunRecord(record.runId, { ...deps, ttlMs: timeoutMs + ACK_LEASE_GRACE_MS });
|
|
6650
6323
|
return claimToken;
|
|
6651
6324
|
},
|
|
6652
6325
|
commit: (token) => {
|
|
6653
|
-
if (token) commitRunRecordClaim(
|
|
6654
|
-
else ackRunRecord(
|
|
6326
|
+
if (token) commitRunRecordClaim(record.runId, token, deps);
|
|
6327
|
+
else ackRunRecord(record.runId, deps);
|
|
6655
6328
|
},
|
|
6656
6329
|
release: (token) => {
|
|
6657
|
-
if (token) releaseRunRecordAck(
|
|
6330
|
+
if (token) releaseRunRecordAck(record.runId, token, deps);
|
|
6658
6331
|
}
|
|
6659
6332
|
}
|
|
6660
6333
|
});
|
|
6661
6334
|
if (result.kind === "aborted") throw new Error(t("agentRunTool.waitAborted"));
|
|
6662
6335
|
if (result.kind === "failed") throw result.error;
|
|
6663
6336
|
if (result.kind === "timeout") {
|
|
6664
|
-
const reconciled2 = result.lastState ??
|
|
6337
|
+
const reconciled2 = result.lastState ?? record;
|
|
6665
6338
|
const nowMs = resolveNowMs(deps);
|
|
6666
6339
|
return { content: JSON.stringify({ runId: reconciled2.runId, found: true, status: "timeout", runStatus: reconciled2.status, pid: reconciled2.pid ?? null, agentKey: reconciled2.agentKey, ...reconciled2.agentName ? { agentName: reconciled2.agentName } : {}, startedAt: reconciled2.startedAt, waitedMs: result.waitedMs, timeoutMs, ...buildProgressField(reconciled2, nowMs) }), metadata: { displayData: t("agentRunWaitTimeout", String(Math.round(result.waitedMs / 1e3))) } };
|
|
6667
6340
|
}
|
|
6668
6341
|
return buildRunStatusPayload(result.state, deps);
|
|
6669
6342
|
}
|
|
6670
|
-
const reconciled = checkStaleRun(
|
|
6343
|
+
const reconciled = checkStaleRun(record.runId, deps) ?? record;
|
|
6671
6344
|
if (isAgentRunTerminalStatus(reconciled.status)) {
|
|
6672
6345
|
const labels2 = agentRunCardLabels();
|
|
6673
6346
|
return {
|
|
@@ -6686,13 +6359,13 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
6686
6359
|
if (!confirmed) {
|
|
6687
6360
|
return {
|
|
6688
6361
|
content: JSON.stringify({
|
|
6689
|
-
runId:
|
|
6362
|
+
runId: record.runId,
|
|
6690
6363
|
found: true,
|
|
6691
6364
|
status: reconciled.status,
|
|
6692
6365
|
stopConfirmed: false
|
|
6693
6366
|
}),
|
|
6694
6367
|
metadata: {
|
|
6695
|
-
displayData: t("agentRunStopFailedAlive", String(
|
|
6368
|
+
displayData: t("agentRunStopFailedAlive", String(record.pid))
|
|
6696
6369
|
}
|
|
6697
6370
|
};
|
|
6698
6371
|
}
|
|
@@ -7160,12 +6833,10 @@ var REFRESH_BY_PROVIDER = {
|
|
|
7160
6833
|
antigravity: refreshAntigravityOAuthToken,
|
|
7161
6834
|
xai: xaiRefresh,
|
|
7162
6835
|
claude: anthropicRefresh,
|
|
7163
|
-
cursor: cursorRefresh
|
|
7164
|
-
workbuddy: workbuddyRefresh,
|
|
7165
|
-
"workbuddy-ai": workbuddyRefresh
|
|
6836
|
+
cursor: cursorRefresh
|
|
7166
6837
|
};
|
|
7167
6838
|
function isOAuthProvider(value) {
|
|
7168
|
-
return value === "chatgpt" || value === "xai" || value === "antigravity" || value === "claude" || value === "cursor" || value === "devin"
|
|
6839
|
+
return value === "chatgpt" || value === "xai" || value === "antigravity" || value === "claude" || value === "cursor" || value === "devin";
|
|
7169
6840
|
}
|
|
7170
6841
|
function createOAuthApiKeyRefResolver(options = {}) {
|
|
7171
6842
|
const pullServerAccessToken = options.pullServerAccessToken ?? createServerAccessTokenPuller({
|
|
@@ -7212,10 +6883,10 @@ function encodeFailure(error, stderr) {
|
|
|
7212
6883
|
function readStreams(output) {
|
|
7213
6884
|
if (typeof output === "string") return { stdout: output, stderr: "" };
|
|
7214
6885
|
if (!output || typeof output !== "object") return { stdout: "", stderr: "" };
|
|
7215
|
-
const
|
|
6886
|
+
const record = output;
|
|
7216
6887
|
return {
|
|
7217
|
-
stdout: typeof
|
|
7218
|
-
stderr: typeof
|
|
6888
|
+
stdout: typeof record.stdout === "string" ? record.stdout : "",
|
|
6889
|
+
stderr: typeof record.stderr === "string" ? record.stderr : ""
|
|
7219
6890
|
};
|
|
7220
6891
|
}
|
|
7221
6892
|
function describeMessage(error) {
|
|
@@ -8622,8 +8293,8 @@ async function createLocalDockerWorkload(args) {
|
|
|
8622
8293
|
}
|
|
8623
8294
|
const createLifecycle = args.createLifecycle ?? (async () => {
|
|
8624
8295
|
const [{ DockerWorkloadLifecycle, createDockerBindingAuthorizer }, accounts] = await Promise.all([
|
|
8625
|
-
import("./workloadLifecycle-
|
|
8626
|
-
import("./accountResolver-
|
|
8296
|
+
import("./workloadLifecycle-6O6PMISX.js"),
|
|
8297
|
+
import("./accountResolver-55EDKEIK.js")
|
|
8627
8298
|
]);
|
|
8628
8299
|
const resolveAccount = args.resolveAccount ?? accounts.createDockerAccountResolver({
|
|
8629
8300
|
env: args.env,
|
|
@@ -8640,7 +8311,28 @@ async function createLocalDockerWorkload(args) {
|
|
|
8640
8311
|
resolveAccount
|
|
8641
8312
|
});
|
|
8642
8313
|
});
|
|
8643
|
-
const
|
|
8314
|
+
const phaseLogEnabled = () => {
|
|
8315
|
+
const env = args.env;
|
|
8316
|
+
return env.NOLO_DEBUG === "1" || env.NOLO_CLI_DEBUG_DETAIL === "1";
|
|
8317
|
+
};
|
|
8318
|
+
const phaseLog = (event, payload) => {
|
|
8319
|
+
if (!phaseLogEnabled()) return;
|
|
8320
|
+
console.warn(`[docker-workload-phase] ${event}`, payload);
|
|
8321
|
+
};
|
|
8322
|
+
const phase = async (name, operation) => {
|
|
8323
|
+
const startedAt = Date.now();
|
|
8324
|
+
phaseLog("start", { phase: name, runId: args.runId });
|
|
8325
|
+
try {
|
|
8326
|
+
const result = await operation();
|
|
8327
|
+
phaseLog("complete", { phase: name, runId: args.runId, elapsedMs: Date.now() - startedAt });
|
|
8328
|
+
return result;
|
|
8329
|
+
} catch (error) {
|
|
8330
|
+
const safeError = error && typeof error === "object" ? error : {};
|
|
8331
|
+
phaseLog("failed", { phase: name, runId: args.runId, elapsedMs: Date.now() - startedAt, errorCode: typeof safeError.code === "string" ? safeError.code : void 0, errorName: typeof safeError.name === "string" ? safeError.name : void 0 });
|
|
8332
|
+
throw error;
|
|
8333
|
+
}
|
|
8334
|
+
};
|
|
8335
|
+
const lifecycle = await phase("create-lifecycle", () => createLifecycle());
|
|
8644
8336
|
const grant = {
|
|
8645
8337
|
version: 1,
|
|
8646
8338
|
grantId: `grant-${args.runId}`,
|
|
@@ -8658,25 +8350,29 @@ async function createLocalDockerWorkload(args) {
|
|
|
8658
8350
|
}
|
|
8659
8351
|
};
|
|
8660
8352
|
const workspaceRoot = args.workspaceRoot ?? process.cwd();
|
|
8353
|
+
const workspaceMode = args.workspaceMode ?? "git";
|
|
8661
8354
|
const prepareDelivery = args.prepareWorkspaceDelivery ?? prepareHostWorkspaceDelivery;
|
|
8662
8355
|
const applyDelivery = args.applyWorkspaceDelivery ?? applyDockerWorkspaceDelivery;
|
|
8663
8356
|
let deliveryApplied = false;
|
|
8664
8357
|
const deliverWorkspace = async (runtime) => {
|
|
8665
8358
|
if (deliveryApplied) return;
|
|
8666
8359
|
deliveryApplied = true;
|
|
8667
|
-
const prepared =
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8360
|
+
const prepared = await phase("host-archive", () => {
|
|
8361
|
+
const result = prepareDelivery({ workspaceRoot });
|
|
8362
|
+
if (!result.ok) {
|
|
8363
|
+
throw new LocalWorkspaceDeliveryError(
|
|
8364
|
+
result.code,
|
|
8365
|
+
`${result.message}\uFF08\u5BBF\u4E3B\u4FA7\u6295\u9001\u51C6\u5907\u5931\u8D25\uFF0C\u672C run \u62D2\u7EDD\u8FDB\u5165\u5DE5\u5177\u5FAA\u73AF\uFF09`
|
|
8366
|
+
);
|
|
8367
|
+
}
|
|
8368
|
+
return result;
|
|
8369
|
+
});
|
|
8674
8370
|
if (args.signal?.aborted) {
|
|
8675
8371
|
await prepared.cleanup();
|
|
8676
8372
|
throw new LocalWorkspaceDeliveryError("delivery_cancelled", "run \u5DF2\u53D6\u6D88\uFF0C\u653E\u5F03\u5DE5\u4F5C\u533A\u6295\u9001\u3002");
|
|
8677
8373
|
}
|
|
8678
8374
|
try {
|
|
8679
|
-
await applyDelivery(runtime, prepared.selection);
|
|
8375
|
+
await phase("delivery", () => applyDelivery(runtime, prepared.selection));
|
|
8680
8376
|
} catch (error) {
|
|
8681
8377
|
const code = isDockerWorkspaceDeliveryError(error) ? error.code : "delivery_failed";
|
|
8682
8378
|
throw new LocalWorkspaceDeliveryError(
|
|
@@ -8725,11 +8421,39 @@ async function createLocalDockerWorkload(args) {
|
|
|
8725
8421
|
},
|
|
8726
8422
|
async (workload2, runtime) => {
|
|
8727
8423
|
if (runtime) {
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8424
|
+
await phase("sandbox-helper-upload", async () => {
|
|
8425
|
+
const uploaded = await runtime.exec(buildSandboxHelperUploadArgv());
|
|
8426
|
+
if (!uploaded.ok) {
|
|
8427
|
+
throw Object.assign(new Error("docker_helper_upload_failed"), { code: "docker_helper_upload_failed" });
|
|
8428
|
+
}
|
|
8429
|
+
});
|
|
8430
|
+
if (workspaceMode === "git") {
|
|
8431
|
+
await deliverWorkspace(runtime);
|
|
8432
|
+
} else {
|
|
8433
|
+
await phase("empty-workspace-root", async () => {
|
|
8434
|
+
const root = await runtime.exec([
|
|
8435
|
+
"bash",
|
|
8436
|
+
"-lc",
|
|
8437
|
+
`mkdir -p '${SANDBOX_WORKSPACE_ROOT}' && test -d '${SANDBOX_WORKSPACE_ROOT}' && test -w '${SANDBOX_WORKSPACE_ROOT}'`
|
|
8438
|
+
]);
|
|
8439
|
+
if (!root.ok) {
|
|
8440
|
+
throw Object.assign(new Error("docker_empty_workspace_root_failed"), { code: "docker_empty_workspace_root_failed" });
|
|
8441
|
+
}
|
|
8442
|
+
const gitInstall = await runtime.exec(buildInstallGitArgv());
|
|
8443
|
+
if (!gitInstall.ok) {
|
|
8444
|
+
throw Object.assign(
|
|
8445
|
+
new Error(`docker_empty_workspace_git_install_failed (exit ${gitInstall.exitCode})`),
|
|
8446
|
+
{ code: "docker_empty_workspace_git_install_failed" }
|
|
8447
|
+
);
|
|
8448
|
+
}
|
|
8449
|
+
const gitProbe = await runtime.exec(["bash", "-lc", "command -v git"]);
|
|
8450
|
+
if (!gitProbe.ok) {
|
|
8451
|
+
throw Object.assign(new Error("docker_empty_workspace_git_missing"), { code: "docker_empty_workspace_git_missing" });
|
|
8452
|
+
}
|
|
8453
|
+
});
|
|
8454
|
+
}
|
|
8731
8455
|
}
|
|
8732
|
-
resolveReady(workload2);
|
|
8456
|
+
await phase("ready", () => resolveReady(workload2));
|
|
8733
8457
|
await waitForReleaseOrAbort();
|
|
8734
8458
|
return void 0;
|
|
8735
8459
|
}
|
|
@@ -8786,6 +8510,7 @@ async function createLocalDockerWorkload(args) {
|
|
|
8786
8510
|
var INSTABOX_BACKEND_ID = "instabox";
|
|
8787
8511
|
var INSTABOX_DEFAULT_BASE_URL = "https://api.instabox.sh/v1";
|
|
8788
8512
|
var INSTABOX_MAX_EXEC_SECONDS = 600;
|
|
8513
|
+
var INSTABOX_MAX_STDIN_BYTES = 1024 * 1024;
|
|
8789
8514
|
var SAFE_MESSAGE3 = {
|
|
8790
8515
|
"instabox_invalid_config": "Rejected: instabox backend needs an apiKey and a templateId",
|
|
8791
8516
|
"instabox_invalid_ticket": "Rejected: execution ticket cannot be satisfied by the instabox backend",
|
|
@@ -8951,9 +8676,9 @@ var InstaboxBackend = class {
|
|
|
8951
8676
|
`create HTTP ${created.status}${created.transportError ? ` ${created.transportError}` : ""}`
|
|
8952
8677
|
);
|
|
8953
8678
|
}
|
|
8954
|
-
const
|
|
8955
|
-
const machineId = readString2(
|
|
8956
|
-
const operationId = readString2(
|
|
8679
|
+
const record = asRecord(created.payload);
|
|
8680
|
+
const machineId = readString2(record?.machineId);
|
|
8681
|
+
const operationId = readString2(record?.id);
|
|
8957
8682
|
if (!machineId || !operationId) {
|
|
8958
8683
|
throw new InstaboxBackendError(
|
|
8959
8684
|
"instabox_create_failed",
|
|
@@ -9019,12 +8744,7 @@ var InstaboxBackend = class {
|
|
|
9019
8744
|
"argv must be a non-empty array"
|
|
9020
8745
|
);
|
|
9021
8746
|
}
|
|
9022
|
-
|
|
9023
|
-
throw new InstaboxBackendError(
|
|
9024
|
-
"instabox_unsupported_request",
|
|
9025
|
-
"instabox exec has no stdin channel"
|
|
9026
|
-
);
|
|
9027
|
-
}
|
|
8747
|
+
const stdin = this.#resolveStdin(request.stdin);
|
|
9028
8748
|
const timeoutSeconds = this.#resolveExecTimeoutSeconds(request.timeoutMs);
|
|
9029
8749
|
const cmd = this.#buildCommand(request);
|
|
9030
8750
|
const executionId = `${entry.machineId}:${this.#now().toString(36)}`;
|
|
@@ -9033,7 +8753,7 @@ var InstaboxBackend = class {
|
|
|
9033
8753
|
const response = await this.#call({
|
|
9034
8754
|
method: "POST",
|
|
9035
8755
|
path: `/machines/${encodeURIComponent(entry.machineId)}/exec`,
|
|
9036
|
-
body: { cmd, timeoutSeconds }
|
|
8756
|
+
body: { cmd, timeoutSeconds, ...stdin === void 0 ? {} : { stdin } }
|
|
9037
8757
|
});
|
|
9038
8758
|
if (!isSuccess(response.status)) {
|
|
9039
8759
|
throw new InstaboxBackendError(
|
|
@@ -9161,6 +8881,27 @@ var InstaboxBackend = class {
|
|
|
9161
8881
|
}
|
|
9162
8882
|
return entry;
|
|
9163
8883
|
}
|
|
8884
|
+
/**
|
|
8885
|
+
* stdin 直通校验:`undefined` = 请求里没提供(body 里也不加字段,保持原报文兼容);
|
|
8886
|
+
* 字符串(含空串)在 1 MiB / UTF-8 字节以内原样透传;其他类型或超限立即拒绝,
|
|
8887
|
+
* 错误文案只带上限数字,**绝不回显输入内容**。
|
|
8888
|
+
*/
|
|
8889
|
+
#resolveStdin(stdin) {
|
|
8890
|
+
if (stdin === void 0) return void 0;
|
|
8891
|
+
if (typeof stdin !== "string") {
|
|
8892
|
+
throw new InstaboxBackendError(
|
|
8893
|
+
"instabox_unsupported_request",
|
|
8894
|
+
"stdin must be a string"
|
|
8895
|
+
);
|
|
8896
|
+
}
|
|
8897
|
+
if (utf8ByteLengthExceeds(stdin, INSTABOX_MAX_STDIN_BYTES)) {
|
|
8898
|
+
throw new InstaboxBackendError(
|
|
8899
|
+
"instabox_unsupported_request",
|
|
8900
|
+
`stdin exceeds the ${INSTABOX_MAX_STDIN_BYTES} byte limit`
|
|
8901
|
+
);
|
|
8902
|
+
}
|
|
8903
|
+
return stdin;
|
|
8904
|
+
}
|
|
9164
8905
|
#resolveExecTimeoutSeconds(timeoutMs) {
|
|
9165
8906
|
const boundMs = INSTABOX_MAX_EXEC_SECONDS * 1e3;
|
|
9166
8907
|
if (timeoutMs === void 0) return this.#execTimeoutSeconds;
|
|
@@ -9178,7 +8919,7 @@ var InstaboxBackend = class {
|
|
|
9178
8919
|
}
|
|
9179
8920
|
return clampExecSeconds(Math.ceil(timeoutMs / 1e3));
|
|
9180
8921
|
}
|
|
9181
|
-
/** cwd / env
|
|
8922
|
+
/** cwd / env 仍用 `cd` + 赋值前缀表达(exec body 只多一个可选 stdin,不承载 cwd/env)。 */
|
|
9182
8923
|
#buildCommand(request) {
|
|
9183
8924
|
const script = argvToInstaboxCommand(request.argv);
|
|
9184
8925
|
const segments = [];
|
|
@@ -9236,15 +8977,15 @@ var InstaboxBackend = class {
|
|
|
9236
8977
|
path: `/machines/${encodeURIComponent(machineId)}/usage`
|
|
9237
8978
|
});
|
|
9238
8979
|
if (!isSuccess(response.status)) return null;
|
|
9239
|
-
const
|
|
9240
|
-
const runningSeconds = readFiniteNumber(
|
|
8980
|
+
const record = asRecord(response.payload);
|
|
8981
|
+
const runningSeconds = readFiniteNumber(record?.runningSeconds);
|
|
9241
8982
|
if (runningSeconds === null) return null;
|
|
9242
8983
|
const sample = { runningSeconds };
|
|
9243
|
-
const vcpuSeconds = readFiniteNumber(
|
|
8984
|
+
const vcpuSeconds = readFiniteNumber(record?.vcpuSeconds);
|
|
9244
8985
|
if (vcpuSeconds !== null) sample.vcpuSeconds = vcpuSeconds;
|
|
9245
|
-
const memGiBSeconds = readFiniteNumber(
|
|
8986
|
+
const memGiBSeconds = readFiniteNumber(record?.memGiBSeconds);
|
|
9246
8987
|
if (memGiBSeconds !== null) sample.memGiBSeconds = memGiBSeconds;
|
|
9247
|
-
const diskGiBSeconds = readFiniteNumber(
|
|
8988
|
+
const diskGiBSeconds = readFiniteNumber(record?.diskGiBSeconds);
|
|
9248
8989
|
if (diskGiBSeconds !== null) sample.diskGiBSeconds = diskGiBSeconds;
|
|
9249
8990
|
return sample;
|
|
9250
8991
|
}
|
|
@@ -9264,13 +9005,13 @@ var InstaboxBackend = class {
|
|
|
9264
9005
|
path: `/operations/${encodeURIComponent(args.operationId)}?wait=${this.#operationWaitSeconds}s`
|
|
9265
9006
|
});
|
|
9266
9007
|
lastStatus = response.status;
|
|
9267
|
-
const
|
|
9268
|
-
const state = readString2(
|
|
9008
|
+
const record = isSuccess(response.status) ? asRecord(response.payload) : null;
|
|
9009
|
+
const state = readString2(record?.state);
|
|
9269
9010
|
if (state === "succeeded") return;
|
|
9270
9011
|
if (state === "failed") {
|
|
9271
9012
|
throw new InstaboxBackendError(
|
|
9272
9013
|
args.failCode,
|
|
9273
|
-
`operation ${args.operationId} failed${readString2(
|
|
9014
|
+
`operation ${args.operationId} failed${readString2(record?.error) ? `: ${readString2(record?.error)}` : ""}`,
|
|
9274
9015
|
args.cleanupPendingOnFailure
|
|
9275
9016
|
);
|
|
9276
9017
|
}
|
|
@@ -9294,6 +9035,10 @@ function truncateOutput(value, limitChars) {
|
|
|
9294
9035
|
if (value.length <= limitChars) return value;
|
|
9295
9036
|
return `${value.slice(0, limitChars)}\u2026[truncated ${value.length - limitChars} chars]`;
|
|
9296
9037
|
}
|
|
9038
|
+
function utf8ByteLengthExceeds(value, limit) {
|
|
9039
|
+
if (value.length > limit) return true;
|
|
9040
|
+
return new TextEncoder().encode(value).length > limit;
|
|
9041
|
+
}
|
|
9297
9042
|
function createInstaboxExecutionBackend(options) {
|
|
9298
9043
|
return new InstaboxBackend(options);
|
|
9299
9044
|
}
|
|
@@ -9308,6 +9053,213 @@ function asExecutionBackend(backend) {
|
|
|
9308
9053
|
};
|
|
9309
9054
|
}
|
|
9310
9055
|
|
|
9056
|
+
// packages/cli/client/localInstaboxFileBridge.ts
|
|
9057
|
+
var INSTABOX_HELPER_PATH = SANDBOX_HELPER_PATH;
|
|
9058
|
+
var INSTABOX_WORKSPACE_ROOT = "/data/home";
|
|
9059
|
+
var INSTABOX_FILE_TOOL_NAMES = [
|
|
9060
|
+
"readFile",
|
|
9061
|
+
"writeFile",
|
|
9062
|
+
"editFile",
|
|
9063
|
+
"globFiles"
|
|
9064
|
+
];
|
|
9065
|
+
var PROBE_FILE_NAME = "nolo-bridge-probe";
|
|
9066
|
+
function escapeForShell(value) {
|
|
9067
|
+
const cleaned = String(value).replace(/[^A-Za-z0-9._-]/g, "-").slice(0, 40);
|
|
9068
|
+
return cleaned || "run";
|
|
9069
|
+
}
|
|
9070
|
+
var PROBE_FILE_CONTENT = "nolo-bridge-ok";
|
|
9071
|
+
function posixQuote(value) {
|
|
9072
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
9073
|
+
}
|
|
9074
|
+
function buildInstaboxHelperSource(root) {
|
|
9075
|
+
const source = buildWorkspaceHelperSource();
|
|
9076
|
+
const rootLiteral = /const ROOT = "[^"]*";/;
|
|
9077
|
+
if (!rootLiteral.test(source)) {
|
|
9078
|
+
throw new Error("instabox_helper_root_patch_failed");
|
|
9079
|
+
}
|
|
9080
|
+
if (!root.startsWith("/") || root.includes('"') || root.includes("\\")) {
|
|
9081
|
+
throw new Error("instabox_invalid_workspace_root");
|
|
9082
|
+
}
|
|
9083
|
+
return source.replace(rootLiteral, `const ROOT = "${root}";`);
|
|
9084
|
+
}
|
|
9085
|
+
function buildInstaboxBridgeBootstrapScript(root, probeId) {
|
|
9086
|
+
let helperPayload;
|
|
9087
|
+
if (!root.startsWith("/") || root.includes('"') || root.includes("\\")) {
|
|
9088
|
+
return `printf 'NOLO_BRIDGE_REASON=root_unavailable
|
|
9089
|
+
'`;
|
|
9090
|
+
}
|
|
9091
|
+
try {
|
|
9092
|
+
helperPayload = Buffer.from(buildInstaboxHelperSource(root), "utf8").toString("base64");
|
|
9093
|
+
} catch (error) {
|
|
9094
|
+
return `printf 'NOLO_BRIDGE_REASON=helper_source_invalid
|
|
9095
|
+
'`;
|
|
9096
|
+
}
|
|
9097
|
+
const dir = INSTABOX_HELPER_PATH.slice(0, INSTABOX_HELPER_PATH.lastIndexOf("/"));
|
|
9098
|
+
return [
|
|
9099
|
+
`root=${posixQuote(root)}`,
|
|
9100
|
+
`mkdir -p "$root" 2>/dev/null || true`,
|
|
9101
|
+
`if [ ! -w "$root" ]; then printf 'NOLO_BRIDGE_REASON=root_unavailable\\n'; exit 0; fi`,
|
|
9102
|
+
`printf 'NOLO_BRIDGE_ROOT=%s\\n' "$root"`,
|
|
9103
|
+
"rt=''",
|
|
9104
|
+
`for cand in bun node; do if command -v "$cand" >/dev/null 2>&1; then rt="$cand"; break; fi; done`,
|
|
9105
|
+
`printf 'NOLO_BRIDGE_RUNTIME=%s\\n' "\${rt:-none}"`,
|
|
9106
|
+
`if [ -z "$rt" ]; then printf 'NOLO_BRIDGE_REASON=runtime_missing\\n'; exit 0; fi`,
|
|
9107
|
+
`mkdir -p ${posixQuote(dir)} 2>/dev/null || true`,
|
|
9108
|
+
`if ! printf %s ${posixQuote(helperPayload)} | base64 -d > ${posixQuote(INSTABOX_HELPER_PATH)}; then printf 'NOLO_BRIDGE_REASON=upload_failed\\n'; exit 0; fi`,
|
|
9109
|
+
`chmod 0644 ${posixQuote(INSTABOX_HELPER_PATH)} 2>/dev/null || true`,
|
|
9110
|
+
// 探针文件名带本次 run 的唯一 id:**只创建自己的**,绝不覆盖/删除同名既有文件
|
|
9111
|
+
`probe=$root/${escapeForShell(probeId)}-${PROBE_FILE_NAME}`,
|
|
9112
|
+
`if [ -e "$probe" ]; then printf 'NOLO_BRIDGE_REASON=probe_failed\\n'; exit 0; fi`,
|
|
9113
|
+
`printf %s ${posixQuote(PROBE_FILE_CONTENT)} > "$probe" || { printf 'NOLO_BRIDGE_REASON=upload_failed\\n'; exit 0; }`,
|
|
9114
|
+
`printf 'NOLO_BRIDGE_PROBE=%s\\n' "$probe"`,
|
|
9115
|
+
`printf 'NOLO_BRIDGE_UPLOAD=ok\\n'`
|
|
9116
|
+
].join("\n");
|
|
9117
|
+
}
|
|
9118
|
+
function parseInstaboxBootstrapOutput(stdout) {
|
|
9119
|
+
let root = null;
|
|
9120
|
+
let probePath = null;
|
|
9121
|
+
let runtime = null;
|
|
9122
|
+
let reason;
|
|
9123
|
+
let uploadOk = false;
|
|
9124
|
+
for (const rawLine of stdout.split(String.fromCharCode(10))) {
|
|
9125
|
+
const line = rawLine.trim();
|
|
9126
|
+
if (line.startsWith("NOLO_BRIDGE_ROOT=")) {
|
|
9127
|
+
const value = line.slice("NOLO_BRIDGE_ROOT=".length).trim();
|
|
9128
|
+
root = value.startsWith("/") ? value : null;
|
|
9129
|
+
} else if (line.startsWith("NOLO_BRIDGE_RUNTIME=")) {
|
|
9130
|
+
const value = line.slice("NOLO_BRIDGE_RUNTIME=".length).trim();
|
|
9131
|
+
runtime = value === "bun" || value === "node" ? value : null;
|
|
9132
|
+
} else if (line.startsWith("NOLO_BRIDGE_UPLOAD=")) {
|
|
9133
|
+
uploadOk = line.slice("NOLO_BRIDGE_UPLOAD=".length).trim() === "ok";
|
|
9134
|
+
} else if (line.startsWith("NOLO_BRIDGE_PROBE=")) {
|
|
9135
|
+
const value = line.slice("NOLO_BRIDGE_PROBE=".length).trim();
|
|
9136
|
+
probePath = value.startsWith("/") ? value : null;
|
|
9137
|
+
} else if (line.startsWith("NOLO_BRIDGE_REASON=")) {
|
|
9138
|
+
const value = line.slice("NOLO_BRIDGE_REASON=".length).trim();
|
|
9139
|
+
reason = value === "runtime_missing" || value === "root_unavailable" || value === "upload_failed" || value === "probe_failed" || value === "root_mismatch" || value === "helper_source_invalid" ? value : "probe_failed";
|
|
9140
|
+
}
|
|
9141
|
+
}
|
|
9142
|
+
if (!root) return { root: null, runtime: null, probePath: null, reason: reason ?? "root_unavailable" };
|
|
9143
|
+
if (!runtime) return { root, runtime: null, probePath, reason: reason ?? "runtime_missing" };
|
|
9144
|
+
if (!uploadOk) return { root, runtime, probePath, reason: reason ?? "upload_failed" };
|
|
9145
|
+
if (!probePath) return { root, runtime, probePath: null, reason: reason ?? "probe_failed" };
|
|
9146
|
+
return { root, runtime, probePath };
|
|
9147
|
+
}
|
|
9148
|
+
function resolveInstaboxPath(root, input) {
|
|
9149
|
+
if (typeof input !== "string" || !input.trim() || input.includes("\0")) {
|
|
9150
|
+
return { ok: false, error: "invalid_path" };
|
|
9151
|
+
}
|
|
9152
|
+
const normalizedRoot = root.endsWith("/") ? root.slice(0, -1) : root;
|
|
9153
|
+
const isAbs = input.startsWith("/");
|
|
9154
|
+
if (isAbs && input !== normalizedRoot && !input.startsWith(`${normalizedRoot}/`)) {
|
|
9155
|
+
return { ok: false, error: "path_outside_workspace" };
|
|
9156
|
+
}
|
|
9157
|
+
const resolved = isAbs ? posixNormalize(input) : posixNormalize(`${normalizedRoot}/${input}`);
|
|
9158
|
+
if (resolved !== normalizedRoot && !resolved.startsWith(`${normalizedRoot}/`)) {
|
|
9159
|
+
return { ok: false, error: "path_escape" };
|
|
9160
|
+
}
|
|
9161
|
+
return { ok: true, path: resolved };
|
|
9162
|
+
}
|
|
9163
|
+
function posixNormalize(input) {
|
|
9164
|
+
const parts = [];
|
|
9165
|
+
for (const segment of input.split("/")) {
|
|
9166
|
+
if (!segment || segment === ".") continue;
|
|
9167
|
+
if (segment === "..") {
|
|
9168
|
+
parts.pop();
|
|
9169
|
+
continue;
|
|
9170
|
+
}
|
|
9171
|
+
parts.push(segment);
|
|
9172
|
+
}
|
|
9173
|
+
return `/${parts.join("/")}`;
|
|
9174
|
+
}
|
|
9175
|
+
function buildInstaboxToolArgv(toolName, args, bridge) {
|
|
9176
|
+
const validated = {};
|
|
9177
|
+
let op;
|
|
9178
|
+
switch (toolName) {
|
|
9179
|
+
case "readFile": {
|
|
9180
|
+
const res = resolveInstaboxPath(bridge.root, String(args.path ?? ""));
|
|
9181
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
9182
|
+
op = "readFile";
|
|
9183
|
+
validated.path = res.path;
|
|
9184
|
+
if (typeof args.lines === "string") validated.lines = args.lines;
|
|
9185
|
+
break;
|
|
9186
|
+
}
|
|
9187
|
+
case "writeFile": {
|
|
9188
|
+
if (typeof args.content !== "string") return { ok: false, error: "missing_content" };
|
|
9189
|
+
if (Buffer.byteLength(args.content, "utf-8") > SANDBOX_OUTPUT_LIMITS.maxContentBytes) {
|
|
9190
|
+
return { ok: false, error: "content_too_large" };
|
|
9191
|
+
}
|
|
9192
|
+
const res = resolveInstaboxPath(bridge.root, String(args.path ?? ""));
|
|
9193
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
9194
|
+
op = "writeFile";
|
|
9195
|
+
validated.path = res.path;
|
|
9196
|
+
validated.content = args.content;
|
|
9197
|
+
break;
|
|
9198
|
+
}
|
|
9199
|
+
case "editFile": {
|
|
9200
|
+
if (typeof args.oldText !== "string" || typeof args.newText !== "string") {
|
|
9201
|
+
return { ok: false, error: "missing_edit_text" };
|
|
9202
|
+
}
|
|
9203
|
+
if (args.oldText === args.newText) return { ok: false, error: "edit_text_identical" };
|
|
9204
|
+
if (Buffer.byteLength(args.newText, "utf-8") > SANDBOX_OUTPUT_LIMITS.maxContentBytes) {
|
|
9205
|
+
return { ok: false, error: "content_too_large" };
|
|
9206
|
+
}
|
|
9207
|
+
const res = resolveInstaboxPath(bridge.root, String(args.path ?? ""));
|
|
9208
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
9209
|
+
op = "editFile";
|
|
9210
|
+
validated.path = res.path;
|
|
9211
|
+
validated.oldText = args.oldText;
|
|
9212
|
+
validated.newText = args.newText;
|
|
9213
|
+
break;
|
|
9214
|
+
}
|
|
9215
|
+
case "globFiles":
|
|
9216
|
+
case "glob": {
|
|
9217
|
+
if (typeof args.pattern !== "string" || !args.pattern.trim()) {
|
|
9218
|
+
return { ok: false, error: "missing_pattern" };
|
|
9219
|
+
}
|
|
9220
|
+
op = "glob";
|
|
9221
|
+
validated.pattern = args.pattern;
|
|
9222
|
+
if (typeof args.path === "string" && args.path.trim()) {
|
|
9223
|
+
const res = resolveInstaboxPath(bridge.root, args.path);
|
|
9224
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
9225
|
+
validated.path = res.path;
|
|
9226
|
+
}
|
|
9227
|
+
break;
|
|
9228
|
+
}
|
|
9229
|
+
default:
|
|
9230
|
+
return { ok: false, error: "unsupported_tool" };
|
|
9231
|
+
}
|
|
9232
|
+
const payload = Buffer.from(JSON.stringify({ op, args: validated }), "utf-8").toString("base64");
|
|
9233
|
+
if (payload.length > SANDBOX_OUTPUT_LIMITS.maxArgvBytes) {
|
|
9234
|
+
return { ok: false, error: "content_too_large" };
|
|
9235
|
+
}
|
|
9236
|
+
return { ok: true, argv: [bridge.runtime, INSTABOX_HELPER_PATH, payload] };
|
|
9237
|
+
}
|
|
9238
|
+
function buildInstaboxBridgeProbeRequest(bridge, probePath) {
|
|
9239
|
+
const payload = Buffer.from(
|
|
9240
|
+
JSON.stringify({ op: "readFile", args: { path: probePath } }),
|
|
9241
|
+
"utf-8"
|
|
9242
|
+
).toString("base64");
|
|
9243
|
+
return { kind: "command", argv: [bridge.runtime, INSTABOX_HELPER_PATH, payload] };
|
|
9244
|
+
}
|
|
9245
|
+
function readInstaboxProbeResult(stdout) {
|
|
9246
|
+
if (typeof stdout !== "string") return { ready: false, reason: "probe_failed" };
|
|
9247
|
+
const text = stdout.trim();
|
|
9248
|
+
if (!text) return { ready: false, reason: "probe_failed" };
|
|
9249
|
+
if (text.includes('"ok":false') || text.includes("'ok':false")) {
|
|
9250
|
+
return { ready: false, reason: "probe_failed" };
|
|
9251
|
+
}
|
|
9252
|
+
if (text.includes(PROBE_FILE_CONTENT)) return { ready: true };
|
|
9253
|
+
const parsed = parseToolOutput(text);
|
|
9254
|
+
if (!parsed.ok) return { ready: false, reason: "probe_failed" };
|
|
9255
|
+
const value = parsed.value;
|
|
9256
|
+
return typeof value === "object" && value !== null && typeof value.content === "string" && value.content.includes(PROBE_FILE_CONTENT) ? { ready: true } : { ready: false, reason: "probe_failed" };
|
|
9257
|
+
}
|
|
9258
|
+
function describeInstaboxBridgeUnavailable(bridge) {
|
|
9259
|
+
const detail = bridge.reason === "runtime_missing" ? "Instabox \u6A21\u677F\u5185\u65E2\u6CA1\u6709 bun \u4E5F\u6CA1\u6709 node\uFF0C\u5BB9\u5668\u5185 helper \u65E0\u6CD5\u6267\u884C" : bridge.reason === "root_unavailable" ? "Instabox \u5BB9\u5668\u5185\u65E0\u6CD5\u521B\u5EFA\u53EF\u5199\u5DE5\u4F5C\u76EE\u5F55" : bridge.reason === "upload_failed" ? "\u5BB9\u5668\u5185 helper \u4E0A\u4F20\u5931\u8D25" : bridge.reason === "root_mismatch" ? "\u5BB9\u5668\u5185\u56FA\u5B9A\u5DE5\u4F5C\u76EE\u5F55\u4E0E helper ROOT \u4E0D\u4E00\u81F4" : bridge.reason === "helper_source_invalid" ? "\u5171\u4EAB helper \u6E90\u7801\u5F62\u72B6\u53D8\u5316\uFF0C\u65E0\u6CD5\u5B89\u5168\u6539\u5199 ROOT" : "\u5BB9\u5668\u5185 helper \u63A2\u9488\u8BFB\u56DE\u5931\u8D25";
|
|
9260
|
+
return `instabox \u6587\u4EF6\u5DE5\u5177 bridge \u672A\u5C31\u7EEA\uFF08${bridge.reason ?? "probe_failed"}\uFF09\uFF1A${detail}\uFF1B\u6587\u4EF6\u5DE5\u5177\u5DF2\u663E\u5F0F\u62D2\u7EDD\uFF0C\u7EDD\u4E0D\u56DE\u843D\u5BBF\u4E3B\u6267\u884C\uFF08execShell \u4ECD\u53EF\u7528\uFF09\u3002`;
|
|
9261
|
+
}
|
|
9262
|
+
|
|
9311
9263
|
// packages/cli/client/localInstaboxWorkload.ts
|
|
9312
9264
|
var LOCAL_INSTABOX_BACKEND_ID = INSTABOX_BACKEND_ID;
|
|
9313
9265
|
function resolveInstaboxApiKey(env) {
|
|
@@ -9328,6 +9280,35 @@ function assertInstaboxPrerequisites(env) {
|
|
|
9328
9280
|
}
|
|
9329
9281
|
return apiKey;
|
|
9330
9282
|
}
|
|
9283
|
+
function resolveInstaboxWorkspaceRoot(env) {
|
|
9284
|
+
const override = env.INSTABOX_WORKSPACE_ROOT?.trim();
|
|
9285
|
+
if (override && override.startsWith("/") && !override.includes('"')) return override;
|
|
9286
|
+
return INSTABOX_WORKSPACE_ROOT;
|
|
9287
|
+
}
|
|
9288
|
+
function posixQuote2(value) {
|
|
9289
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
9290
|
+
}
|
|
9291
|
+
async function prepareFileBridge(execDirect, root, probeId) {
|
|
9292
|
+
const bootstrapStdout = await execDirect({
|
|
9293
|
+
kind: "command",
|
|
9294
|
+
argv: ["bash", "-lc", buildInstaboxBridgeBootstrapScript(root, probeId)]
|
|
9295
|
+
});
|
|
9296
|
+
const parsed = parseInstaboxBootstrapOutput(bootstrapStdout);
|
|
9297
|
+
if (!parsed.root || !parsed.runtime || !parsed.probePath || parsed.reason) {
|
|
9298
|
+
return {
|
|
9299
|
+
root: parsed.root,
|
|
9300
|
+
runtime: parsed.runtime,
|
|
9301
|
+
ready: false,
|
|
9302
|
+
reason: parsed.reason ?? "probe_failed"
|
|
9303
|
+
};
|
|
9304
|
+
}
|
|
9305
|
+
const pinned = { root: parsed.root, runtime: parsed.runtime };
|
|
9306
|
+
const probeStdout = await execDirect(
|
|
9307
|
+
buildInstaboxBridgeProbeRequest(pinned, parsed.probePath)
|
|
9308
|
+
);
|
|
9309
|
+
const verdict = readInstaboxProbeResult(probeStdout);
|
|
9310
|
+
return verdict.ready ? { root: pinned.root, runtime: pinned.runtime, ready: true } : { root: pinned.root, runtime: pinned.runtime, ready: false, reason: verdict.reason ?? "probe_failed" };
|
|
9311
|
+
}
|
|
9331
9312
|
async function createLocalInstaboxWorkload(args) {
|
|
9332
9313
|
if (args.runtimeKey.trim() !== "instabox") {
|
|
9333
9314
|
throw new LocalRuntimeKeyUnsupportedError(
|
|
@@ -9342,6 +9323,7 @@ async function createLocalInstaboxWorkload(args) {
|
|
|
9342
9323
|
templateId: args.templateId ?? args.env.INSTABOX_TEMPLATE_ID?.trim() ?? "universal"
|
|
9343
9324
|
})
|
|
9344
9325
|
);
|
|
9326
|
+
const workspaceRoot = resolveInstaboxWorkspaceRoot(args.env);
|
|
9345
9327
|
const ticket = {
|
|
9346
9328
|
version: 1,
|
|
9347
9329
|
ticketId: `ticket-${args.runId}`,
|
|
@@ -9351,12 +9333,14 @@ async function createLocalInstaboxWorkload(args) {
|
|
|
9351
9333
|
callerUserId: args.authenticatedCaller || "local-caller",
|
|
9352
9334
|
executionClass: "session",
|
|
9353
9335
|
target: { kind: "server" },
|
|
9354
|
-
|
|
9336
|
+
// 本 workload 真的会执行这些工具(shell + 容器内结构化文件工具),授权声明必须一致
|
|
9337
|
+
toolNames: [EXECUTION_SHELL_TOOL, ...INSTABOX_FILE_TOOL_NAMES],
|
|
9355
9338
|
filesystem: {
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9339
|
+
// 钉住的固定工作目录:读写范围都声明成它,不写 "none" 再偷偷写文件
|
|
9340
|
+
readScope: "configured-roots",
|
|
9341
|
+
readableRoots: [workspaceRoot],
|
|
9342
|
+
writeScope: "configured-roots",
|
|
9343
|
+
writableRoots: [workspaceRoot]
|
|
9360
9344
|
},
|
|
9361
9345
|
shellAllowed: true,
|
|
9362
9346
|
requestedIsolation: "container",
|
|
@@ -9371,37 +9355,118 @@ async function createLocalInstaboxWorkload(args) {
|
|
|
9371
9355
|
`runtimeKey \u6307\u5411 instabox\uFF0C\u4F46\u4E91\u6C99\u76D2\u521D\u59CB\u5316\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}\u3002${instaboxFailureHint}`
|
|
9372
9356
|
);
|
|
9373
9357
|
}
|
|
9358
|
+
let releaseState = "active";
|
|
9359
|
+
let releasePromise = null;
|
|
9360
|
+
const releaseBackend = () => {
|
|
9361
|
+
if (releaseState === "released") return Promise.resolve();
|
|
9362
|
+
if (releasePromise) return releasePromise;
|
|
9363
|
+
releaseState = "releasing";
|
|
9364
|
+
let attempt;
|
|
9365
|
+
try {
|
|
9366
|
+
attempt = Promise.resolve(backend.release(lease, "completed"));
|
|
9367
|
+
} catch (error) {
|
|
9368
|
+
attempt = Promise.reject(error);
|
|
9369
|
+
}
|
|
9370
|
+
releasePromise = attempt.then(
|
|
9371
|
+
() => {
|
|
9372
|
+
releaseState = "released";
|
|
9373
|
+
},
|
|
9374
|
+
(error) => {
|
|
9375
|
+
releaseState = "cleanup_pending";
|
|
9376
|
+
throw error;
|
|
9377
|
+
}
|
|
9378
|
+
).finally(() => {
|
|
9379
|
+
releasePromise = null;
|
|
9380
|
+
});
|
|
9381
|
+
return releasePromise;
|
|
9382
|
+
};
|
|
9383
|
+
const describeReleaseFailure = (error) => {
|
|
9384
|
+
const record = error;
|
|
9385
|
+
const cleanupPending = record?.cleanupPending === true || record?.code === "instabox_cleanup_pending";
|
|
9386
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
9387
|
+
return cleanupPending ? `\u4E14\u673A\u5668\u5220\u9664\u672A\u786E\u8BA4\uFF1Acleanup_pending\uFF08${detail}\uFF09\u2014\u2014\u4E91\u7AEF\u53EF\u80FD\u4ECD\u6709\u5B58\u6D3B\u673A\u5668\uFF0C\u4E0D\u5F97\u5F53\u4F5C\u5DF2\u6E05\u7406\uFF0C\u9700\u4EBA\u5DE5\u6838\u5BF9\u540E\u5220\u9664` : `\u4E14 release \u4E5F\u5931\u8D25\uFF08${detail}\uFF09`;
|
|
9388
|
+
};
|
|
9389
|
+
const execDirect = async (request) => {
|
|
9390
|
+
const result = await backend.execute(lease, request);
|
|
9391
|
+
const streams = result.output;
|
|
9392
|
+
const stdout = typeof streams?.stdout === "string" ? streams.stdout : "";
|
|
9393
|
+
const stderr = typeof streams?.stderr === "string" ? streams.stderr : "";
|
|
9394
|
+
if (result.ok === false) {
|
|
9395
|
+
throw new Error(`instabox \u5BB9\u5668\u5185\u6267\u884C\u5931\u8D25\uFF1A${stderr || `exit_code:${result.exitCode ?? "unknown"}`}`);
|
|
9396
|
+
}
|
|
9397
|
+
return stdout;
|
|
9398
|
+
};
|
|
9399
|
+
let bridge;
|
|
9400
|
+
try {
|
|
9401
|
+
bridge = await prepareFileBridge(execDirect, workspaceRoot, args.runId);
|
|
9402
|
+
} catch (error) {
|
|
9403
|
+
let cleanupNote = "\u672C\u6B21 lease \u5DF2\u91CA\u653E";
|
|
9404
|
+
try {
|
|
9405
|
+
await releaseBackend();
|
|
9406
|
+
} catch (releaseError) {
|
|
9407
|
+
cleanupNote = describeReleaseFailure(releaseError);
|
|
9408
|
+
}
|
|
9409
|
+
throw new LocalRuntimeKeyUnsupportedError(
|
|
9410
|
+
"instabox_bridge_bootstrap_failed",
|
|
9411
|
+
`runtimeKey \u6307\u5411 instabox\uFF0C\u4F46\u5BB9\u5668\u5185\u6587\u4EF6\u5DE5\u5177\u6865 bootstrap \u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}\uFF1B${cleanupNote}\u3002${instaboxFailureHint}`
|
|
9412
|
+
);
|
|
9413
|
+
}
|
|
9374
9414
|
const rawChannel = createExecutionChannel({
|
|
9375
9415
|
backend,
|
|
9376
9416
|
lease,
|
|
9377
|
-
timeoutMs: 10 * 60 * 1e3
|
|
9417
|
+
timeoutMs: 10 * 60 * 1e3,
|
|
9418
|
+
...bridge.ready && bridge.root && bridge.runtime ? {
|
|
9419
|
+
helper: {
|
|
9420
|
+
path: INSTABOX_HELPER_PATH,
|
|
9421
|
+
buildArgv: (toolName, toolArgs) => buildInstaboxToolArgv(toolName, toolArgs, {
|
|
9422
|
+
root: bridge.root,
|
|
9423
|
+
runtime: bridge.runtime
|
|
9424
|
+
})
|
|
9425
|
+
}
|
|
9426
|
+
} : {}
|
|
9378
9427
|
});
|
|
9379
|
-
let released = false;
|
|
9380
9428
|
const release = async () => {
|
|
9381
|
-
|
|
9382
|
-
released = true;
|
|
9383
|
-
try {
|
|
9384
|
-
await backend.release(lease, "completed");
|
|
9385
|
-
} catch {
|
|
9386
|
-
}
|
|
9429
|
+
await releaseBackend();
|
|
9387
9430
|
};
|
|
9388
9431
|
const channel = async (toolName, toolArgs, signal) => {
|
|
9389
|
-
if (
|
|
9432
|
+
if (releaseState !== "active") {
|
|
9390
9433
|
throw new Error(
|
|
9391
|
-
"instabox workload \u5DF2\u91CA\u653E\uFF1A\u672C run \u7684 lease \u5DF2\u5931\u6548\uFF0C\u62D2\u7EDD\u5728\u5BBF\u4E3B\u6267\u884C\u5DE5\u5177"
|
|
9434
|
+
releaseState === "cleanup_pending" ? "instabox workload cleanup_pending\uFF1A\u4E0A\u4E00\u6B21\u6E05\u7406\u672A\u786E\u8BA4\uFF0Clease \u72B6\u6001\u4E0D\u53EF\u4FE1\uFF0C\u62D2\u7EDD\u6267\u884C\u5DE5\u5177" : "instabox workload \u5DF2\u91CA\u653E\uFF1A\u672C run \u7684 lease \u5DF2\u5931\u6548\uFF0C\u62D2\u7EDD\u5728\u5BBF\u4E3B\u6267\u884C\u5DE5\u5177"
|
|
9392
9435
|
);
|
|
9393
9436
|
}
|
|
9394
9437
|
if (toolName === "execShell") {
|
|
9438
|
+
const command = typeof toolArgs.command === "string" ? toolArgs.command : void 0;
|
|
9439
|
+
if (bridge.root && command !== void 0) {
|
|
9440
|
+
return await rawChannel(EXECUTION_SHELL_TOOL, {
|
|
9441
|
+
...toolArgs,
|
|
9442
|
+
command: `cd ${posixQuote2(bridge.root)} && ${command}`
|
|
9443
|
+
}, signal);
|
|
9444
|
+
}
|
|
9395
9445
|
return await rawChannel(EXECUTION_SHELL_TOOL, toolArgs, signal);
|
|
9396
9446
|
}
|
|
9447
|
+
if (INSTABOX_FILE_TOOL_NAMES.includes(toolName)) {
|
|
9448
|
+
if (!bridge.ready) {
|
|
9449
|
+
throw new Error(describeInstaboxBridgeUnavailable(bridge));
|
|
9450
|
+
}
|
|
9451
|
+
const output = await rawChannel(toolName, toolArgs, signal);
|
|
9452
|
+
const parsed = parseToolOutput(output);
|
|
9453
|
+
if (!parsed.ok) {
|
|
9454
|
+
return JSON.stringify({ ok: false, error: parsed.error, workloadLocation: "instabox" });
|
|
9455
|
+
}
|
|
9456
|
+
const value = parsed.value;
|
|
9457
|
+
const payload = typeof value === "object" && value !== null ? { ok: true, ...value, value, workloadLocation: "instabox" } : { ok: true, value, workloadLocation: "instabox" };
|
|
9458
|
+
return JSON.stringify(payload);
|
|
9459
|
+
}
|
|
9397
9460
|
throw new Error(
|
|
9398
|
-
`instabox workload \u6682\
|
|
9461
|
+
`instabox workload \u6682\u4E0D\u652F\u6301\u5DE5\u5177 "${toolName}"\uFF08\u672C\u5757\u53EA\u6865\u63A5 readFile/writeFile/editFile/globFiles\uFF09\uFF1B\u62D2\u7EDD\u5728\u5BBF\u4E3B\u6267\u884C\u3002`
|
|
9399
9462
|
);
|
|
9400
9463
|
};
|
|
9401
9464
|
return {
|
|
9402
9465
|
backendId: LOCAL_INSTABOX_BACKEND_ID,
|
|
9403
9466
|
runId: args.runId,
|
|
9404
9467
|
channel,
|
|
9468
|
+
workspaceRoot: bridge.root,
|
|
9469
|
+
fileBridge: bridge,
|
|
9405
9470
|
release
|
|
9406
9471
|
};
|
|
9407
9472
|
}
|
|
@@ -9608,12 +9673,12 @@ function parseExecShellChannelOutput(raw) {
|
|
|
9608
9673
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9609
9674
|
return { stdout: text, exitCode: 0, ...isTruncated(text) ? { truncated: true } : {} };
|
|
9610
9675
|
}
|
|
9611
|
-
const
|
|
9612
|
-
const output =
|
|
9613
|
-
const stdout = firstString(output?.stdout,
|
|
9614
|
-
const truncated =
|
|
9615
|
-
const explicitFailure =
|
|
9616
|
-
const rawExit =
|
|
9676
|
+
const record = parsed;
|
|
9677
|
+
const output = record.output && typeof record.output === "object" ? record.output : void 0;
|
|
9678
|
+
const stdout = firstString(output?.stdout, record.stdout, record.output, record.content) ?? "";
|
|
9679
|
+
const truncated = record.truncated === true || output?.truncated === true || isTruncated(stdout) || isTruncated(firstString(output?.stderr, record.stderr) ?? "");
|
|
9680
|
+
const explicitFailure = record.ok === false || typeof record.error === "string";
|
|
9681
|
+
const rawExit = record.exitCode ?? record.exit_code;
|
|
9617
9682
|
const exitCode = typeof rawExit === "number" ? rawExit : explicitFailure ? 1 : 0;
|
|
9618
9683
|
if (explicitFailure && stdout.trim() === "") return { stdout: "", exitCode: exitCode === 0 ? 1 : exitCode, ...truncated ? { truncated: true } : {} };
|
|
9619
9684
|
return { stdout, exitCode, ...truncated ? { truncated: true } : {} };
|
|
@@ -9661,9 +9726,9 @@ async function exportRunDiffArtifact(args) {
|
|
|
9661
9726
|
return null;
|
|
9662
9727
|
}
|
|
9663
9728
|
if (args.writeAudit) {
|
|
9664
|
-
const
|
|
9729
|
+
const record = { runId: args.runId, kind: "diff", key, ref };
|
|
9665
9730
|
try {
|
|
9666
|
-
await args.writeAudit(
|
|
9731
|
+
await args.writeAudit(record);
|
|
9667
9732
|
} catch (error) {
|
|
9668
9733
|
warn(`run \u7EC8\u6001\u5BFC\u51FA\u5BA1\u8BA1\u5199\u5165\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD run \u7ED3\u679C\uFF09\uFF1A${describeError2(error)}`);
|
|
9669
9734
|
}
|
|
@@ -9740,8 +9805,8 @@ async function exportRunWorktreeDiffArtifacts(args) {
|
|
|
9740
9805
|
}
|
|
9741
9806
|
return summary;
|
|
9742
9807
|
}
|
|
9743
|
-
function serializeRunArtifactAudit(
|
|
9744
|
-
return `${JSON.stringify(
|
|
9808
|
+
function serializeRunArtifactAudit(record) {
|
|
9809
|
+
return `${JSON.stringify(record, null, 2)}
|
|
9745
9810
|
`;
|
|
9746
9811
|
}
|
|
9747
9812
|
|
|
@@ -10306,9 +10371,9 @@ async function writeLocalTokenRecord(args) {
|
|
|
10306
10371
|
function extractLastProviderInputTokens(input) {
|
|
10307
10372
|
if (input.usageRecords && input.usageRecords.length > 0) {
|
|
10308
10373
|
for (let i = input.usageRecords.length - 1; i >= 0; i--) {
|
|
10309
|
-
const
|
|
10310
|
-
if (!
|
|
10311
|
-
const normalized = normalizeUsage(
|
|
10374
|
+
const record = input.usageRecords[i];
|
|
10375
|
+
if (!record?.usage) continue;
|
|
10376
|
+
const normalized = normalizeUsage(record.usage);
|
|
10312
10377
|
if (normalized.input_tokens > 0) {
|
|
10313
10378
|
return normalized.input_tokens;
|
|
10314
10379
|
}
|
|
@@ -10491,21 +10556,21 @@ function resolveCliDialogRecordKey(userId, dialogId) {
|
|
|
10491
10556
|
}
|
|
10492
10557
|
async function loadCliDialogSummary(args) {
|
|
10493
10558
|
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10494
|
-
const
|
|
10495
|
-
if (!
|
|
10496
|
-
const summary = typeof
|
|
10559
|
+
const record = await args.store.read(dialogKey);
|
|
10560
|
+
if (!record || typeof record !== "object") return null;
|
|
10561
|
+
const summary = typeof record.summary === "string" ? record.summary.trim() : "";
|
|
10497
10562
|
if (!summary) return null;
|
|
10498
|
-
const summarizedBeforeId =
|
|
10499
|
-
const sourceHash =
|
|
10500
|
-
const sourceCount =
|
|
10501
|
-
const schemaVersion =
|
|
10563
|
+
const summarizedBeforeId = record.summarizedBeforeId;
|
|
10564
|
+
const sourceHash = record.sourceHash;
|
|
10565
|
+
const sourceCount = record.sourceCount;
|
|
10566
|
+
const schemaVersion = record.schemaVersion;
|
|
10502
10567
|
return {
|
|
10503
10568
|
summary,
|
|
10504
10569
|
...typeof summarizedBeforeId === "string" && summarizedBeforeId ? { summarizedBeforeId } : {},
|
|
10505
10570
|
...typeof sourceHash === "string" && sourceHash ? { sourceHash } : {},
|
|
10506
10571
|
...typeof sourceCount === "number" && sourceCount > 0 ? { sourceCount } : {},
|
|
10507
|
-
..."schemaVersion" in
|
|
10508
|
-
...Array.isArray(
|
|
10572
|
+
..."schemaVersion" in record ? { schemaVersion } : {},
|
|
10573
|
+
...Array.isArray(record.referenceKeys) ? { referenceKeys: record.referenceKeys.filter((key) => typeof key === "string") } : {}
|
|
10509
10574
|
};
|
|
10510
10575
|
}
|
|
10511
10576
|
async function saveCliDialogSummary(args) {
|
|
@@ -10534,9 +10599,9 @@ async function saveCliDialogSummary(args) {
|
|
|
10534
10599
|
}
|
|
10535
10600
|
async function loadCliDialogLastContextUsage(args) {
|
|
10536
10601
|
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10537
|
-
const
|
|
10538
|
-
if (!
|
|
10539
|
-
const lastInputTokens =
|
|
10602
|
+
const record = await args.store.read(dialogKey, { remote: false });
|
|
10603
|
+
if (!record || typeof record !== "object") return null;
|
|
10604
|
+
const lastInputTokens = record.lastInputTokens;
|
|
10540
10605
|
if (typeof lastInputTokens === "number" && Number.isFinite(lastInputTokens) && lastInputTokens > 0) {
|
|
10541
10606
|
return { inputTokens: lastInputTokens };
|
|
10542
10607
|
}
|
|
@@ -10553,6 +10618,36 @@ function parseTitleUpdatedAtMs(existingDialog) {
|
|
|
10553
10618
|
}
|
|
10554
10619
|
|
|
10555
10620
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
10621
|
+
var LOCAL_INSTABOX_TOOL_NAMES = [
|
|
10622
|
+
EXECUTION_SHELL_TOOL,
|
|
10623
|
+
...INSTABOX_FILE_TOOL_NAMES
|
|
10624
|
+
];
|
|
10625
|
+
function resolveLocalInstaboxToolRoute(args) {
|
|
10626
|
+
const toolName = normalizeLocalToolName(args.toolName);
|
|
10627
|
+
if (!LOCAL_INSTABOX_TOOL_NAMES.includes(toolName)) {
|
|
10628
|
+
return WORKSPACE_TOOL_NAMES.includes(toolName) ? {
|
|
10629
|
+
action: "reject",
|
|
10630
|
+
toolName,
|
|
10631
|
+
reason: `instabox workload \u4E0D\u652F\u6301\u5DE5\u4F5C\u533A\u5DE5\u5177 "${toolName}"\uFF08instabox \u5DE5\u5177\u9762\uFF1A${LOCAL_INSTABOX_TOOL_NAMES.join(", ")}\uFF09\uFF1B\u62D2\u7EDD\u56DE\u843D\u5230\u5BBF\u4E3B\u6267\u884C`
|
|
10632
|
+
} : { action: "passthrough", toolName };
|
|
10633
|
+
}
|
|
10634
|
+
const agentToolNames = (args.agentToolNames ?? []).map(
|
|
10635
|
+
normalizeLocalToolName
|
|
10636
|
+
);
|
|
10637
|
+
const deniedBySurfaceOrPolicy = !agentToolNames.includes(toolName) || !resolveLocalToolPolicy({
|
|
10638
|
+
env: args.env ?? {},
|
|
10639
|
+
agentToolNames,
|
|
10640
|
+
toolName
|
|
10641
|
+
}).allowed;
|
|
10642
|
+
if (deniedBySurfaceOrPolicy) {
|
|
10643
|
+
return {
|
|
10644
|
+
action: "reject",
|
|
10645
|
+
toolName,
|
|
10646
|
+
reason: `${toolName} is outside the run tool surface / policy \u2014 instabox workload \u4E0D\u662F\u7ED5\u8FC7 deny \u7684\u901A\u9053\uFF1B\u62D2\u7EDD\u5728\u5BBF\u4E3B\u6267\u884C\u5DE5\u4F5C\u533A\u5DE5\u5177`
|
|
10647
|
+
};
|
|
10648
|
+
}
|
|
10649
|
+
return { action: "intercept", toolName };
|
|
10650
|
+
}
|
|
10556
10651
|
var currentMetaFile = fileURLToPath(import.meta.url);
|
|
10557
10652
|
var isJsBundle = extname(currentMetaFile) === ".js";
|
|
10558
10653
|
var SOURCE_CLI_DIR = isJsBundle ? dirname4(currentMetaFile) : dirname4(dirname4(currentMetaFile));
|
|
@@ -10592,13 +10687,13 @@ async function recordLocalAvailabilityForAgent(args) {
|
|
|
10592
10687
|
);
|
|
10593
10688
|
return typeof entry?.nextAvailableAt === "number" ? entry.nextAvailableAt : action.nextAvailableAt;
|
|
10594
10689
|
}
|
|
10595
|
-
const
|
|
10596
|
-
if (action.kind === "clear" && !("nextAvailableAt" in
|
|
10597
|
-
const next = { ...
|
|
10690
|
+
const record = current;
|
|
10691
|
+
if (action.kind === "clear" && !("nextAvailableAt" in record)) return void 0;
|
|
10692
|
+
const next = { ...record };
|
|
10598
10693
|
let effectiveNextAvailableAt;
|
|
10599
10694
|
if (action.kind === "mark") {
|
|
10600
10695
|
const merged = mergeAvailabilityDeadline(
|
|
10601
|
-
|
|
10696
|
+
record.nextAvailableAt,
|
|
10602
10697
|
action.nextAvailableAt
|
|
10603
10698
|
);
|
|
10604
10699
|
next.nextAvailableAt = merged;
|
|
@@ -10640,13 +10735,13 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10640
10735
|
const additionalToolNames = deps.pastedTextStore ? ["readPastedText"] : [];
|
|
10641
10736
|
const resolveAgentCredentialGroup = async (agentRef) => {
|
|
10642
10737
|
try {
|
|
10643
|
-
const
|
|
10738
|
+
const record = await readAgentFromStore({
|
|
10644
10739
|
agentRef,
|
|
10645
10740
|
store: await getOrCreateSharedStore(deps),
|
|
10646
10741
|
userId
|
|
10647
10742
|
});
|
|
10648
|
-
if (!
|
|
10649
|
-
const rec =
|
|
10743
|
+
if (!record || typeof record !== "object") return void 0;
|
|
10744
|
+
const rec = record;
|
|
10650
10745
|
const existing = typeof rec.credentialGroup === "string" && rec.credentialGroup.trim() ? rec.credentialGroup.trim() : void 0;
|
|
10651
10746
|
if (existing) return existing;
|
|
10652
10747
|
const ref = typeof rec.apiKeyRef === "string" && rec.apiKeyRef.trim() ? rec.apiKeyRef : typeof rec.credentialRef === "string" && rec.credentialRef.trim() ? rec.credentialRef : void 0;
|
|
@@ -10660,13 +10755,13 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10660
10755
|
};
|
|
10661
10756
|
const resolveAgentDisplayName = async (agentRef) => {
|
|
10662
10757
|
try {
|
|
10663
|
-
const
|
|
10758
|
+
const record = await readAgentFromStore({
|
|
10664
10759
|
agentRef,
|
|
10665
10760
|
store: await getOrCreateSharedStore(deps),
|
|
10666
10761
|
userId
|
|
10667
10762
|
});
|
|
10668
|
-
if (!
|
|
10669
|
-
const name =
|
|
10763
|
+
if (!record || typeof record !== "object") return void 0;
|
|
10764
|
+
const name = record.name;
|
|
10670
10765
|
return typeof name === "string" && name.trim() ? name.trim() : void 0;
|
|
10671
10766
|
} catch {
|
|
10672
10767
|
return void 0;
|
|
@@ -10674,12 +10769,12 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10674
10769
|
};
|
|
10675
10770
|
const resolveAgentRuntimeBindingMachineId = async (agentRef) => {
|
|
10676
10771
|
try {
|
|
10677
|
-
const
|
|
10772
|
+
const record = await readAgentFromStore({
|
|
10678
10773
|
agentRef,
|
|
10679
10774
|
store: await getOrCreateSharedStore(deps),
|
|
10680
10775
|
userId
|
|
10681
10776
|
});
|
|
10682
|
-
const rec =
|
|
10777
|
+
const rec = record;
|
|
10683
10778
|
const binding = asRecordOrEmpty(rec?.runtimeBinding);
|
|
10684
10779
|
return asOptionalTrimmedString(binding.machineId);
|
|
10685
10780
|
} catch {
|
|
@@ -10723,16 +10818,24 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10723
10818
|
authenticatedCaller: resolveLocalUserId(deps.env),
|
|
10724
10819
|
agentKey: "cli-local-run",
|
|
10725
10820
|
env: deps.env,
|
|
10726
|
-
workspaceRoot
|
|
10821
|
+
workspaceRoot,
|
|
10822
|
+
...deps.dockerWorkspaceMode ? { workspaceMode: deps.dockerWorkspaceMode } : {}
|
|
10727
10823
|
}))();
|
|
10728
10824
|
return dockerWorkloadLoad;
|
|
10729
10825
|
};
|
|
10730
10826
|
const instaboxRuntimeEnabled = runtimeKey === "instabox";
|
|
10731
10827
|
let instaboxWorkloadLoad = null;
|
|
10732
10828
|
let instaboxWorkloadReleased = false;
|
|
10829
|
+
let instaboxReleasePending = false;
|
|
10830
|
+
let instaboxReleasePromise = null;
|
|
10733
10831
|
const createInstaboxWorkload = deps.createLocalInstaboxWorkload ?? createLocalInstaboxWorkload;
|
|
10734
10832
|
const loadLocalInstaboxWorkload = () => {
|
|
10735
10833
|
if (!instaboxRuntimeEnabled) return Promise.resolve(null);
|
|
10834
|
+
if (instaboxReleasePending) {
|
|
10835
|
+
return Promise.reject(
|
|
10836
|
+
new Error("instabox workload cleanup_pending\uFF1Alease cleanup \u5C1A\u672A\u786E\u8BA4\uFF0C\u62D2\u7EDD\u6267\u884C\u5DE5\u5177")
|
|
10837
|
+
);
|
|
10838
|
+
}
|
|
10736
10839
|
if (instaboxWorkloadReleased) {
|
|
10737
10840
|
return Promise.reject(
|
|
10738
10841
|
new Error(
|
|
@@ -10759,7 +10862,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10759
10862
|
const recordRunExecutionIsolation = async () => {
|
|
10760
10863
|
try {
|
|
10761
10864
|
const { writeFileSync: writeFileSync4, mkdirSync: mkdirSync4 } = await import("node:fs");
|
|
10762
|
-
const { resolveRunsDir } = await import("./agentRunControl-
|
|
10865
|
+
const { resolveRunsDir } = await import("./agentRunControl-XBSNHHZE.js");
|
|
10763
10866
|
const fact = resolveLocalRunExecutionIsolationFact({
|
|
10764
10867
|
// F1:显式点名宿主执行的 run 在审计里必须与 docker 沙盒区分开
|
|
10765
10868
|
// (reason: host-explicit-writes vs docker-workload)。
|
|
@@ -10791,7 +10894,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10791
10894
|
dockerWorkloadReleased = true;
|
|
10792
10895
|
dockerWorkloadLoad = null;
|
|
10793
10896
|
if (loaded) {
|
|
10794
|
-
const { resolveRunsDir } = await import("./agentRunControl-
|
|
10897
|
+
const { resolveRunsDir } = await import("./agentRunControl-XBSNHHZE.js");
|
|
10795
10898
|
const exportRunDiff = deps.exportDockerRunDiffArtifact ?? exportDockerRunDiffArtifact;
|
|
10796
10899
|
const warn = (message) => process.stderr.write(`[nolo] ${message}
|
|
10797
10900
|
`);
|
|
@@ -10814,13 +10917,34 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10814
10917
|
const loadLocalSandboxWorkload = () => localSandboxLoad ??= createSandboxWorkload({ workspaceRoot }).catch(
|
|
10815
10918
|
() => null
|
|
10816
10919
|
);
|
|
10817
|
-
const releaseLocalInstaboxWorkload =
|
|
10818
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10920
|
+
const releaseLocalInstaboxWorkload = () => {
|
|
10921
|
+
if (instaboxReleasePromise) return instaboxReleasePromise;
|
|
10922
|
+
const attempt = (async () => {
|
|
10923
|
+
const loaded = instaboxWorkloadLoad ? await instaboxWorkloadLoad.catch(() => null) : null;
|
|
10924
|
+
if (!loaded) {
|
|
10925
|
+
instaboxWorkloadReleased = true;
|
|
10926
|
+
instaboxWorkloadLoad = null;
|
|
10927
|
+
return;
|
|
10928
|
+
}
|
|
10929
|
+
try {
|
|
10930
|
+
await loaded.release();
|
|
10931
|
+
instaboxWorkloadReleased = true;
|
|
10932
|
+
instaboxReleasePending = false;
|
|
10933
|
+
instaboxWorkloadLoad = null;
|
|
10934
|
+
} catch (error) {
|
|
10935
|
+
instaboxReleasePending = true;
|
|
10936
|
+
const record = error;
|
|
10937
|
+
const code = record?.code === "instabox_cleanup_pending" || record?.cleanupPending === true ? "cleanup_pending" : "release_failed";
|
|
10938
|
+
process.stderr.write(`[nolo] instabox_release_${code}
|
|
10939
|
+
`);
|
|
10940
|
+
throw error;
|
|
10941
|
+
}
|
|
10942
|
+
})();
|
|
10943
|
+
instaboxReleasePromise = attempt;
|
|
10944
|
+
void attempt.finally(() => {
|
|
10945
|
+
if (instaboxReleasePromise === attempt) instaboxReleasePromise = null;
|
|
10946
|
+
}).catch(() => void 0);
|
|
10947
|
+
return attempt;
|
|
10824
10948
|
};
|
|
10825
10949
|
const releaseLocalSandboxWorkload = async () => {
|
|
10826
10950
|
await releaseLocalDockerWorkload();
|
|
@@ -11297,18 +11421,30 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11297
11421
|
}
|
|
11298
11422
|
}
|
|
11299
11423
|
if (instaboxRuntimeEnabled) {
|
|
11300
|
-
const
|
|
11301
|
-
|
|
11302
|
-
|
|
11424
|
+
const instaboxRoute = resolveLocalInstaboxToolRoute({
|
|
11425
|
+
toolName: call.name,
|
|
11426
|
+
env: deps.env,
|
|
11427
|
+
agentToolNames: activeAgentToolNames
|
|
11428
|
+
});
|
|
11429
|
+
if (instaboxRoute.action === "reject") {
|
|
11430
|
+
throw new Error(instaboxRoute.reason);
|
|
11431
|
+
}
|
|
11432
|
+
if (instaboxRoute.action === "intercept") {
|
|
11433
|
+
const instaboxHandle = await loadLocalInstaboxWorkload();
|
|
11434
|
+
if (!instaboxHandle) {
|
|
11435
|
+
throw new Error(
|
|
11436
|
+
`instabox workload \u4E0D\u53EF\u7528\uFF08\u65E0 handle\uFF09\uFF1A\u62D2\u7EDD\u5728\u5BBF\u4E3B\u6267\u884C\u5DE5\u4F5C\u533A\u5DE5\u5177 "${instaboxRoute.toolName}"`
|
|
11437
|
+
);
|
|
11438
|
+
}
|
|
11303
11439
|
const instaboxArgs = parseToolArgumentsObject(injectedCall.arguments) ?? {};
|
|
11304
11440
|
const instaboxOutput = await instaboxHandle.channel(
|
|
11305
|
-
|
|
11441
|
+
instaboxRoute.toolName,
|
|
11306
11442
|
instaboxArgs,
|
|
11307
11443
|
opts?.abortSignal
|
|
11308
11444
|
);
|
|
11309
11445
|
if (typeof instaboxOutput !== "string") {
|
|
11310
11446
|
throw new Error(
|
|
11311
|
-
`instabox workload \u672A\u8FD4\u56DE\u7ED3\u679C\uFF08tool=${
|
|
11447
|
+
`instabox workload \u672A\u8FD4\u56DE\u7ED3\u679C\uFF08tool=${instaboxRoute.toolName}\uFF09\uFF1A\u62D2\u7EDD\u56DE\u843D\u5230\u5BBF\u4E3B\u6267\u884C`
|
|
11312
11448
|
);
|
|
11313
11449
|
}
|
|
11314
11450
|
return { content: instaboxOutput };
|
|
@@ -11506,6 +11642,7 @@ export {
|
|
|
11506
11642
|
loadCliDialogSummary,
|
|
11507
11643
|
saveCliDialogSummary,
|
|
11508
11644
|
loadCliDialogLastContextUsage,
|
|
11645
|
+
resolveLocalInstaboxToolRoute,
|
|
11509
11646
|
recordLocalAvailabilityForAgent,
|
|
11510
11647
|
setCliAutoCompactionSummaryFallback,
|
|
11511
11648
|
getCliAutoCompactionSummaryFallback,
|