nolo-cli 0.16.0 → 0.17.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-AVCA2NAV.js → _executeModel-WPNX5DH4.js} +49 -43
- package/{action-F5JACQBG.js → action-LT7BRFLK.js} +10 -9
- package/{addContentAction-AQXEYRBE.js → addContentAction-PL3KKBDH.js} +9 -8
- package/{addDialogAgentAction-EJHHJZWW.js → addDialogAgentAction-FCMSKYAF.js} +8 -7
- package/{agentDeleteCommand-QW5PUMDQ.js → agentDeleteCommand-L3357EFL.js} +31 -28
- package/{agentEmailCommands-4ORVLGVQ.js → agentEmailCommands-N65AVLEI.js} +61 -55
- package/{agentListCommands-YWBYRTYC.js → agentListCommands-CH27FTI2.js} +30 -27
- package/{agentMachineCommands-JSQW4FOA.js → agentMachineCommands-PPK5HJZB.js} +29 -26
- package/{agentPullCommand-6HWUT3SW.js → agentPullCommand-ZZGU5KOY.js} +4 -4
- package/{agentRecordCommands-AASIWOBT.js → agentRecordCommands-HTVXD4TT.js} +56 -50
- package/{agentRunCommand-TB5BHXUH.js → agentRunCommand-MGLVJUA5.js} +62 -53
- package/{agentRunControl-6ADXVYMR.js → agentRunControl-P75VPTGS.js} +24 -1
- package/{agentRuntimeLocal-QNPNJRVH.js → agentRuntimeLocal-QUTBSY3I.js} +24 -21
- package/{agentSlice-RUNXC62Y.js → agentSlice-DOGRCMWK.js} +9 -8
- package/appDeleteCommands-FEEVXUBG.js +127 -0
- package/appDeployCommands-C4HCGC4B.js +166 -0
- package/appDeployStatusCommands-IR5ZUZBQ.js +147 -0
- package/appGetCommands-6RJGZ66Z.js +122 -0
- package/appListCommands-VMTF5YZF.js +125 -0
- package/{authCommand-YFTR3347.js → authCommand-WJZPOLSS.js} +16 -9
- package/{authCommands-YXGOXNBZ.js → authCommands-XTBV7OFZ.js} +6 -5
- package/{chunk-XPC5C7BK.js → chunk-3ND52WIL.js} +2 -2
- package/{chunk-SOTZ6RDN.js → chunk-3Q7WHGCB.js} +1 -1
- package/{chunk-M43KDE25.js → chunk-45BY7RLP.js} +2 -8
- package/{chunk-KKY4B2Q2.js → chunk-4PWB7JRR.js} +4 -1
- package/{chunk-6N4KODMN.js → chunk-4T5F7YZQ.js} +1 -1
- package/chunk-7BUYEZ6U.js +671 -0
- package/{chunk-AS3ZQ3O2.js → chunk-7OBMZCRD.js} +1 -1
- package/{chunk-AVVZUXXC.js → chunk-AAODAAUQ.js} +34 -13
- package/{chunk-QLUFR47U.js → chunk-AL2V7U3E.js} +1 -1
- package/{chunk-MTU75CZ2.js → chunk-B5TOXZAK.js} +1 -1
- package/{chunk-AUURUT6L.js → chunk-BT6K76S7.js} +238 -424
- package/chunk-CEFXYF66.js +107 -0
- package/{chunk-RLCXU7A5.js → chunk-D3HVJJIA.js} +1 -1
- package/{chunk-JTMNCCWF.js → chunk-DKZFOK24.js} +16 -87
- package/chunk-DL6EPNIK.js +50 -0
- package/{chunk-4L2OJPCU.js → chunk-EGPCU42M.js} +58 -8
- package/{chunk-IWLUTMYX.js → chunk-ELT65PZW.js} +2 -2
- package/chunk-FKXFCYVO.js +221 -0
- package/{chunk-4FX6NVDW.js → chunk-FPKLD4KB.js} +3 -136
- package/{chunk-PCTUYVUM.js → chunk-FVIPEIVX.js} +10 -3
- package/chunk-GFUIQ4RY.js +136 -0
- package/{chunk-66X4VSRC.js → chunk-HQPG2PIV.js} +41 -1
- package/{chunk-IGXREZW2.js → chunk-HV2A3B4W.js} +1 -1
- package/{chunk-LPEUV5RE.js → chunk-IOOMJJ4Z.js} +2 -2
- package/{setDialogExtraReferencesAction-LR6MSIXO.js → chunk-JLA4FXYC.js} +2 -17
- package/{chunk-3OIRVWXA.js → chunk-JP7REMYP.js} +10 -1
- package/chunk-KFEVY3ST.js +255 -0
- package/{chunk-P3RIAYGG.js → chunk-L2MLZQXU.js} +3 -3
- package/{chunk-55NSNCFM.js → chunk-L6NVTGI7.js} +1 -1
- package/{chunk-3WGLLTK4.js → chunk-LSFAWXKC.js} +100 -3
- package/{chunk-S2LXHNHG.js → chunk-MD3V54DA.js} +6 -6
- package/{chunk-6EVITP2G.js → chunk-MUCU6ATG.js} +2 -251
- package/{chunk-KFHN5NGJ.js → chunk-MVQ4TBSD.js} +1 -1
- package/{chunk-ZQBL7LIC.js → chunk-NEKFSXOP.js} +310 -211
- package/{chunk-NSCHQQPU.js → chunk-NVB267BZ.js} +397 -324
- package/{chunk-Z5JQNBNY.js → chunk-NYUXSXLY.js} +33 -14
- package/{chunk-FRV6A633.js → chunk-PZCBZO4J.js} +2 -2
- package/{chunk-GSINCD4P.js → chunk-QCJITMYO.js} +21 -11
- package/{chunk-OOSFSFMA.js → chunk-R5V5G73M.js} +2 -0
- package/{chunk-4IJYA27C.js → chunk-RG2U2MTJ.js} +1 -1
- package/{chunk-BEBNFWDU.js → chunk-RRGVDPH3.js} +3 -3
- package/{chunk-EABWT43X.js → chunk-RVOUXDFU.js} +5 -5
- package/{chunk-JTINRTBT.js → chunk-SKDNBYZK.js} +2 -2
- package/{chunk-3663CXZN.js → chunk-SNZV4QCE.js} +65 -22
- package/{chunk-KMQPSTMJ.js → chunk-TRT4I4UD.js} +2 -2
- package/{chunk-MYMMNKYL.js → chunk-TSIYZBTH.js} +156 -6
- package/{chunk-EHLHSX7R.js → chunk-UB4RYYNQ.js} +9 -2
- package/{chunk-YJKXGHJ6.js → chunk-UGUW3FHG.js} +4 -4
- package/{chunk-DPAB4FQ7.js → chunk-UZY4BEBR.js} +1579 -212
- package/chunk-V5R4NZP2.js +78 -0
- package/{chunk-MR6ISAGB.js → chunk-VDNQF5VI.js} +6 -6
- package/{chunk-33BJUVK4.js → chunk-VGMJ6PDJ.js} +5 -5
- package/{chunk-W4NVOSFF.js → chunk-WFHXMLHZ.js} +1 -1
- package/{chunk-H33743XH.js → chunk-WJRJDX2W.js} +1 -1
- package/chunk-X4Q4UZEY.js +26 -0
- package/{chunk-RPDGJO4D.js → chunk-XHG22OEX.js} +4 -4
- package/{chunk-DVRHHFEA.js → chunk-XMLRJUU5.js} +1 -1
- package/{chunk-3S2VOMIF.js → chunk-XRZJGPFI.js} +7 -7
- package/{chunk-7UKFVQ5W.js → chunk-YLRTBX4Y.js} +105 -36
- package/{chunk-DGEYDWEZ.js → chunk-YXTRNO5W.js} +3 -3
- package/{chunk-FY233ZFU.js → chunk-ZJZCMKOR.js} +107 -177
- package/{chunk-NVEWUJVX.js → chunk-ZVOZH2HW.js} +1 -1
- package/chunk-ZZ2MH7LE.js +84 -0
- package/{cliExecutor-K3F7DMRO.js → cliExecutor-DNE7TCC4.js} +2 -2
- package/codingSkills-36KN5NQT.js +48 -0
- package/{createAgentAutomationAction-FNHPSKKO.js → createAgentAutomationAction-PMOLEPGJ.js} +19 -18
- package/{createDialogAction-TZCVQ3NU.js → createDialogAction-DPRTYNAK.js} +21 -20
- package/{createPageAction-EIGZ3BKT.js → createPageAction-JGZK3WAM.js} +25 -24
- package/{dbSlice-7KQH6GOU.js → dbSlice-CGSRFJN3.js} +8 -7
- package/{deleteFile-WPWVZE4B.js → deleteFile-WDZ3VM7B.js} +3 -3
- package/{dialogCommands-FO77J5DQ.js → dialogCommands-XED6DKLV.js} +29 -26
- package/{dialogSlice-MM5U4KE2.js → dialogSlice-KO4NRNKC.js} +19 -18
- package/{docCreateCommands-I3BS3AZI.js → docCreateCommands-P6DYWHH3.js} +32 -27
- package/{docDeleteCommands-Q2OPV52P.js → docDeleteCommands-KUWXAMSN.js} +31 -26
- package/{docReadCommands-YOOFACYZ.js → docReadCommands-ECW55TKB.js} +30 -25
- package/{docStore-NGYQ2JTR.js → docStore-6KMERNUY.js} +20 -19
- package/{docUpdateCommands-2B32ITHN.js → docUpdateCommands-5J4BTJQN.js} +31 -26
- package/{fetchMessages-KTNM7QAR.js → fetchMessages-BMGVZVSE.js} +4 -3
- package/{getPricing-P4XRJRZB.js → getPricing-RYY6OBA4.js} +2 -2
- package/{handleSendMessageAction-JRZWWBKP.js → handleSendMessageAction-R3ZHTVU4.js} +20 -19
- package/index.js +95 -64
- package/{localDialogRead-2VRI24F4.js → localDialogRead-HQZPVIE3.js} +1 -1
- package/{localRuntimeDb-LGDF6FQP.js → localRuntimeDb-THJZGAOJ.js} +1 -1
- package/{machineCommands-WRWF2ICZ.js → machineCommands-JF2YL34J.js} +62 -56
- package/{machineWsRunDispatch-ZX7Q3TWZ.js → machineWsRunDispatch-ON4AEOJL.js} +54 -48
- package/{models-WQ5N4OJM.js → models-5K5G2CZI.js} +1 -1
- package/package.json +1 -1
- package/queryRunOverlay-O4LOMMPO.js +161 -0
- package/{read-CN3TNXIP.js → read-3FMPZPER.js} +3 -3
- package/{readDocTool-WF3675ED.js → readDocTool-VSYHKK3V.js} +1 -1
- package/{readlineWorkspace-ZTGRGW46.js → readlineWorkspace-SUCINTL7.js} +354 -185
- package/{removeDialogAgentAction-YDHBFEGI.js → removeDialogAgentAction-OAGA2G3U.js} +10 -9
- package/{runAgentClientLoop-JZCOP7LG.js → runAgentClientLoop-OBD2AVEL.js} +43 -37
- package/runOverlayPresentation-ZO4VCWEU.js +11 -0
- package/{runtimeDoctorCommands-THIHX2SY.js → runtimeDoctorCommands-E2OUORHK.js} +6 -6
- package/setDialogExtraReferencesAction-JZEXA5SL.js +27 -0
- package/{setPrimaryDialogAgentAction-IIVDCY5C.js → setPrimaryDialogAgentAction-4ZUQQKDG.js} +26 -17
- package/{settingSlice-O23YDK2O.js → settingSlice-7MNKHZ6R.js} +9 -8
- package/{skillDiscovery-6M2BZUFN.js → skillDiscovery-KJWT7JBU.js} +3 -3
- package/{spaceCommands-VV4GTPQK.js → spaceCommands-32NTNLHS.js} +30 -27
- package/{spaceSlice-DRWWZJP7.js → spaceSlice-P7VOXLY6.js} +19 -18
- package/{streamAgentChatTurn-Y6WGATQR.js → streamAgentChatTurn-UHEMNI3X.js} +97 -56
- package/{tableCommands-3P7MJ3PF.js → tableCommands-BEQAGE4I.js} +1 -1
- package/{tools-PUNBY3AH.js → tools-BMXIXHMB.js} +32 -27
- package/{tuiSummaryLlmCaller-F64WLSAF.js → tuiSummaryLlmCaller-VUNVBRX3.js} +5 -4
- package/types-ZSTJ7MPR.js +7 -0
- package/{updateDialogTitleAction-YSR4TCMB.js → updateDialogTitleAction-LJBDYZLH.js} +22 -21
- package/{chunk-O4BU24WZ.js → chunk-6Y7A3OQQ.js} +3 -3
- package/{chunk-XBS2WYJ2.js → chunk-RK5NYQEL.js} +0 -0
- package/{chunk-CMKUBIGW.js → chunk-X7W4TNB4.js} +3 -3
- package/{localRuntimeAuthority-TEGCOWX4.js → localRuntimeAuthority-4IXJCHZ7.js} +3 -3
|
@@ -3,12 +3,11 @@ import {
|
|
|
3
3
|
refreshAntigravityOAuthToken,
|
|
4
4
|
refreshOpenAiCodexToken,
|
|
5
5
|
refreshXaiOAuthToken
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-UB4RYYNQ.js";
|
|
7
7
|
import {
|
|
8
8
|
buildLocalAgentLookupKeys,
|
|
9
|
-
normalizeAgentHandle,
|
|
10
9
|
shouldReadAgentKeyRemotely
|
|
11
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-45BY7RLP.js";
|
|
12
11
|
import {
|
|
13
12
|
LOCAL_CODEX_AGENT_ID,
|
|
14
13
|
LOCAL_CODEX_AGENT_KEY,
|
|
@@ -17,17 +16,17 @@ import {
|
|
|
17
16
|
} from "./chunk-VHBWHNVT.js";
|
|
18
17
|
import {
|
|
19
18
|
inferCaptureIntent
|
|
20
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-MVQ4TBSD.js";
|
|
21
20
|
import {
|
|
22
21
|
inlineImageUrlsForCustomProvider,
|
|
23
22
|
prepareTools
|
|
24
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-PZCBZO4J.js";
|
|
25
24
|
import {
|
|
26
25
|
getAntigravityUserAgent,
|
|
27
26
|
isAntigravityOAuthAgent,
|
|
28
27
|
readAntigravityProjectId,
|
|
29
28
|
resolveAntigravityCloudCodeBaseUrl
|
|
30
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-L6NVTGI7.js";
|
|
31
30
|
import {
|
|
32
31
|
FORCED_TOOLS,
|
|
33
32
|
addDefaultLightWebToolsForConfiguredAgents,
|
|
@@ -36,19 +35,13 @@ import {
|
|
|
36
35
|
applyDisabledTools,
|
|
37
36
|
applySystemBuiltinSkillFilter,
|
|
38
37
|
expandEnabledPacks,
|
|
39
|
-
formatListRunsCard,
|
|
40
|
-
formatNotFoundRunCard,
|
|
41
|
-
formatStartRunCard,
|
|
42
|
-
formatStatusRunCard,
|
|
43
|
-
formatStopRunCard,
|
|
44
38
|
readXPostFunc,
|
|
45
39
|
readXPostFunctionSchema,
|
|
46
40
|
readXhsProfileFunc,
|
|
47
41
|
readXhsProfileFunctionSchema,
|
|
48
42
|
rememberMemoryFunctionSchema,
|
|
49
|
-
resolveEffectiveEnabledPacks
|
|
50
|
-
|
|
51
|
-
} from "./chunk-ZQBL7LIC.js";
|
|
43
|
+
resolveEffectiveEnabledPacks
|
|
44
|
+
} from "./chunk-NEKFSXOP.js";
|
|
52
45
|
import {
|
|
53
46
|
createDrainExhaustedResponse,
|
|
54
47
|
isCoreDrainingBody,
|
|
@@ -58,15 +51,18 @@ import {
|
|
|
58
51
|
import {
|
|
59
52
|
normalizeDialogTitle
|
|
60
53
|
} from "./chunk-OWOHNGCN.js";
|
|
54
|
+
import {
|
|
55
|
+
getDefaultCliLocalRuntimeDb
|
|
56
|
+
} from "./chunk-WJRJDX2W.js";
|
|
61
57
|
import {
|
|
62
58
|
prepareTokenUsageData
|
|
63
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-NVB267BZ.js";
|
|
64
60
|
import {
|
|
65
61
|
BUILTIN_TITLE_LLM_CONFIG
|
|
66
62
|
} from "./chunk-XOIF2TNF.js";
|
|
67
63
|
import {
|
|
68
64
|
fetchServerSyncedCredential
|
|
69
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-MD3V54DA.js";
|
|
70
66
|
import {
|
|
71
67
|
buildAgentRuntimeDialogWritePlan,
|
|
72
68
|
buildLocalWorkspaceOpenAiTools,
|
|
@@ -77,9 +73,10 @@ import {
|
|
|
77
73
|
executeLocalToolWithPolicy,
|
|
78
74
|
executeOpenAiCompatibleChatCompletion,
|
|
79
75
|
parseSseDataLineJson,
|
|
76
|
+
parseSseDataLineObject,
|
|
80
77
|
readOpenAiCompatibleSseCompletion,
|
|
81
78
|
resolveOpenAiCompatibleProviderConfig
|
|
82
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-YLRTBX4Y.js";
|
|
83
80
|
import {
|
|
84
81
|
buildPlatformChatCompletionRequest,
|
|
85
82
|
canUsePlatformChatProvider,
|
|
@@ -88,25 +85,27 @@ import {
|
|
|
88
85
|
readSseDataValues,
|
|
89
86
|
resolvePlatformChatProviderConfig,
|
|
90
87
|
shouldUsePlatformChatProvider
|
|
91
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-AAODAAUQ.js";
|
|
92
89
|
import {
|
|
93
90
|
resolveAgentRuntimeConfigFromRecord
|
|
94
91
|
} from "./chunk-OIQPORYI.js";
|
|
95
92
|
import {
|
|
96
|
-
parseToolArgumentsJson,
|
|
97
93
|
summarizeToolArguments
|
|
98
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-QCJITMYO.js";
|
|
95
|
+
import {
|
|
96
|
+
convertMessagesToResponsesInput,
|
|
97
|
+
toResponsesTools
|
|
98
|
+
} from "./chunk-KFEVY3ST.js";
|
|
99
99
|
import {
|
|
100
100
|
resolvePlatformAuthToken
|
|
101
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-MUCU6ATG.js";
|
|
102
102
|
import {
|
|
103
103
|
buildLoadSkillExecutor,
|
|
104
104
|
buildNoloWorkspaceCliToolExecutors,
|
|
105
105
|
buildNoloWorkspaceOpenAiTools,
|
|
106
|
-
canonicalizeToolNames,
|
|
107
106
|
parseNoloWorkspaceToolArguments,
|
|
108
107
|
resolveRuntimeToolSurfaceForAgent
|
|
109
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-DKZFOK24.js";
|
|
110
109
|
import {
|
|
111
110
|
clipCompactText
|
|
112
111
|
} from "./chunk-5MMAK75Q.js";
|
|
@@ -122,6 +121,15 @@ import {
|
|
|
122
121
|
readOAuthCredential,
|
|
123
122
|
resolveFreshAccessToken
|
|
124
123
|
} from "./chunk-JZPBVBIY.js";
|
|
124
|
+
import {
|
|
125
|
+
isAdaptiveThinkingModelId
|
|
126
|
+
} from "./chunk-HQPG2PIV.js";
|
|
127
|
+
import {
|
|
128
|
+
toErrorMessage
|
|
129
|
+
} from "./chunk-HNMXYYJR.js";
|
|
130
|
+
import {
|
|
131
|
+
canonicalizeToolNames
|
|
132
|
+
} from "./chunk-ZZ2MH7LE.js";
|
|
125
133
|
import {
|
|
126
134
|
compactWhitespace
|
|
127
135
|
} from "./chunk-DWLEOOGR.js";
|
|
@@ -129,22 +137,29 @@ import {
|
|
|
129
137
|
checkStaleRun,
|
|
130
138
|
finalizeRunRecord,
|
|
131
139
|
findRunRecord,
|
|
132
|
-
|
|
140
|
+
gcRunRecords,
|
|
141
|
+
queryRunRecords,
|
|
133
142
|
spawnLocalBackgroundRun
|
|
134
|
-
} from "./chunk-
|
|
143
|
+
} from "./chunk-TSIYZBTH.js";
|
|
144
|
+
import {
|
|
145
|
+
TASK_PREVIEW_MAX,
|
|
146
|
+
formatListRunsCard,
|
|
147
|
+
formatNotFoundRunCard,
|
|
148
|
+
formatStartRunCard,
|
|
149
|
+
formatStatusRunCard,
|
|
150
|
+
formatStopRunCard,
|
|
151
|
+
isAgentNameFallback,
|
|
152
|
+
isAgentRunTerminalStatus,
|
|
153
|
+
resolveRunLabel,
|
|
154
|
+
shortRunId
|
|
155
|
+
} from "./chunk-FKXFCYVO.js";
|
|
135
156
|
import {
|
|
136
157
|
CliProviderQuotaError,
|
|
137
158
|
executeCli
|
|
138
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-X7W4TNB4.js";
|
|
139
160
|
import {
|
|
140
161
|
buildCliPrompt
|
|
141
162
|
} from "./chunk-ATNTHIZI.js";
|
|
142
|
-
import {
|
|
143
|
-
toErrorMessage
|
|
144
|
-
} from "./chunk-HNMXYYJR.js";
|
|
145
|
-
import {
|
|
146
|
-
getDefaultCliLocalRuntimeDb
|
|
147
|
-
} from "./chunk-H33743XH.js";
|
|
148
163
|
import {
|
|
149
164
|
isCompiledBinary,
|
|
150
165
|
parseUserIdFromAuthToken
|
|
@@ -152,27 +167,27 @@ import {
|
|
|
152
167
|
import {
|
|
153
168
|
DEFAULT_NOLO_SERVER_URL
|
|
154
169
|
} from "./chunk-OLZBQWZU.js";
|
|
155
|
-
import {
|
|
156
|
-
asRecordOrEmpty
|
|
157
|
-
} from "./chunk-KX6YBIHG.js";
|
|
158
170
|
import {
|
|
159
171
|
createTokenKey,
|
|
160
172
|
createUserKey,
|
|
161
173
|
dialogMessageRange
|
|
162
|
-
} from "./chunk-
|
|
174
|
+
} from "./chunk-6Y7A3OQQ.js";
|
|
175
|
+
import {
|
|
176
|
+
asOptionalFiniteNumber
|
|
177
|
+
} from "./chunk-WWC7I6TA.js";
|
|
163
178
|
import {
|
|
164
179
|
asTrimmedNonEmptyStringArray
|
|
165
180
|
} from "./chunk-I42VC5KR.js";
|
|
166
181
|
import {
|
|
167
|
-
|
|
168
|
-
} from "./chunk-
|
|
182
|
+
asTrimmedLowercaseString
|
|
183
|
+
} from "./chunk-QSJ3HFEF.js";
|
|
169
184
|
import {
|
|
170
185
|
BUILTIN_NOLO_AGENT_KEY,
|
|
171
186
|
PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
|
|
172
187
|
PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
|
|
173
188
|
PUBLIC_GLM_52_AGENT_KEY,
|
|
174
189
|
PUBLIC_KIMI_K26_IMAGE_AGENT_KEY
|
|
175
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-3ND52WIL.js";
|
|
176
191
|
import {
|
|
177
192
|
asTrimmedString
|
|
178
193
|
} from "./chunk-3EUW3WEO.js";
|
|
@@ -294,6 +309,10 @@ var STRINGS = {
|
|
|
294
309
|
en: "Agent switch cancelled.",
|
|
295
310
|
zh: "\u5DF2\u53D6\u6D88\u5207\u6362 agent\u3002"
|
|
296
311
|
},
|
|
312
|
+
agentPickerLoading: {
|
|
313
|
+
en: "Loading agents\u2026",
|
|
314
|
+
zh: "\u6B63\u5728\u52A0\u8F7D agent \u5217\u8868\u2026"
|
|
315
|
+
},
|
|
297
316
|
historyPickerTitle: {
|
|
298
317
|
en: "Resume dialog (\u2191\u2193 Enter Esc)",
|
|
299
318
|
zh: "\u6062\u590D\u5BF9\u8BDD\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
|
|
@@ -458,6 +477,10 @@ var STRINGS = {
|
|
|
458
477
|
en: "Run stopped",
|
|
459
478
|
zh: "\u8FD0\u884C\u5DF2\u505C\u6B62"
|
|
460
479
|
},
|
|
480
|
+
runFinishedLabel: {
|
|
481
|
+
en: "Run finished",
|
|
482
|
+
zh: "\u8FD0\u884C\u5DF2\u7ED3\u675F"
|
|
483
|
+
},
|
|
461
484
|
runLogTailLabel: {
|
|
462
485
|
en: "Log tail:",
|
|
463
486
|
zh: "\u65E5\u5FD7\u5C3E\u90E8\uFF1A"
|
|
@@ -492,6 +515,10 @@ var STRINGS = {
|
|
|
492
515
|
en: "selected",
|
|
493
516
|
zh: "\u5DF2\u9009"
|
|
494
517
|
},
|
|
518
|
+
dialogMultiSelectRequired: {
|
|
519
|
+
en: "Pick at least one option to submit",
|
|
520
|
+
zh: "\u81F3\u5C11\u9009\u62E9\u4E00\u9879\u624D\u80FD\u63D0\u4EA4"
|
|
521
|
+
},
|
|
495
522
|
dialogConfirmHint: {
|
|
496
523
|
en: "(\u2191\u2193 move \xB7 Enter choose \xB7 Esc cancel)",
|
|
497
524
|
zh: "\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
|
|
@@ -532,7 +559,7 @@ var STRINGS = {
|
|
|
532
559
|
en: "abort the operation",
|
|
533
560
|
zh: "\u4E2D\u6B62\u64CD\u4F5C"
|
|
534
561
|
},
|
|
535
|
-
// --- Ask choice (
|
|
562
|
+
// --- Ask choice (ask_user) ------------------------------------------
|
|
536
563
|
askChoiceTitle: {
|
|
537
564
|
en: "question",
|
|
538
565
|
zh: "\u95EE\u9898"
|
|
@@ -613,10 +640,6 @@ var STRINGS = {
|
|
|
613
640
|
en: "tools",
|
|
614
641
|
zh: "\u5DE5\u5177"
|
|
615
642
|
},
|
|
616
|
-
contextFieldThinking: {
|
|
617
|
-
en: "thinking",
|
|
618
|
-
zh: "\u601D\u8003"
|
|
619
|
-
},
|
|
620
643
|
contextFieldServer: {
|
|
621
644
|
en: "server",
|
|
622
645
|
zh: "\u670D\u52A1\u7AEF"
|
|
@@ -654,7 +677,6 @@ var STRINGS = {
|
|
|
654
677
|
" /context Show workspace context and next actions",
|
|
655
678
|
" /runtime <mode> Use auto, local, or server runtime",
|
|
656
679
|
" /tools <mode> Control tool trace: hide, compact, verbose",
|
|
657
|
-
" /thinking <mode> Control thinking output: hide, marker, show",
|
|
658
680
|
" /switch Pick an agent interactively (\u2191\u2193, Enter)",
|
|
659
681
|
" /switch list List agents as text",
|
|
660
682
|
" /switch <name> Switch directly by name, alias, or key (alias: /agent)",
|
|
@@ -691,7 +713,6 @@ var STRINGS = {
|
|
|
691
713
|
" /context \u67E5\u770B\u5DE5\u4F5C\u533A\u4E0A\u4E0B\u6587\u4E0E\u540E\u7EED\u64CD\u4F5C",
|
|
692
714
|
" /runtime <mode> \u5207\u6362 runtime\uFF1Aauto\u3001local\u3001server",
|
|
693
715
|
" /tools <mode> \u5DE5\u5177\u8F68\u8FF9\u663E\u793A\uFF1Ahide\u3001compact\u3001verbose",
|
|
694
|
-
" /thinking <mode> \u601D\u8003\u8FC7\u7A0B\u663E\u793A\uFF1Ahide\u3001marker\u3001show",
|
|
695
716
|
" /switch \u4EA4\u4E92\u5F0F\u9009\u62E9 agent\uFF08\u2191\u2193 \u79FB\u52A8\uFF0CEnter \u786E\u8BA4\uFF09",
|
|
696
717
|
" /switch list \u4EE5\u6587\u672C\u5217\u51FA\u5168\u90E8 agent",
|
|
697
718
|
" /switch <name> \u6309\u540D\u79F0\u3001\u522B\u540D\u6216 key \u76F4\u63A5\u5207\u6362\uFF08\u522B\u540D\uFF1A/agent\uFF09",
|
|
@@ -736,12 +757,6 @@ var STRINGS = {
|
|
|
736
757
|
},
|
|
737
758
|
toolsUsage: { en: "Usage: /tools <hide|compact|verbose>", zh: "\u7528\u6CD5\uFF1A/tools <hide|compact|verbose>" },
|
|
738
759
|
toolsSet: { en: "Tool display: {0}", zh: "\u5DE5\u5177\u663E\u793A\uFF1A{0}" },
|
|
739
|
-
thinkingCurrent: {
|
|
740
|
-
en: "Thinking display: {0} (hide | marker | show)",
|
|
741
|
-
zh: "\u601D\u8003\u663E\u793A\uFF1A{0}\uFF08hide | marker | show\uFF09"
|
|
742
|
-
},
|
|
743
|
-
thinkingUsage: { en: "Usage: /thinking <hide|marker|show>", zh: "\u7528\u6CD5\uFF1A/thinking <hide|marker|show>" },
|
|
744
|
-
thinkingSet: { en: "Thinking display: {0}", zh: "\u601D\u8003\u663E\u793A\uFF1A{0}" },
|
|
745
760
|
tasksRunning: { en: "Running processes ({0}):", zh: "\u8FD0\u884C\u4E2D\u7684\u8FDB\u7A0B\uFF08{0}\uFF09\uFF1A" },
|
|
746
761
|
tasksStopped: { en: "Stopped/exited ({0}):", zh: "\u5DF2\u505C\u6B62/\u5DF2\u9000\u51FA\uFF08{0}\uFF09\uFF1A" },
|
|
747
762
|
tasksNone: { en: "No processes.", zh: "\u6CA1\u6709\u8FD0\u884C\u4E2D\u7684\u8FDB\u7A0B\u3002" },
|
|
@@ -935,11 +950,191 @@ function agentRunCardLabels() {
|
|
|
935
950
|
runStatus: t("runStatusLabel"),
|
|
936
951
|
runStarted: t("runStartedLabel"),
|
|
937
952
|
runStopped: t("runStoppedLabel"),
|
|
953
|
+
runFinished: t("runFinishedLabel"),
|
|
938
954
|
logTail: t("runLogTailLabel"),
|
|
939
955
|
runs: (count) => t("runsListLabel", String(count))
|
|
940
956
|
};
|
|
941
957
|
}
|
|
942
958
|
|
|
959
|
+
// packages/ai/tools/agent/quotaCircuitBreaker.ts
|
|
960
|
+
var QUOTA_ERROR_PATTERNS = [
|
|
961
|
+
/429/,
|
|
962
|
+
/quota/i,
|
|
963
|
+
/rate\s*limit/i,
|
|
964
|
+
/too\s*many\s*requests/i,
|
|
965
|
+
/额度/,
|
|
966
|
+
/上限/,
|
|
967
|
+
/用尽/,
|
|
968
|
+
/CliProviderQuotaError/i
|
|
969
|
+
];
|
|
970
|
+
var AGENT_NOT_FOUND_PATTERNS = [
|
|
971
|
+
/agent[^\n]{0,80}not\s+found/i,
|
|
972
|
+
/agent[^\n]{0,80}not\s+exist/i,
|
|
973
|
+
/agent[^\n]{0,80}不存在/i,
|
|
974
|
+
/agent[^\n]{0,80}未找到/i,
|
|
975
|
+
/AGENT_NOT_FOUND/
|
|
976
|
+
];
|
|
977
|
+
var AUTH_ERROR_PATTERNS = [
|
|
978
|
+
/401/,
|
|
979
|
+
/403/,
|
|
980
|
+
/unauthori[sz]ed/i,
|
|
981
|
+
/authentication\s+failed/i,
|
|
982
|
+
/invalid\s+(api[-\s]?key|token|credential)/i,
|
|
983
|
+
/api[-\s]?key\s+(invalid|missing|not\s+found)/i,
|
|
984
|
+
/token\s*(invalid|expired|失效|过期)/i,
|
|
985
|
+
/未授权/,
|
|
986
|
+
/认证失败/,
|
|
987
|
+
/凭证/
|
|
988
|
+
];
|
|
989
|
+
var NETWORK_ERROR_PATTERNS = [
|
|
990
|
+
/ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EHOSTUNREACH|EPIPE/i,
|
|
991
|
+
/getaddrinfo|DNS\s+(error|fail)/i,
|
|
992
|
+
/fetch\s+failed/i,
|
|
993
|
+
/network\s+(error|unreachable|down|disconnected)/i,
|
|
994
|
+
/socket\s+(hang|closed|error)/i,
|
|
995
|
+
/连接失败/,
|
|
996
|
+
/网络错误|网络异常|无法连接/
|
|
997
|
+
];
|
|
998
|
+
function findActiveBreaker(now, table, target) {
|
|
999
|
+
if (!Number.isFinite(now)) return void 0;
|
|
1000
|
+
for (const entry of table) {
|
|
1001
|
+
if (entry.target !== target) continue;
|
|
1002
|
+
if (typeof entry.until === "number" && entry.until > now) return entry;
|
|
1003
|
+
}
|
|
1004
|
+
return void 0;
|
|
1005
|
+
}
|
|
1006
|
+
function isCliProviderQuotaErrorShape(error) {
|
|
1007
|
+
if (!error || typeof error !== "object") return false;
|
|
1008
|
+
const e = error;
|
|
1009
|
+
return e.name === "CliProviderQuotaError" || typeof e.message === "string" && e.message.startsWith("[QUOTA_LIMITED:");
|
|
1010
|
+
}
|
|
1011
|
+
function isQuotaExhaustedError(error) {
|
|
1012
|
+
if (!error) return false;
|
|
1013
|
+
if (isCliProviderQuotaErrorShape(error)) return true;
|
|
1014
|
+
if (error instanceof Error) {
|
|
1015
|
+
return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error.message));
|
|
1016
|
+
}
|
|
1017
|
+
if (typeof error === "string") {
|
|
1018
|
+
return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error));
|
|
1019
|
+
}
|
|
1020
|
+
const maybeStatus = error.status;
|
|
1021
|
+
if (typeof maybeStatus === "number" && maybeStatus === 429) return true;
|
|
1022
|
+
const maybeStatusCode = error.statusCode;
|
|
1023
|
+
if (typeof maybeStatusCode === "number" && maybeStatusCode === 429) return true;
|
|
1024
|
+
return false;
|
|
1025
|
+
}
|
|
1026
|
+
function isAgentNotFoundError(error) {
|
|
1027
|
+
if (!error) return false;
|
|
1028
|
+
const e = error;
|
|
1029
|
+
if (e.code === "AGENT_NOT_FOUND") return true;
|
|
1030
|
+
const message = typeof e.message === "string" ? e.message : typeof error === "string" ? error : "";
|
|
1031
|
+
if (AGENT_NOT_FOUND_PATTERNS.some((pattern) => pattern.test(message))) return true;
|
|
1032
|
+
if ((e.status === 404 || e.statusCode === 404) && /agent|不存在|未找到/i.test(message)) {
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
1035
|
+
return false;
|
|
1036
|
+
}
|
|
1037
|
+
function extractMessage(error) {
|
|
1038
|
+
if (typeof error === "string") return error;
|
|
1039
|
+
if (error instanceof Error) return error.message;
|
|
1040
|
+
if (error && typeof error === "object") {
|
|
1041
|
+
const m = error.message;
|
|
1042
|
+
return typeof m === "string" ? m : "";
|
|
1043
|
+
}
|
|
1044
|
+
return "";
|
|
1045
|
+
}
|
|
1046
|
+
function extractStatus(error) {
|
|
1047
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1048
|
+
const e = error;
|
|
1049
|
+
const s = typeof e.status === "number" ? e.status : void 0;
|
|
1050
|
+
const sc = typeof e.statusCode === "number" ? e.statusCode : void 0;
|
|
1051
|
+
return s ?? sc;
|
|
1052
|
+
}
|
|
1053
|
+
function parseResetsInMs(text) {
|
|
1054
|
+
if (!text) return void 0;
|
|
1055
|
+
const unitMs = (n, unit) => {
|
|
1056
|
+
if (/^d/.test(unit)) return n * 24 * 3600 * 1e3;
|
|
1057
|
+
if (/^h/.test(unit)) return n * 3600 * 1e3;
|
|
1058
|
+
if (/^m/.test(unit)) return n * 60 * 1e3;
|
|
1059
|
+
if (/^s/.test(unit)) return n * 1e3;
|
|
1060
|
+
return NaN;
|
|
1061
|
+
};
|
|
1062
|
+
const re = /(\d+)\s*(d(?:ay|ays)?|h(?:r|rs|our|ours)?|m(?:in|ins|inute|inutes)?|s(?:ec|ecs|econd|econds)?)/gi;
|
|
1063
|
+
let totalMs = 0;
|
|
1064
|
+
let matched = false;
|
|
1065
|
+
let m;
|
|
1066
|
+
while ((m = re.exec(text)) !== null) {
|
|
1067
|
+
const ms = unitMs(Number(m[1]), m[2]);
|
|
1068
|
+
if (!Number.isFinite(ms)) continue;
|
|
1069
|
+
totalMs += ms;
|
|
1070
|
+
matched = true;
|
|
1071
|
+
}
|
|
1072
|
+
return matched ? totalMs : void 0;
|
|
1073
|
+
}
|
|
1074
|
+
function extractProvider(error) {
|
|
1075
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1076
|
+
const p = error.provider;
|
|
1077
|
+
if (typeof p === "string" && p.length > 0) return p;
|
|
1078
|
+
const message = extractMessage(error);
|
|
1079
|
+
const tag = /\[QUOTA_LIMITED:([^\]]+)\]/i.exec(message);
|
|
1080
|
+
if (tag?.[1]) return tag[1];
|
|
1081
|
+
return void 0;
|
|
1082
|
+
}
|
|
1083
|
+
function extractRetryAfterHeader(error) {
|
|
1084
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1085
|
+
const headers = error.headers;
|
|
1086
|
+
if (!headers || typeof headers !== "object") return void 0;
|
|
1087
|
+
const raw = headers["retry-after"];
|
|
1088
|
+
if (typeof raw !== "string" && typeof raw !== "number") return void 0;
|
|
1089
|
+
const secs = Number(raw);
|
|
1090
|
+
return Number.isFinite(secs) && secs > 0 ? secs * 1e3 : void 0;
|
|
1091
|
+
}
|
|
1092
|
+
function classifyRunFailure(error) {
|
|
1093
|
+
const message = extractMessage(error);
|
|
1094
|
+
const status = extractStatus(error);
|
|
1095
|
+
const retryAfterMs = extractRetryAfterHeader(error) ?? parseResetsInMs(message);
|
|
1096
|
+
if (isQuotaExhaustedError(error)) {
|
|
1097
|
+
return {
|
|
1098
|
+
reason: "quota",
|
|
1099
|
+
provider: extractProvider(error),
|
|
1100
|
+
// 纯函数不取时钟:resetsAt 由调用方用 now + retryAfterMs 计算后补齐
|
|
1101
|
+
retryAfterMs,
|
|
1102
|
+
message
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
if (isAgentNotFoundError(error)) {
|
|
1106
|
+
return { reason: "agent-not-found", message };
|
|
1107
|
+
}
|
|
1108
|
+
if (isAuthError(error)) {
|
|
1109
|
+
return { reason: "auth", message };
|
|
1110
|
+
}
|
|
1111
|
+
if (isNetworkError(error)) {
|
|
1112
|
+
return { reason: "network", message };
|
|
1113
|
+
}
|
|
1114
|
+
return { reason: "other", message };
|
|
1115
|
+
}
|
|
1116
|
+
function isAuthError(error) {
|
|
1117
|
+
const message = extractMessage(error);
|
|
1118
|
+
const status = extractStatus(error);
|
|
1119
|
+
if (status === 401 || status === 403) return true;
|
|
1120
|
+
return AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
1121
|
+
}
|
|
1122
|
+
function isNetworkError(error) {
|
|
1123
|
+
const message = extractMessage(error);
|
|
1124
|
+
return NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
1125
|
+
}
|
|
1126
|
+
var DEFAULT_QUOTA_BREAKER_MS = 6 * 3600 * 1e3;
|
|
1127
|
+
var DEFAULT_AGENT_NOT_FOUND_BREAKER_MS = 15 * 60 * 1e3;
|
|
1128
|
+
function buildBreakerEntry(now, target, kind, retryAfterMs) {
|
|
1129
|
+
const ttl = kind === "quota" ? typeof retryAfterMs === "number" && retryAfterMs > 0 ? retryAfterMs : DEFAULT_QUOTA_BREAKER_MS : DEFAULT_AGENT_NOT_FOUND_BREAKER_MS;
|
|
1130
|
+
return {
|
|
1131
|
+
target,
|
|
1132
|
+
kind,
|
|
1133
|
+
until: now + ttl,
|
|
1134
|
+
...kind === "quota" && typeof retryAfterMs === "number" ? { resetsAt: now + retryAfterMs } : {}
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
943
1138
|
// packages/cli/client/localRuntimeDiagnostics.ts
|
|
944
1139
|
import { ulid } from "ulid";
|
|
945
1140
|
var preparedAgentRuntimeCache = /* @__PURE__ */ new Map();
|
|
@@ -979,7 +1174,7 @@ function summarizeOpenAiToolNames(tools) {
|
|
|
979
1174
|
}
|
|
980
1175
|
|
|
981
1176
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
982
|
-
import { dirname, extname, join } from "node:path";
|
|
1177
|
+
import { dirname as dirname2, extname, join as join2 } from "node:path";
|
|
983
1178
|
import { fileURLToPath } from "node:url";
|
|
984
1179
|
|
|
985
1180
|
// packages/core/summarizeEndpoint.ts
|
|
@@ -1130,6 +1325,11 @@ async function fetchWithTransientRetry(fetchImpl, input, init, options = {}) {
|
|
|
1130
1325
|
const attemptBudget = coreDraining ? coreDrainingMaxAttempts : maxAttempts;
|
|
1131
1326
|
if (attempt < attemptBudget) {
|
|
1132
1327
|
const delayMs = await resolveRetryAfterMs(response, attempt);
|
|
1328
|
+
options.onRetry?.({
|
|
1329
|
+
attempt: attempt + 1,
|
|
1330
|
+
maxAttempts: attemptBudget,
|
|
1331
|
+
delayMs
|
|
1332
|
+
});
|
|
1133
1333
|
await (options.sleep ?? defaultSleep)(delayMs);
|
|
1134
1334
|
continue;
|
|
1135
1335
|
}
|
|
@@ -1143,7 +1343,13 @@ async function fetchWithTransientRetry(fetchImpl, input, init, options = {}) {
|
|
|
1143
1343
|
if (!isTransientFetchError(error)) throw error;
|
|
1144
1344
|
lastError = error;
|
|
1145
1345
|
if (attempt < maxAttempts) {
|
|
1146
|
-
|
|
1346
|
+
const delayMs = transientFetchRetryDelayMs(attempt);
|
|
1347
|
+
options.onRetry?.({
|
|
1348
|
+
attempt: attempt + 1,
|
|
1349
|
+
maxAttempts,
|
|
1350
|
+
delayMs
|
|
1351
|
+
});
|
|
1352
|
+
await (options.sleep ?? defaultSleep)(delayMs);
|
|
1147
1353
|
}
|
|
1148
1354
|
}
|
|
1149
1355
|
}
|
|
@@ -1590,23 +1796,6 @@ async function readAgentFromStore(args) {
|
|
|
1590
1796
|
if (!record || typeof record !== "object") continue;
|
|
1591
1797
|
return resolveAgentRuntimeConfigFromRecord(key, record);
|
|
1592
1798
|
}
|
|
1593
|
-
const normalizedRef = normalizeAgentHandle(args.agentRef);
|
|
1594
|
-
if (!normalizedRef) {
|
|
1595
|
-
return resolveBuiltinPlatformAgentConfig(args.agentRef);
|
|
1596
|
-
}
|
|
1597
|
-
try {
|
|
1598
|
-
const iterator = args.store.iterator({
|
|
1599
|
-
gte: "agent-",
|
|
1600
|
-
lte: "agent-\uFFFF"
|
|
1601
|
-
});
|
|
1602
|
-
for await (const [key, record] of iterator) {
|
|
1603
|
-
if (!record || typeof record !== "object") continue;
|
|
1604
|
-
const handle = normalizeAgentHandle(record.handle);
|
|
1605
|
-
if (handle !== normalizedRef) continue;
|
|
1606
|
-
return resolveAgentRuntimeConfigFromRecord(key, record);
|
|
1607
|
-
}
|
|
1608
|
-
} catch {
|
|
1609
|
-
}
|
|
1610
1799
|
return resolveBuiltinPlatformAgentConfig(args.agentRef);
|
|
1611
1800
|
}
|
|
1612
1801
|
async function readDialogMessages(args) {
|
|
@@ -1765,7 +1954,10 @@ var LOCAL_SERVER_WEB_TOOL_NAMES = ["fetchWebpage", "exa_search"];
|
|
|
1765
1954
|
var LOCAL_SERVER_WEB_TOOL_NAME_SET = new Set(
|
|
1766
1955
|
LOCAL_SERVER_WEB_TOOL_NAMES
|
|
1767
1956
|
);
|
|
1768
|
-
var LOCAL_SERVER_MEMORY_TOOL_NAMES = [
|
|
1957
|
+
var LOCAL_SERVER_MEMORY_TOOL_NAMES = [
|
|
1958
|
+
"queryMemory",
|
|
1959
|
+
"rememberMemory"
|
|
1960
|
+
];
|
|
1769
1961
|
var LOCAL_SERVER_MEMORY_TOOL_NAME_SET = new Set(
|
|
1770
1962
|
LOCAL_SERVER_MEMORY_TOOL_NAMES
|
|
1771
1963
|
);
|
|
@@ -1997,6 +2189,25 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
1997
2189
|
}
|
|
1998
2190
|
])
|
|
1999
2191
|
);
|
|
2192
|
+
const queryMemory = async (call) => {
|
|
2193
|
+
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
2194
|
+
const query = typeof parsed.query === "string" ? parsed.query.trim() : "";
|
|
2195
|
+
if (!query) {
|
|
2196
|
+
return {
|
|
2197
|
+
content: JSON.stringify({ error: "queryMemory \u9700\u8981\u975E\u7A7A query\u3002" }),
|
|
2198
|
+
metadata: { serverPlatformTool: true, memoryRead: false }
|
|
2199
|
+
};
|
|
2200
|
+
}
|
|
2201
|
+
const body = { userInput: query };
|
|
2202
|
+
if (args.agentKey) body.agentKey = args.agentKey;
|
|
2203
|
+
const raw = await postServer("/api/memory/query", body, {
|
|
2204
|
+
retryTransient: true
|
|
2205
|
+
});
|
|
2206
|
+
return {
|
|
2207
|
+
content: raw,
|
|
2208
|
+
metadata: { serverPlatformTool: true, memoryRead: true }
|
|
2209
|
+
};
|
|
2210
|
+
};
|
|
2000
2211
|
const rememberMemory = async (call) => {
|
|
2001
2212
|
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
2002
2213
|
const content = typeof parsed.content === "string" ? parsed.content.trim() : "";
|
|
@@ -2023,11 +2234,368 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
2023
2234
|
metadata: { serverPlatformTool: true, memoryWrite: true }
|
|
2024
2235
|
};
|
|
2025
2236
|
};
|
|
2026
|
-
return { ...tableExecutors, ...webExecutors, rememberMemory };
|
|
2237
|
+
return { ...tableExecutors, ...webExecutors, queryMemory, rememberMemory };
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
// packages/cli/client/cliAgentRunToolExecutors.ts
|
|
2241
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
2242
|
+
|
|
2243
|
+
// packages/cli/client/agentRunSnapshot.ts
|
|
2244
|
+
function readString(value) {
|
|
2245
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2246
|
+
}
|
|
2247
|
+
function readLogLines(parsed) {
|
|
2248
|
+
if (Array.isArray(parsed.logLines)) return parsed.logLines;
|
|
2249
|
+
const tail = readString(parsed.logTail);
|
|
2250
|
+
return tail ? tail.split("\n") : void 0;
|
|
2251
|
+
}
|
|
2252
|
+
function readTimestamp(value) {
|
|
2253
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
|
|
2254
|
+
if (typeof value === "string" && value.trim()) {
|
|
2255
|
+
const parsed = Date.parse(value);
|
|
2256
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
2257
|
+
}
|
|
2258
|
+
return void 0;
|
|
2259
|
+
}
|
|
2260
|
+
function readToolNames(value) {
|
|
2261
|
+
if (!Array.isArray(value)) return void 0;
|
|
2262
|
+
const names = value.filter((n) => typeof n === "string" && Boolean(n.trim()));
|
|
2263
|
+
return names.length > 0 ? names : void 0;
|
|
2264
|
+
}
|
|
2265
|
+
function buildSnapshot(parsed, event) {
|
|
2266
|
+
const runId = readString(parsed.runId) ?? readString(event.metadata?.runId) ?? "";
|
|
2267
|
+
const label = resolveRunLabel({
|
|
2268
|
+
agentName: parsed.agentName,
|
|
2269
|
+
name: parsed.name,
|
|
2270
|
+
agentKey: parsed.agentKey
|
|
2271
|
+
});
|
|
2272
|
+
const logLines = readLogLines(parsed);
|
|
2273
|
+
const taskPreview = readString(parsed.taskPreview);
|
|
2274
|
+
const lastToolNames = readToolNames(parsed.lastToolNames);
|
|
2275
|
+
const lastAssistantText = readString(parsed.lastAssistantText);
|
|
2276
|
+
const errorMessage = readString(parsed.errorMessage);
|
|
2277
|
+
const startedAt = readTimestamp(parsed.startedAt);
|
|
2278
|
+
const finishedAt = readTimestamp(parsed.finishedAt) ?? readTimestamp(parsed.endedAt);
|
|
2279
|
+
return {
|
|
2280
|
+
runId,
|
|
2281
|
+
status: readString(parsed.status) ?? "running",
|
|
2282
|
+
// The literal `agent` fallback is dropped here rather than at each render
|
|
2283
|
+
// site: an unnamed run should render no name row, not the word "agent".
|
|
2284
|
+
...isAgentNameFallback(label) ? {} : { agentName: label },
|
|
2285
|
+
...taskPreview ? { taskPreview } : {},
|
|
2286
|
+
...typeof parsed.toolCallCount === "number" && Number.isFinite(parsed.toolCallCount) ? { toolCallCount: parsed.toolCallCount } : {},
|
|
2287
|
+
...lastToolNames ? { lastToolNames } : {},
|
|
2288
|
+
...lastAssistantText ? { lastAssistantText } : {},
|
|
2289
|
+
...errorMessage ? { errorMessage } : {},
|
|
2290
|
+
...startedAt !== void 0 ? { startedAt } : {},
|
|
2291
|
+
...finishedAt !== void 0 ? { finishedAt } : {},
|
|
2292
|
+
...logLines ? { logLines } : {},
|
|
2293
|
+
logKey: logLines && logLines.length > 0 ? logLines.join("\n") : ""
|
|
2294
|
+
};
|
|
2295
|
+
}
|
|
2296
|
+
var STOP_STATUSES = /* @__PURE__ */ new Set(["killed", "cancelled", "cancelling"]);
|
|
2297
|
+
function parseAgentRunEvent(event) {
|
|
2298
|
+
if (event.type !== "tool-result") return null;
|
|
2299
|
+
if (event.toolName !== "startAgentRun" && event.toolName !== "controlAgentRun") {
|
|
2300
|
+
return null;
|
|
2301
|
+
}
|
|
2302
|
+
const raw = typeof event.content === "string" ? event.content.trim() : "";
|
|
2303
|
+
if (!raw.startsWith("{")) return null;
|
|
2304
|
+
let parsed;
|
|
2305
|
+
try {
|
|
2306
|
+
parsed = JSON.parse(raw);
|
|
2307
|
+
} catch {
|
|
2308
|
+
return null;
|
|
2309
|
+
}
|
|
2310
|
+
if (Array.isArray(parsed.runs)) return null;
|
|
2311
|
+
const snapshot = buildSnapshot(parsed, event);
|
|
2312
|
+
const status = readString(parsed.status);
|
|
2313
|
+
if (event.toolName === "startAgentRun") {
|
|
2314
|
+
if (!snapshot.runId) return null;
|
|
2315
|
+
return { kind: "start", snapshot };
|
|
2316
|
+
}
|
|
2317
|
+
if (parsed.found === false || status === "not_found") {
|
|
2318
|
+
return { kind: "gone", snapshot: { ...snapshot, status: "not_found" } };
|
|
2319
|
+
}
|
|
2320
|
+
if (status && STOP_STATUSES.has(status)) {
|
|
2321
|
+
return { kind: "stop", snapshot };
|
|
2322
|
+
}
|
|
2323
|
+
if (!status) return null;
|
|
2324
|
+
if (!snapshot.runId) return null;
|
|
2325
|
+
return { kind: "status", snapshot };
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
// packages/ai/tools/agent/batchAggregation.ts
|
|
2329
|
+
var DEFAULT_BATCH_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
2330
|
+
var MAX_ERROR_SUMMARY_CHARS = 120;
|
|
2331
|
+
var MAX_FAILURE_LINES = 10;
|
|
2332
|
+
function isFailureStatus(status) {
|
|
2333
|
+
return isAgentRunTerminalStatus(status) && status !== "done";
|
|
2334
|
+
}
|
|
2335
|
+
function isOrphanedStatus(status) {
|
|
2336
|
+
return status === "orphaned";
|
|
2337
|
+
}
|
|
2338
|
+
function toEpochMs(iso) {
|
|
2339
|
+
if (!iso) return void 0;
|
|
2340
|
+
const ms = Date.parse(iso);
|
|
2341
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
2342
|
+
}
|
|
2343
|
+
function isOverTimeout(run, nowMs, timeoutMs) {
|
|
2344
|
+
const startedMs = toEpochMs(run.startedAt);
|
|
2345
|
+
if (startedMs === void 0) return false;
|
|
2346
|
+
return nowMs - startedMs >= timeoutMs;
|
|
2347
|
+
}
|
|
2348
|
+
function truncateErrorSummary(text, max = MAX_ERROR_SUMMARY_CHARS) {
|
|
2349
|
+
if (!text) return "";
|
|
2350
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
2351
|
+
if (collapsed.length <= max) return collapsed;
|
|
2352
|
+
return `${collapsed.slice(0, max - 1)}\u2026`;
|
|
2353
|
+
}
|
|
2354
|
+
function formatFailureLine(run) {
|
|
2355
|
+
const label = shortRunId(run.runId);
|
|
2356
|
+
const agent = run.agentName ? ` (${run.agentName})` : "";
|
|
2357
|
+
const error = truncateErrorSummary(run.errorSummary);
|
|
2358
|
+
return error ? `\u5931\u8D25: ${label}${agent} \u2014 ${error}` : `\u5931\u8D25: ${label}${agent}`;
|
|
2359
|
+
}
|
|
2360
|
+
function formatBatchSummary(batchId, counts, runs, reason) {
|
|
2361
|
+
const failures = runs.filter((r) => isFailureStatus(r.status));
|
|
2362
|
+
const unfinished = runs.filter((r) => !isAgentRunTerminalStatus(r.status));
|
|
2363
|
+
if (reason === "timeout") {
|
|
2364
|
+
const lines2 = [
|
|
2365
|
+
`\u6279\u6B21 ${batchId}: \u8D85\u65F6\u672A\u6536\u655B \u2014 ${counts.running} \u4E2A\u672A\u5B8C\u6210`
|
|
2366
|
+
];
|
|
2367
|
+
for (const run of unfinished.slice(0, MAX_FAILURE_LINES)) {
|
|
2368
|
+
const agent = run.agentName ? ` (${run.agentName})` : "";
|
|
2369
|
+
lines2.push(`\u672A\u5B8C\u6210: ${shortRunId(run.runId)}${agent}`);
|
|
2370
|
+
}
|
|
2371
|
+
const rest2 = unfinished.length - MAX_FAILURE_LINES;
|
|
2372
|
+
if (rest2 > 0) lines2.push(`\u2026 \u53CA\u53E6\u5916 ${rest2} \u4E2A\u672A\u5B8C\u6210`);
|
|
2373
|
+
return lines2.join("\n");
|
|
2374
|
+
}
|
|
2375
|
+
const tail = counts.running > 0 ? `, ${counts.running} \u4ECD\u5728\u8DD1` : "";
|
|
2376
|
+
const lines = [
|
|
2377
|
+
`\u6279\u6B21 ${batchId}: ${counts.success + counts.failed}/${counts.total} \u5B8C\u6210 \u2014 ${counts.success} \u6210\u529F, ${counts.failed} \u5931\u8D25${tail}`
|
|
2378
|
+
];
|
|
2379
|
+
for (const run of failures.slice(0, MAX_FAILURE_LINES)) {
|
|
2380
|
+
lines.push(formatFailureLine(run));
|
|
2381
|
+
}
|
|
2382
|
+
const rest = failures.length - MAX_FAILURE_LINES;
|
|
2383
|
+
if (rest > 0) lines.push(`\u2026 \u53CA\u53E6\u5916 ${rest} \u4E2A\u5931\u8D25`);
|
|
2384
|
+
return lines.join("\n");
|
|
2385
|
+
}
|
|
2386
|
+
function aggregateBatch(input) {
|
|
2387
|
+
const { batchId, runs, now } = input;
|
|
2388
|
+
const timeoutMs = input.timeoutMs ?? DEFAULT_BATCH_TIMEOUT_MS;
|
|
2389
|
+
const notified = new Set(input.notifiedReasons ?? []);
|
|
2390
|
+
const nowMs = toEpochMs(now) ?? 0;
|
|
2391
|
+
let success = 0;
|
|
2392
|
+
let failed = 0;
|
|
2393
|
+
let orphaned = 0;
|
|
2394
|
+
let running = 0;
|
|
2395
|
+
const unfinished = [];
|
|
2396
|
+
let timedOut = false;
|
|
2397
|
+
for (const run of runs) {
|
|
2398
|
+
if (isAgentRunTerminalStatus(run.status)) {
|
|
2399
|
+
if (run.status === "done") success += 1;
|
|
2400
|
+
else {
|
|
2401
|
+
failed += 1;
|
|
2402
|
+
if (isOrphanedStatus(run.status)) orphaned += 1;
|
|
2403
|
+
}
|
|
2404
|
+
} else {
|
|
2405
|
+
running += 1;
|
|
2406
|
+
unfinished.push(run.runId);
|
|
2407
|
+
if (isOverTimeout(run, nowMs, timeoutMs)) timedOut = true;
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
const converged = running === 0;
|
|
2411
|
+
let newWakeReasons = [];
|
|
2412
|
+
if (failed > 0 && !notified.has("failure")) {
|
|
2413
|
+
newWakeReasons = ["failure"];
|
|
2414
|
+
} else if (converged && !notified.has("converged")) {
|
|
2415
|
+
newWakeReasons = ["converged"];
|
|
2416
|
+
} else if (timedOut && !notified.has("timeout")) {
|
|
2417
|
+
newWakeReasons = ["timeout"];
|
|
2418
|
+
}
|
|
2419
|
+
const counts = {
|
|
2420
|
+
total: runs.length,
|
|
2421
|
+
success,
|
|
2422
|
+
failed,
|
|
2423
|
+
orphaned,
|
|
2424
|
+
running
|
|
2425
|
+
};
|
|
2426
|
+
const summary = newWakeReasons.length > 0 ? formatBatchSummary(batchId, counts, runs, newWakeReasons[0]) : "";
|
|
2427
|
+
return {
|
|
2428
|
+
batchId,
|
|
2429
|
+
converged,
|
|
2430
|
+
timedOut,
|
|
2431
|
+
counts,
|
|
2432
|
+
newWakeReasons,
|
|
2433
|
+
unfinished,
|
|
2434
|
+
summary
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
// packages/ai/tools/agent/runtimeTodo.ts
|
|
2439
|
+
var TODO_REVIEW_BLOCK = "BLOCK";
|
|
2440
|
+
function deriveTodoStatus(input) {
|
|
2441
|
+
const { todo, runs } = input;
|
|
2442
|
+
if (todo.status === "abandoned") {
|
|
2443
|
+
return { status: "abandoned" };
|
|
2444
|
+
}
|
|
2445
|
+
if (runs.length === 0) {
|
|
2446
|
+
return { status: todo.status };
|
|
2447
|
+
}
|
|
2448
|
+
if (runs.some((r) => !isAgentRunTerminalStatus(r.status))) {
|
|
2449
|
+
return { status: "running", latestRun: latestRun(runs) };
|
|
2450
|
+
}
|
|
2451
|
+
const latest = latestRun(runs);
|
|
2452
|
+
if (latest?.reviewVerdict === TODO_REVIEW_BLOCK) {
|
|
2453
|
+
return {
|
|
2454
|
+
status: "blocked",
|
|
2455
|
+
latestRun: latest,
|
|
2456
|
+
blockedReason: clipSummary(latest.reviewReason, MAX_ERROR_SUMMARY_CHARS)
|
|
2457
|
+
};
|
|
2458
|
+
}
|
|
2459
|
+
if (latest?.status === "done") {
|
|
2460
|
+
return { status: "done", latestRun: latest };
|
|
2461
|
+
}
|
|
2462
|
+
return { status: "pending", latestRun: latest };
|
|
2463
|
+
}
|
|
2464
|
+
function toEpochMs2(iso) {
|
|
2465
|
+
if (!iso) return void 0;
|
|
2466
|
+
const ms = Date.parse(iso);
|
|
2467
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
2468
|
+
}
|
|
2469
|
+
function latestRun(runs) {
|
|
2470
|
+
let latest;
|
|
2471
|
+
let latestScore = -1;
|
|
2472
|
+
for (const run of runs) {
|
|
2473
|
+
const score = toEpochMs2(run.finishedAt) ?? toEpochMs2(run.startedAt) ?? -1;
|
|
2474
|
+
if (latest === void 0 || score >= latestScore) {
|
|
2475
|
+
latest = run;
|
|
2476
|
+
latestScore = score;
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
return latest;
|
|
2480
|
+
}
|
|
2481
|
+
function clipSummary(text, max) {
|
|
2482
|
+
if (!text) return void 0;
|
|
2483
|
+
const folded = text.replace(/\s+/g, " ").trim();
|
|
2484
|
+
if (folded.length === 0) return void 0;
|
|
2485
|
+
return folded.length > max ? `${folded.slice(0, max - 1)}\u2026` : folded;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
// packages/cli/client/fileSystemStores.ts
|
|
2489
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2490
|
+
import { homedir as nodeHomedir } from "node:os";
|
|
2491
|
+
import { dirname, join } from "node:path";
|
|
2492
|
+
var nodeFs = {
|
|
2493
|
+
mkdirSync,
|
|
2494
|
+
writeFileSync,
|
|
2495
|
+
readFileSync,
|
|
2496
|
+
existsSync
|
|
2497
|
+
};
|
|
2498
|
+
function resolveNoloHome(env, homedir) {
|
|
2499
|
+
const custom = env?.NOLO_HOME;
|
|
2500
|
+
if (custom && custom.trim()) return custom.trim();
|
|
2501
|
+
return join(homedir(), ".nolo");
|
|
2502
|
+
}
|
|
2503
|
+
function ensureDir(dir, fs) {
|
|
2504
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
2505
|
+
}
|
|
2506
|
+
function readJson(path, fs) {
|
|
2507
|
+
if (!fs.existsSync(path)) return void 0;
|
|
2508
|
+
try {
|
|
2509
|
+
const raw = fs.readFileSync(path, "utf8");
|
|
2510
|
+
return JSON.parse(String(raw));
|
|
2511
|
+
} catch {
|
|
2512
|
+
return void 0;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
function writeJson(path, data, fs) {
|
|
2516
|
+
fs.writeFileSync(path, JSON.stringify(data, null, 2));
|
|
2517
|
+
}
|
|
2518
|
+
function createFileSystemCircuitBreakerStore(opts = {}) {
|
|
2519
|
+
const env = opts.env ?? process.env;
|
|
2520
|
+
const homedir = opts.homedir ?? nodeHomedir;
|
|
2521
|
+
const fs = opts.fs ?? nodeFs;
|
|
2522
|
+
const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "breakers.json");
|
|
2523
|
+
const loadMap = () => {
|
|
2524
|
+
const data = readJson(filePath, fs);
|
|
2525
|
+
const map = /* @__PURE__ */ new Map();
|
|
2526
|
+
if (data?.entries) {
|
|
2527
|
+
for (const entry of data.entries) {
|
|
2528
|
+
if (entry && typeof entry.target === "string") map.set(entry.target, entry);
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
return map;
|
|
2532
|
+
};
|
|
2533
|
+
const persist = (map) => {
|
|
2534
|
+
ensureDir(dirname(filePath), fs);
|
|
2535
|
+
writeJson(filePath, { entries: [...map.values()] }, fs);
|
|
2536
|
+
};
|
|
2537
|
+
return {
|
|
2538
|
+
get(target) {
|
|
2539
|
+
return loadMap().get(target);
|
|
2540
|
+
},
|
|
2541
|
+
set(entry) {
|
|
2542
|
+
const map = loadMap();
|
|
2543
|
+
map.set(entry.target, entry);
|
|
2544
|
+
persist(map);
|
|
2545
|
+
},
|
|
2546
|
+
clear(target) {
|
|
2547
|
+
const map = loadMap();
|
|
2548
|
+
map.delete(target);
|
|
2549
|
+
persist(map);
|
|
2550
|
+
},
|
|
2551
|
+
clearAll() {
|
|
2552
|
+
persist(/* @__PURE__ */ new Map());
|
|
2553
|
+
}
|
|
2554
|
+
};
|
|
2555
|
+
}
|
|
2556
|
+
function createFileSystemTodoStore(opts = {}) {
|
|
2557
|
+
const env = opts.env ?? process.env;
|
|
2558
|
+
const homedir = opts.homedir ?? nodeHomedir;
|
|
2559
|
+
const fs = opts.fs ?? nodeFs;
|
|
2560
|
+
const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "todos.json");
|
|
2561
|
+
const loadMap = () => {
|
|
2562
|
+
const data = readJson(filePath, fs);
|
|
2563
|
+
const map = /* @__PURE__ */ new Map();
|
|
2564
|
+
if (data?.todos) {
|
|
2565
|
+
for (const todo of data.todos) {
|
|
2566
|
+
if (todo && typeof todo.id === "string") map.set(todo.id, todo);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
return map;
|
|
2570
|
+
};
|
|
2571
|
+
const persist = (map) => {
|
|
2572
|
+
ensureDir(dirname(filePath), fs);
|
|
2573
|
+
writeJson(filePath, { todos: [...map.values()] }, fs);
|
|
2574
|
+
};
|
|
2575
|
+
return {
|
|
2576
|
+
async getTodo(id) {
|
|
2577
|
+
return loadMap().get(id);
|
|
2578
|
+
},
|
|
2579
|
+
async listTodos(filter) {
|
|
2580
|
+
const all = [...loadMap().values()];
|
|
2581
|
+
if (!filter?.statuses || filter.statuses.length === 0) return all;
|
|
2582
|
+
const wanted = new Set(filter.statuses);
|
|
2583
|
+
return all.filter((t2) => wanted.has(t2.status));
|
|
2584
|
+
},
|
|
2585
|
+
async putTodo(todo) {
|
|
2586
|
+
const map = loadMap();
|
|
2587
|
+
map.set(todo.id, todo);
|
|
2588
|
+
persist(map);
|
|
2589
|
+
},
|
|
2590
|
+
async deleteTodo(id) {
|
|
2591
|
+
const map = loadMap();
|
|
2592
|
+
map.delete(id);
|
|
2593
|
+
persist(map);
|
|
2594
|
+
}
|
|
2595
|
+
};
|
|
2027
2596
|
}
|
|
2028
2597
|
|
|
2029
2598
|
// packages/cli/client/cliAgentRunToolExecutors.ts
|
|
2030
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2031
2599
|
var noopOutput = { write: () => {
|
|
2032
2600
|
} };
|
|
2033
2601
|
var parseCallArgs = (call) => {
|
|
@@ -2037,7 +2605,7 @@ var parseCallArgs = (call) => {
|
|
|
2037
2605
|
return {};
|
|
2038
2606
|
}
|
|
2039
2607
|
};
|
|
2040
|
-
var resolveFs = (deps) => deps.fs ?? { existsSync, readFileSync };
|
|
2608
|
+
var resolveFs = (deps) => deps.fs ?? { existsSync: existsSync2, readFileSync: readFileSync2 };
|
|
2041
2609
|
var tailFile = (logPath, tailLines, fs) => {
|
|
2042
2610
|
if (!fs.existsSync(logPath)) return void 0;
|
|
2043
2611
|
try {
|
|
@@ -2049,6 +2617,10 @@ var tailFile = (logPath, tailLines, fs) => {
|
|
|
2049
2617
|
return void 0;
|
|
2050
2618
|
}
|
|
2051
2619
|
};
|
|
2620
|
+
var resolveBreakerStore = (deps) => deps.breakerStore ?? createFileSystemCircuitBreakerStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2621
|
+
var resolveTodoStore = (deps) => deps.todoStore ?? createFileSystemTodoStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2622
|
+
var resolveNowMs = (deps) => typeof deps.nowMs === "function" ? deps.nowMs() : Date.now();
|
|
2623
|
+
var resolveTarget = (deps, agentKey) => typeof deps.resolveProviderTarget === "function" ? deps.resolveProviderTarget(agentKey) : agentKey;
|
|
2052
2624
|
function createCliStartAgentRunExecutor(deps = {}) {
|
|
2053
2625
|
return async (call) => {
|
|
2054
2626
|
const args = parseCallArgs(call);
|
|
@@ -2056,6 +2628,29 @@ function createCliStartAgentRunExecutor(deps = {}) {
|
|
|
2056
2628
|
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
2057
2629
|
if (!agentKey) throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
|
|
2058
2630
|
if (!task) throw new Error("startAgentRun: \u7F3A\u5C11\u6709\u6548\u7684 task \u6587\u672C\u63CF\u8FF0\u3002");
|
|
2631
|
+
const breakerStore = resolveBreakerStore(deps);
|
|
2632
|
+
const target = resolveTarget(deps, agentKey);
|
|
2633
|
+
const nowMs = resolveNowMs(deps);
|
|
2634
|
+
const activeBreaker = findActiveBreaker(
|
|
2635
|
+
nowMs,
|
|
2636
|
+
[breakerStore.get(target)].filter(Boolean),
|
|
2637
|
+
target
|
|
2638
|
+
);
|
|
2639
|
+
if (activeBreaker) {
|
|
2640
|
+
const resetsAt = activeBreaker.resetsAt;
|
|
2641
|
+
return {
|
|
2642
|
+
content: JSON.stringify({
|
|
2643
|
+
rejected: true,
|
|
2644
|
+
reason: "quota",
|
|
2645
|
+
provider: target,
|
|
2646
|
+
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
2647
|
+
message: `provider ${target} \u5904\u4E8E\u7194\u65AD\u671F\uFF08\u914D\u989D\u8017\u5C3D\uFF09\uFF0C\u5EFA\u8BAE\u6539\u6D3E\u5176\u5B83 provider\u3002`
|
|
2648
|
+
}),
|
|
2649
|
+
metadata: {
|
|
2650
|
+
displayData: `Run rejected \xB7 quota breaker active on ${target}`
|
|
2651
|
+
}
|
|
2652
|
+
};
|
|
2653
|
+
}
|
|
2059
2654
|
const message = typeof args.input === "undefined" ? task : `${task}
|
|
2060
2655
|
|
|
2061
2656
|
--- \u9644\u52A0\u8F93\u5165 ---
|
|
@@ -2071,13 +2666,16 @@ ${JSON.stringify(args.input)}`;
|
|
|
2071
2666
|
...args.ephemeral === true ? ["--ephemeral"] : []
|
|
2072
2667
|
];
|
|
2073
2668
|
const agentName = typeof args.agentName === "string" && args.agentName.trim() ? args.agentName.trim() : typeof args.name === "string" && args.name.trim() ? args.name.trim() : void 0;
|
|
2074
|
-
const
|
|
2669
|
+
const batchId = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
|
|
2670
|
+
const { runId, batchId: resolvedBatchId } = await spawnLocalBackgroundRun(
|
|
2075
2671
|
{
|
|
2076
2672
|
rawArgs,
|
|
2077
2673
|
commandPath: ["agent", "run"],
|
|
2078
2674
|
cliEntrypointPath: deps.cliEntrypoint,
|
|
2079
2675
|
agentKey,
|
|
2080
2676
|
...agentName ? { agentName } : {},
|
|
2677
|
+
...batchId ? { batchId } : {},
|
|
2678
|
+
...typeof args.parentDialogId === "string" && args.parentDialogId.trim() ? { parentDialogId: args.parentDialogId.trim() } : {},
|
|
2081
2679
|
cwd: deps.cwd ?? process.cwd(),
|
|
2082
2680
|
message,
|
|
2083
2681
|
output: noopOutput
|
|
@@ -2086,14 +2684,49 @@ ${JSON.stringify(args.input)}`;
|
|
|
2086
2684
|
);
|
|
2087
2685
|
const displayName = resolveRunLabel({ agentName, agentKey, runId });
|
|
2088
2686
|
const labels = agentRunCardLabels();
|
|
2687
|
+
const taskPreview = typeof args.task === "string" ? args.task.replace(/\s+/g, " ").trim().slice(0, TASK_PREVIEW_MAX) : "";
|
|
2688
|
+
const trackTodo = typeof args.trackTodo === "boolean" ? args.trackTodo : Boolean(resolvedBatchId);
|
|
2689
|
+
if (trackTodo) {
|
|
2690
|
+
try {
|
|
2691
|
+
const todoStore = resolveTodoStore(deps);
|
|
2692
|
+
const todoId = `todo-${resolvedBatchId}`;
|
|
2693
|
+
const existing = await todoStore.getTodo(todoId);
|
|
2694
|
+
const nowIso = new Date(nowMs).toISOString();
|
|
2695
|
+
const runIds = existing?.runIds ?? [];
|
|
2696
|
+
if (!runIds.includes(runId)) runIds.push(runId);
|
|
2697
|
+
const todo = {
|
|
2698
|
+
id: todoId,
|
|
2699
|
+
title: taskPreview || task.slice(0, 100),
|
|
2700
|
+
status: existing?.status ?? "pending",
|
|
2701
|
+
...existing?.specPath ? { specPath: existing.specPath } : {},
|
|
2702
|
+
...existing?.worktree ? { worktree: existing.worktree } : {},
|
|
2703
|
+
...existing?.branch ? { branch: existing.branch } : {},
|
|
2704
|
+
...deps.cwd ? { worktree: deps.cwd } : {},
|
|
2705
|
+
runIds,
|
|
2706
|
+
deps: existing?.deps ?? [],
|
|
2707
|
+
createdAt: existing?.createdAt ?? nowIso,
|
|
2708
|
+
updatedAt: nowIso
|
|
2709
|
+
};
|
|
2710
|
+
await todoStore.putTodo(todo);
|
|
2711
|
+
} catch {
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2089
2714
|
return {
|
|
2090
2715
|
content: JSON.stringify({
|
|
2091
2716
|
runId,
|
|
2092
2717
|
status: "running",
|
|
2093
|
-
|
|
2718
|
+
// batchId is always returned so the caller can later filter by it —
|
|
2719
|
+
// even when the caller didn't supply one, a fresh id was generated.
|
|
2720
|
+
batchId: resolvedBatchId,
|
|
2721
|
+
...agentName ? { agentName } : {},
|
|
2722
|
+
...taskPreview ? { taskPreview } : {}
|
|
2094
2723
|
}),
|
|
2095
2724
|
metadata: {
|
|
2096
|
-
displayData: formatStartRunCard(displayName, "running",
|
|
2725
|
+
displayData: formatStartRunCard(displayName, "running", {
|
|
2726
|
+
task: taskPreview,
|
|
2727
|
+
runId,
|
|
2728
|
+
labels
|
|
2729
|
+
})
|
|
2097
2730
|
}
|
|
2098
2731
|
};
|
|
2099
2732
|
};
|
|
@@ -2104,26 +2737,103 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2104
2737
|
const action = typeof args.action === "string" ? args.action : "";
|
|
2105
2738
|
const tailLines = typeof args.tailLines === "number" ? args.tailLines : 0;
|
|
2106
2739
|
if (action === "list") {
|
|
2107
|
-
|
|
2740
|
+
gcRunRecords(deps);
|
|
2741
|
+
const { runs: records, total, hasMore } = queryRunRecords(
|
|
2742
|
+
{
|
|
2743
|
+
...typeof args.batchId === "string" && args.batchId.trim() ? { batchId: args.batchId.trim() } : {},
|
|
2744
|
+
...typeof args.status === "string" && args.status.trim() ? { status: args.status.trim() } : typeof args.statusFilter === "string" && args.statusFilter.trim() ? { status: args.statusFilter.trim() } : {},
|
|
2745
|
+
...typeof args.limit === "number" ? { limit: args.limit } : {},
|
|
2746
|
+
...typeof args.offset === "number" ? { offset: args.offset } : {}
|
|
2747
|
+
},
|
|
2748
|
+
deps
|
|
2749
|
+
);
|
|
2108
2750
|
const runs = records.map((record2) => {
|
|
2109
|
-
const reconciled = checkStaleRun(record2.runId, deps) ?? record2;
|
|
2110
2751
|
return {
|
|
2111
|
-
runId:
|
|
2112
|
-
status:
|
|
2113
|
-
agentKey:
|
|
2114
|
-
...
|
|
2115
|
-
|
|
2116
|
-
|
|
2752
|
+
runId: record2.runId,
|
|
2753
|
+
status: record2.status,
|
|
2754
|
+
agentKey: record2.agentKey,
|
|
2755
|
+
...record2.agentName ? { agentName: record2.agentName } : {},
|
|
2756
|
+
...record2.batchId ? { batchId: record2.batchId } : {},
|
|
2757
|
+
pid: record2.pid ?? null,
|
|
2758
|
+
startedAt: record2.startedAt
|
|
2117
2759
|
};
|
|
2118
2760
|
});
|
|
2119
2761
|
const labels2 = agentRunCardLabels();
|
|
2762
|
+
const batchIdArg = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
|
|
2763
|
+
let batchSummary;
|
|
2764
|
+
if (batchIdArg && records.length > 0) {
|
|
2765
|
+
const batchRuns = records.map((r) => ({
|
|
2766
|
+
runId: r.runId,
|
|
2767
|
+
status: r.status,
|
|
2768
|
+
startedAt: r.startedAt,
|
|
2769
|
+
...r.agentName ? { agentName: r.agentName } : {}
|
|
2770
|
+
}));
|
|
2771
|
+
batchSummary = aggregateBatch({
|
|
2772
|
+
batchId: batchIdArg,
|
|
2773
|
+
runs: batchRuns,
|
|
2774
|
+
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2775
|
+
});
|
|
2776
|
+
}
|
|
2120
2777
|
return {
|
|
2121
|
-
content: JSON.stringify({
|
|
2778
|
+
content: JSON.stringify({
|
|
2779
|
+
runs,
|
|
2780
|
+
count: runs.length,
|
|
2781
|
+
total,
|
|
2782
|
+
hasMore,
|
|
2783
|
+
...batchSummary?.summary ? { batchSummary: batchSummary.summary } : {}
|
|
2784
|
+
}),
|
|
2122
2785
|
metadata: {
|
|
2123
2786
|
displayData: formatListRunsCard(runs, labels2)
|
|
2124
2787
|
}
|
|
2125
2788
|
};
|
|
2126
2789
|
}
|
|
2790
|
+
if (action === "todo") {
|
|
2791
|
+
const todoStore = resolveTodoStore(deps);
|
|
2792
|
+
const statusesRaw = typeof args.status === "string" ? args.status.trim() : void 0;
|
|
2793
|
+
const filter = statusesRaw && statusesRaw !== "all" ? { statuses: statusesRaw.split(",").map((s) => s.trim()).filter(Boolean) } : void 0;
|
|
2794
|
+
const todos = await todoStore.listTodos(filter);
|
|
2795
|
+
const enriched = await Promise.all(
|
|
2796
|
+
todos.map(async (todo) => {
|
|
2797
|
+
const runSummaries = [];
|
|
2798
|
+
for (const rid of todo.runIds) {
|
|
2799
|
+
const rec = findRunRecord(rid, deps);
|
|
2800
|
+
if (!rec) continue;
|
|
2801
|
+
runSummaries.push({
|
|
2802
|
+
runId: rec.runId,
|
|
2803
|
+
status: rec.status,
|
|
2804
|
+
startedAt: rec.startedAt,
|
|
2805
|
+
...rec.agentName ? { agentName: rec.agentName } : {}
|
|
2806
|
+
});
|
|
2807
|
+
}
|
|
2808
|
+
const derived = deriveTodoStatus({
|
|
2809
|
+
todo: { id: todo.id, status: todo.status },
|
|
2810
|
+
runs: runSummaries,
|
|
2811
|
+
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2812
|
+
});
|
|
2813
|
+
return {
|
|
2814
|
+
id: todo.id,
|
|
2815
|
+
title: todo.title,
|
|
2816
|
+
status: derived.status,
|
|
2817
|
+
runIds: todo.runIds,
|
|
2818
|
+
...derived.blockedReason ? { blockedReason: derived.blockedReason } : {},
|
|
2819
|
+
...derived.latestRun ? { latestRunId: derived.latestRun.runId, latestRunStatus: derived.latestRun.status } : {},
|
|
2820
|
+
updatedAt: todo.updatedAt
|
|
2821
|
+
};
|
|
2822
|
+
})
|
|
2823
|
+
);
|
|
2824
|
+
return {
|
|
2825
|
+
content: JSON.stringify({ todos: enriched, count: enriched.length }),
|
|
2826
|
+
metadata: {
|
|
2827
|
+
displayData: formatListRunsCard(
|
|
2828
|
+
enriched.map((t2) => ({
|
|
2829
|
+
agentName: t2.title,
|
|
2830
|
+
status: t2.status
|
|
2831
|
+
})),
|
|
2832
|
+
agentRunCardLabels()
|
|
2833
|
+
)
|
|
2834
|
+
}
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2127
2837
|
if (action !== "status" && action !== "stop") {
|
|
2128
2838
|
throw new Error(`controlAgentRun: \u672A\u77E5 action "${action}"\u3002`);
|
|
2129
2839
|
}
|
|
@@ -2142,6 +2852,25 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2142
2852
|
const name = resolveRunLabel(reconciled);
|
|
2143
2853
|
const logLines = logTail ? logTail.split("\n") : void 0;
|
|
2144
2854
|
const labels2 = agentRunCardLabels();
|
|
2855
|
+
if (reconciled.status === "failed" || reconciled.status === "orphaned") {
|
|
2856
|
+
try {
|
|
2857
|
+
const failureSource = logTail ?? reconciled.note ?? "";
|
|
2858
|
+
const failureInfo = classifyRunFailure(
|
|
2859
|
+
failureSource || reconciled.status
|
|
2860
|
+
);
|
|
2861
|
+
if (failureInfo.reason === "quota") {
|
|
2862
|
+
const t2 = resolveTarget(deps, reconciled.agentKey);
|
|
2863
|
+
const entry = buildBreakerEntry(
|
|
2864
|
+
resolveNowMs(deps),
|
|
2865
|
+
t2,
|
|
2866
|
+
"quota",
|
|
2867
|
+
failureInfo.retryAfterMs
|
|
2868
|
+
);
|
|
2869
|
+
resolveBreakerStore(deps).set(entry);
|
|
2870
|
+
}
|
|
2871
|
+
} catch {
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2145
2874
|
return {
|
|
2146
2875
|
content: JSON.stringify({
|
|
2147
2876
|
runId: reconciled.runId,
|
|
@@ -2166,7 +2895,15 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2166
2895
|
...logLines ? { logLines } : {}
|
|
2167
2896
|
}),
|
|
2168
2897
|
metadata: {
|
|
2169
|
-
displayData: formatStatusRunCard(name, reconciled.status, {
|
|
2898
|
+
displayData: formatStatusRunCard(name, reconciled.status, {
|
|
2899
|
+
runId: reconciled.runId,
|
|
2900
|
+
timing: {
|
|
2901
|
+
startedAt: readTimestamp(reconciled.startedAt),
|
|
2902
|
+
finishedAt: readTimestamp(reconciled.endedAt)
|
|
2903
|
+
},
|
|
2904
|
+
logLines,
|
|
2905
|
+
labels: labels2
|
|
2906
|
+
})
|
|
2170
2907
|
}
|
|
2171
2908
|
};
|
|
2172
2909
|
}
|
|
@@ -2304,7 +3041,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2304
3041
|
}
|
|
2305
3042
|
};
|
|
2306
3043
|
},
|
|
2307
|
-
|
|
3044
|
+
ask_user: async (call) => {
|
|
2308
3045
|
const parsedArgs = (() => {
|
|
2309
3046
|
try {
|
|
2310
3047
|
return JSON.parse(call.arguments || "{}");
|
|
@@ -2320,8 +3057,8 @@ function buildLocalToolExecutors(args) {
|
|
|
2320
3057
|
if (!hasQuestions && (!question || choices.length === 0)) {
|
|
2321
3058
|
return {
|
|
2322
3059
|
content: JSON.stringify({
|
|
2323
|
-
error: "
|
|
2324
|
-
detail: "
|
|
3060
|
+
error: "ask_user",
|
|
3061
|
+
detail: "ask_user \u9700\u8981 question+choices \u6216 questions\u3002"
|
|
2325
3062
|
}),
|
|
2326
3063
|
metadata: { uiAskChoice: true, error: true }
|
|
2327
3064
|
};
|
|
@@ -2337,7 +3074,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2337
3074
|
if (result.kind === "multi-submitted") {
|
|
2338
3075
|
return {
|
|
2339
3076
|
content: JSON.stringify({
|
|
2340
|
-
type: "
|
|
3077
|
+
type: "ask_user",
|
|
2341
3078
|
question,
|
|
2342
3079
|
choices,
|
|
2343
3080
|
blocking,
|
|
@@ -2354,7 +3091,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2354
3091
|
if (result.kind === "selected") {
|
|
2355
3092
|
return {
|
|
2356
3093
|
content: JSON.stringify({
|
|
2357
|
-
type: "
|
|
3094
|
+
type: "ask_user",
|
|
2358
3095
|
question,
|
|
2359
3096
|
choices,
|
|
2360
3097
|
blocking,
|
|
@@ -2369,7 +3106,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2369
3106
|
}
|
|
2370
3107
|
return {
|
|
2371
3108
|
content: JSON.stringify({
|
|
2372
|
-
type: "
|
|
3109
|
+
type: "ask_user",
|
|
2373
3110
|
question,
|
|
2374
3111
|
choices,
|
|
2375
3112
|
blocking,
|
|
@@ -2384,7 +3121,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2384
3121
|
}
|
|
2385
3122
|
return {
|
|
2386
3123
|
content: JSON.stringify({
|
|
2387
|
-
type: "
|
|
3124
|
+
type: "ask_user",
|
|
2388
3125
|
question,
|
|
2389
3126
|
choices,
|
|
2390
3127
|
blocking,
|
|
@@ -2448,19 +3185,22 @@ function resolveAntigravityWireModel(logicalModelId) {
|
|
|
2448
3185
|
return { wireModelId: id };
|
|
2449
3186
|
}
|
|
2450
3187
|
|
|
2451
|
-
// packages/agent-runtime/
|
|
2452
|
-
var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
|
|
3188
|
+
// packages/agent-runtime/geminiNativeShared.ts
|
|
2453
3189
|
var SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
2454
|
-
function
|
|
3190
|
+
function isGemini3Model(modelId) {
|
|
2455
3191
|
return modelId.includes("gemini-3");
|
|
2456
3192
|
}
|
|
2457
3193
|
function messageText(content) {
|
|
2458
3194
|
if (typeof content === "string") return content;
|
|
2459
3195
|
if (!Array.isArray(content)) return "";
|
|
2460
|
-
return content.filter(
|
|
3196
|
+
return content.filter(
|
|
3197
|
+
(part) => part?.type === "text"
|
|
3198
|
+
).map((part) => part.text).join("\n").trim();
|
|
2461
3199
|
}
|
|
2462
3200
|
function parseDataUrlToInlineData(url) {
|
|
2463
|
-
const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
|
|
3201
|
+
const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
|
|
3202
|
+
url
|
|
3203
|
+
);
|
|
2464
3204
|
if (!match) return null;
|
|
2465
3205
|
return { mimeType: match[1], data: match[2] };
|
|
2466
3206
|
}
|
|
@@ -2477,7 +3217,7 @@ function extractInlineDataParts(content) {
|
|
|
2477
3217
|
}
|
|
2478
3218
|
return parts;
|
|
2479
3219
|
}
|
|
2480
|
-
function
|
|
3220
|
+
function convertOpenAiMessagesToGemini(messages, options) {
|
|
2481
3221
|
const contents = [];
|
|
2482
3222
|
const systemTexts = [];
|
|
2483
3223
|
const toolNamesById = /* @__PURE__ */ new Map();
|
|
@@ -2493,9 +3233,11 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2493
3233
|
};
|
|
2494
3234
|
const flushPendingFunctionCalls = () => {
|
|
2495
3235
|
if (pendingFunctionCalls.length === 0) return;
|
|
2496
|
-
const dummyResponses = pendingFunctionCalls.map(
|
|
2497
|
-
|
|
2498
|
-
|
|
3236
|
+
const dummyResponses = pendingFunctionCalls.map(
|
|
3237
|
+
({ name }) => ({
|
|
3238
|
+
functionResponse: { name, response: { output: "{}" } }
|
|
3239
|
+
})
|
|
3240
|
+
);
|
|
2499
3241
|
pendingFunctionCalls = [];
|
|
2500
3242
|
pushOrMergeContent("user", dummyResponses);
|
|
2501
3243
|
};
|
|
@@ -2504,13 +3246,17 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2504
3246
|
const role = String(raw.role);
|
|
2505
3247
|
const content = "content" in raw ? raw.content : null;
|
|
2506
3248
|
if (role === "system") {
|
|
2507
|
-
const text = messageText(
|
|
3249
|
+
const text = messageText(
|
|
3250
|
+
content
|
|
3251
|
+
);
|
|
2508
3252
|
if (text) systemTexts.push(text);
|
|
2509
3253
|
continue;
|
|
2510
3254
|
}
|
|
2511
3255
|
if (role === "user") {
|
|
2512
3256
|
flushPendingFunctionCalls();
|
|
2513
|
-
const text = messageText(
|
|
3257
|
+
const text = messageText(
|
|
3258
|
+
content
|
|
3259
|
+
);
|
|
2514
3260
|
const imageParts = extractInlineDataParts(
|
|
2515
3261
|
content
|
|
2516
3262
|
);
|
|
@@ -2524,7 +3270,9 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2524
3270
|
if (role === "assistant") {
|
|
2525
3271
|
flushPendingFunctionCalls();
|
|
2526
3272
|
const parts = [];
|
|
2527
|
-
const text = messageText(
|
|
3273
|
+
const text = messageText(
|
|
3274
|
+
content
|
|
3275
|
+
);
|
|
2528
3276
|
if (text) parts.push({ text });
|
|
2529
3277
|
const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
|
|
2530
3278
|
for (const call of toolCalls) {
|
|
@@ -2534,17 +3282,20 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2534
3282
|
toolNamesById.set(id, name);
|
|
2535
3283
|
pendingFunctionCalls.push({ name, id });
|
|
2536
3284
|
const realSignature = typeof call.thought_signature === "string" && call.thought_signature ? call.thought_signature : void 0;
|
|
2537
|
-
const isFirstFunctionCallPart = !parts.some(
|
|
2538
|
-
|
|
3285
|
+
const isFirstFunctionCallPart = !parts.some(
|
|
3286
|
+
(p) => "functionCall" in p
|
|
3287
|
+
);
|
|
3288
|
+
const signature = realSignature ?? (options.attachSkipThoughtSignature && isFirstFunctionCallPart ? SKIP_THOUGHT_SIGNATURE : void 0);
|
|
3289
|
+
const part = {
|
|
2539
3290
|
functionCall: {
|
|
2540
3291
|
name,
|
|
2541
|
-
args:
|
|
2542
|
-
id
|
|
3292
|
+
args: parseToolArgs(call.function?.arguments),
|
|
3293
|
+
...id ? { id } : {}
|
|
2543
3294
|
},
|
|
2544
|
-
...
|
|
2545
|
-
}
|
|
3295
|
+
...signature ? { thoughtSignature: signature } : {}
|
|
3296
|
+
};
|
|
3297
|
+
parts.push(part);
|
|
2546
3298
|
}
|
|
2547
|
-
if (parts.length === 0) continue;
|
|
2548
3299
|
pushOrMergeContent("model", parts);
|
|
2549
3300
|
continue;
|
|
2550
3301
|
}
|
|
@@ -2562,14 +3313,39 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2562
3313
|
}
|
|
2563
3314
|
const output = messageText(content) || "{}";
|
|
2564
3315
|
pushOrMergeContent("user", [
|
|
2565
|
-
{
|
|
3316
|
+
{
|
|
3317
|
+
functionResponse: {
|
|
3318
|
+
name,
|
|
3319
|
+
response: { output },
|
|
3320
|
+
// 保留 OpenAI tool_call_id:antigravity Cloud Code Assist 网关把
|
|
3321
|
+
// Gemini contents 转成 Claude messages 时需要 functionResponse →
|
|
3322
|
+
// tool_result 的 tool_use_id;缺 id 时网关报
|
|
3323
|
+
// "tool_result.tool_use_id: Field required"(HTTP 400)。
|
|
3324
|
+
...toolCallId ? { id: toolCallId } : {}
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
2566
3327
|
]);
|
|
2567
3328
|
}
|
|
2568
3329
|
}
|
|
2569
3330
|
flushPendingFunctionCalls();
|
|
2570
3331
|
return { contents, systemTexts };
|
|
2571
3332
|
}
|
|
2572
|
-
function
|
|
3333
|
+
function parseToolArgs(raw) {
|
|
3334
|
+
if (typeof raw === "string") {
|
|
3335
|
+
try {
|
|
3336
|
+
const parsed = JSON.parse(raw);
|
|
3337
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3338
|
+
return parsed;
|
|
3339
|
+
}
|
|
3340
|
+
} catch {
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
3344
|
+
return raw;
|
|
3345
|
+
}
|
|
3346
|
+
return {};
|
|
3347
|
+
}
|
|
3348
|
+
function convertOpenAiToolsToGemini(tools) {
|
|
2573
3349
|
if (!Array.isArray(tools) || tools.length === 0) return void 0;
|
|
2574
3350
|
const declarations = [];
|
|
2575
3351
|
for (const tool of tools) {
|
|
@@ -2586,79 +3362,7 @@ function convertOpenAiTools(tools) {
|
|
|
2586
3362
|
if (declarations.length === 0) return void 0;
|
|
2587
3363
|
return [{ functionDeclarations: declarations }];
|
|
2588
3364
|
}
|
|
2589
|
-
function
|
|
2590
|
-
const projectId = readAntigravityProjectId(args.metadata);
|
|
2591
|
-
if (!projectId) {
|
|
2592
|
-
throw new Error(
|
|
2593
|
-
"Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
|
|
2594
|
-
);
|
|
2595
|
-
}
|
|
2596
|
-
const logicalModel = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gemini-3.1-pro";
|
|
2597
|
-
const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
|
|
2598
|
-
const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
|
|
2599
|
-
const { contents, systemTexts } = convertOpenAiMessagesToCca(rawMessages, {
|
|
2600
|
-
attachSkipThoughtSignature: isGemini3WireModel(model)
|
|
2601
|
-
});
|
|
2602
|
-
if (contents.length === 0) {
|
|
2603
|
-
throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
|
|
2604
|
-
}
|
|
2605
|
-
const prompt = args.agentConfig.prompt?.trim();
|
|
2606
|
-
if (prompt) systemTexts.unshift(prompt);
|
|
2607
|
-
const request = { contents };
|
|
2608
|
-
if (systemTexts.length > 0) {
|
|
2609
|
-
request.systemInstruction = {
|
|
2610
|
-
role: "user",
|
|
2611
|
-
parts: systemTexts.map((text) => ({ text }))
|
|
2612
|
-
};
|
|
2613
|
-
}
|
|
2614
|
-
const tools = convertOpenAiTools(
|
|
2615
|
-
Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
|
|
2616
|
-
);
|
|
2617
|
-
if (tools) {
|
|
2618
|
-
request.tools = tools;
|
|
2619
|
-
request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
|
|
2620
|
-
}
|
|
2621
|
-
const generationConfig = {};
|
|
2622
|
-
if (profile?.maxOutputTokens) {
|
|
2623
|
-
generationConfig.maxOutputTokens = profile.maxOutputTokens;
|
|
2624
|
-
} else if (typeof args.agentConfig.max_tokens === "number" && args.agentConfig.max_tokens > 0) {
|
|
2625
|
-
generationConfig.maxOutputTokens = args.agentConfig.max_tokens;
|
|
2626
|
-
}
|
|
2627
|
-
if (typeof args.agentConfig.temperature === "number") {
|
|
2628
|
-
generationConfig.temperature = args.agentConfig.temperature;
|
|
2629
|
-
}
|
|
2630
|
-
if (Object.keys(generationConfig).length > 0) {
|
|
2631
|
-
request.generationConfig = generationConfig;
|
|
2632
|
-
}
|
|
2633
|
-
const agentId = randomUUID();
|
|
2634
|
-
const trajectoryId = randomUUID();
|
|
2635
|
-
const step = 2;
|
|
2636
|
-
const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
|
|
2637
|
-
const isClaude = model.toLowerCase().includes("claude");
|
|
2638
|
-
const labels = {
|
|
2639
|
-
trajectory_id: trajectoryId,
|
|
2640
|
-
last_step_index: String(step - 1),
|
|
2641
|
-
used_claude: String(isClaude),
|
|
2642
|
-
used_claude_conservative: String(isClaude)
|
|
2643
|
-
};
|
|
2644
|
-
if (profile?.modelEnum) {
|
|
2645
|
-
labels.model_enum = profile.modelEnum;
|
|
2646
|
-
}
|
|
2647
|
-
request.labels = labels;
|
|
2648
|
-
request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
|
|
2649
|
-
return {
|
|
2650
|
-
url: `${resolveAntigravityCloudCodeBaseUrl(args.agentConfig.customProviderUrl)}${STREAM_PATH}`,
|
|
2651
|
-
envelope: {
|
|
2652
|
-
project: projectId,
|
|
2653
|
-
model,
|
|
2654
|
-
request,
|
|
2655
|
-
requestId,
|
|
2656
|
-
requestType: "agent",
|
|
2657
|
-
userAgent: "antigravity"
|
|
2658
|
-
}
|
|
2659
|
-
};
|
|
2660
|
-
}
|
|
2661
|
-
function accumulateCcaChunks(chunks) {
|
|
3365
|
+
function accumulateGeminiChunks(chunks) {
|
|
2662
3366
|
let text = "";
|
|
2663
3367
|
const toolCalls = [];
|
|
2664
3368
|
let usage;
|
|
@@ -2679,11 +3383,10 @@ function accumulateCcaChunks(chunks) {
|
|
|
2679
3383
|
}
|
|
2680
3384
|
const candidates = Array.isArray(response.candidates) ? response.candidates : [];
|
|
2681
3385
|
for (const candidate of candidates) {
|
|
2682
|
-
if (!candidate || typeof candidate !== "object"
|
|
2683
|
-
const
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
if (!Array.isArray(parts)) continue;
|
|
3386
|
+
if (!candidate || typeof candidate !== "object") continue;
|
|
3387
|
+
const parts = Array.isArray(
|
|
3388
|
+
candidate.content?.parts
|
|
3389
|
+
) ? candidate.content.parts : [];
|
|
2687
3390
|
for (const part of parts) {
|
|
2688
3391
|
if (!part || typeof part !== "object") continue;
|
|
2689
3392
|
const partSignature = part.thoughtSignature;
|
|
@@ -2700,7 +3403,7 @@ function accumulateCcaChunks(chunks) {
|
|
|
2700
3403
|
const call = part.functionCall;
|
|
2701
3404
|
const name = typeof call.name === "string" ? call.name : "tool";
|
|
2702
3405
|
const id = typeof call.id === "string" ? call.id : `${name}_${toolCalls.length}`;
|
|
2703
|
-
const argsObj =
|
|
3406
|
+
const argsObj = call.args && typeof call.args === "object" ? call.args : {};
|
|
2704
3407
|
const resolvedSignature = typeof partSignature === "string" && partSignature ? partSignature : pendingThoughtSignature;
|
|
2705
3408
|
pendingThoughtSignature = void 0;
|
|
2706
3409
|
toolCalls.push({
|
|
@@ -2713,7 +3416,114 @@ function accumulateCcaChunks(chunks) {
|
|
|
2713
3416
|
}
|
|
2714
3417
|
}
|
|
2715
3418
|
}
|
|
2716
|
-
return { text, toolCalls, usage };
|
|
3419
|
+
return { text, toolCalls, usage };
|
|
3420
|
+
}
|
|
3421
|
+
function shouldUseGeminiNativeToolRoute(provider, model, tools, isImageModel) {
|
|
3422
|
+
return provider === "google" && !isImageModel(model) && isGemini3Model(model) && Array.isArray(tools) && tools.length > 0;
|
|
3423
|
+
}
|
|
3424
|
+
function buildGeminiGenerateContentRequest(args) {
|
|
3425
|
+
const { contents, systemTexts } = convertOpenAiMessagesToGemini(
|
|
3426
|
+
args.messages,
|
|
3427
|
+
{ attachSkipThoughtSignature: args.attachSkipThoughtSignature }
|
|
3428
|
+
);
|
|
3429
|
+
const request = { contents };
|
|
3430
|
+
if (systemTexts.length > 0) {
|
|
3431
|
+
request.systemInstruction = {
|
|
3432
|
+
role: "user",
|
|
3433
|
+
parts: systemTexts.map((text) => ({ text }))
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
const toolsResult = convertOpenAiToolsToGemini(args.tools);
|
|
3437
|
+
if (toolsResult) {
|
|
3438
|
+
request.tools = toolsResult;
|
|
3439
|
+
request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
|
|
3440
|
+
}
|
|
3441
|
+
const generationConfig = {};
|
|
3442
|
+
if (typeof args.maxTokens === "number" && args.maxTokens > 0) {
|
|
3443
|
+
generationConfig.maxOutputTokens = args.maxTokens;
|
|
3444
|
+
}
|
|
3445
|
+
if (typeof args.temperature === "number") {
|
|
3446
|
+
generationConfig.temperature = args.temperature;
|
|
3447
|
+
}
|
|
3448
|
+
if (Object.keys(generationConfig).length > 0) {
|
|
3449
|
+
request.generationConfig = generationConfig;
|
|
3450
|
+
}
|
|
3451
|
+
return request;
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3454
|
+
// packages/agent-runtime/antigravityCloudCodeProvider.ts
|
|
3455
|
+
var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
|
|
3456
|
+
function buildCloudCodeAssistPayload(args) {
|
|
3457
|
+
const projectId = readAntigravityProjectId(args.metadata);
|
|
3458
|
+
if (!projectId) {
|
|
3459
|
+
throw new Error(
|
|
3460
|
+
"Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
|
|
3461
|
+
);
|
|
3462
|
+
}
|
|
3463
|
+
const logicalModel = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gemini-3.1-pro";
|
|
3464
|
+
const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
|
|
3465
|
+
const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
|
|
3466
|
+
const isClaude = model.toLowerCase().includes("claude");
|
|
3467
|
+
const { contents, systemTexts } = convertOpenAiMessagesToGemini(rawMessages, {
|
|
3468
|
+
attachSkipThoughtSignature: isGemini3Model(model)
|
|
3469
|
+
});
|
|
3470
|
+
if (contents.length === 0) {
|
|
3471
|
+
throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
|
|
3472
|
+
}
|
|
3473
|
+
const prompt = args.agentConfig.prompt?.trim();
|
|
3474
|
+
if (prompt) systemTexts.unshift(prompt);
|
|
3475
|
+
const request = { contents };
|
|
3476
|
+
if (systemTexts.length > 0) {
|
|
3477
|
+
request.systemInstruction = {
|
|
3478
|
+
role: "user",
|
|
3479
|
+
parts: systemTexts.map((text) => ({ text }))
|
|
3480
|
+
};
|
|
3481
|
+
}
|
|
3482
|
+
const tools = convertOpenAiToolsToGemini(
|
|
3483
|
+
Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
|
|
3484
|
+
);
|
|
3485
|
+
if (tools) {
|
|
3486
|
+
request.tools = tools;
|
|
3487
|
+
request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
|
|
3488
|
+
}
|
|
3489
|
+
const generationConfig = {};
|
|
3490
|
+
if (profile?.maxOutputTokens) {
|
|
3491
|
+
generationConfig.maxOutputTokens = profile.maxOutputTokens;
|
|
3492
|
+
} else if (typeof args.agentConfig.max_tokens === "number" && args.agentConfig.max_tokens > 0) {
|
|
3493
|
+
generationConfig.maxOutputTokens = args.agentConfig.max_tokens;
|
|
3494
|
+
}
|
|
3495
|
+
if (typeof args.agentConfig.temperature === "number") {
|
|
3496
|
+
generationConfig.temperature = args.agentConfig.temperature;
|
|
3497
|
+
}
|
|
3498
|
+
if (Object.keys(generationConfig).length > 0) {
|
|
3499
|
+
request.generationConfig = generationConfig;
|
|
3500
|
+
}
|
|
3501
|
+
const agentId = randomUUID();
|
|
3502
|
+
const trajectoryId = randomUUID();
|
|
3503
|
+
const step = 2;
|
|
3504
|
+
const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
|
|
3505
|
+
const labels = {
|
|
3506
|
+
trajectory_id: trajectoryId,
|
|
3507
|
+
last_step_index: String(step - 1),
|
|
3508
|
+
used_claude: String(isClaude),
|
|
3509
|
+
used_claude_conservative: String(isClaude)
|
|
3510
|
+
};
|
|
3511
|
+
if (profile?.modelEnum) {
|
|
3512
|
+
labels.model_enum = profile.modelEnum;
|
|
3513
|
+
}
|
|
3514
|
+
request.labels = labels;
|
|
3515
|
+
request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
|
|
3516
|
+
return {
|
|
3517
|
+
url: `${resolveAntigravityCloudCodeBaseUrl(args.agentConfig.customProviderUrl)}${STREAM_PATH}`,
|
|
3518
|
+
envelope: {
|
|
3519
|
+
project: projectId,
|
|
3520
|
+
model,
|
|
3521
|
+
request,
|
|
3522
|
+
requestId,
|
|
3523
|
+
requestType: "agent",
|
|
3524
|
+
userAgent: "antigravity"
|
|
3525
|
+
}
|
|
3526
|
+
};
|
|
2717
3527
|
}
|
|
2718
3528
|
async function readSseJsonChunks(response) {
|
|
2719
3529
|
return readSseDataValues(response, parseSseDataLineJson);
|
|
@@ -2739,7 +3549,7 @@ async function fetchAntigravityCloudCodeCompletion(args) {
|
|
|
2739
3549
|
};
|
|
2740
3550
|
}
|
|
2741
3551
|
const chunks = await readSseJsonChunks(response);
|
|
2742
|
-
const { text, toolCalls, usage } =
|
|
3552
|
+
const { text, toolCalls, usage } = accumulateGeminiChunks(chunks);
|
|
2743
3553
|
const message = {
|
|
2744
3554
|
role: "assistant",
|
|
2745
3555
|
content: text || null
|
|
@@ -2775,9 +3585,67 @@ var CLAUDE_CODE_IDENTITY_PATTERNS = [
|
|
|
2775
3585
|
CLAUDE_CODE_SYSTEM_INSTRUCTION,
|
|
2776
3586
|
"You are Claude Code"
|
|
2777
3587
|
];
|
|
3588
|
+
var REASONING_EFFORT_TO_BUDGET = {
|
|
3589
|
+
minimal: 2048,
|
|
3590
|
+
low: 4096,
|
|
3591
|
+
medium: 8192,
|
|
3592
|
+
high: 16384,
|
|
3593
|
+
xhigh: 32e3,
|
|
3594
|
+
max: 32e3
|
|
3595
|
+
};
|
|
3596
|
+
function resolveThinkingBudget(effort) {
|
|
3597
|
+
if (!effort) return void 0;
|
|
3598
|
+
const normalized = effort.toLowerCase();
|
|
3599
|
+
if (normalized === "none" || normalized === "off") return void 0;
|
|
3600
|
+
return REASONING_EFFORT_TO_BUDGET[normalized];
|
|
3601
|
+
}
|
|
3602
|
+
var DEFAULT_THINKING_EFFORT = "medium";
|
|
3603
|
+
var DEFAULT_ENABLED_BUDGET = 8192;
|
|
3604
|
+
var DEFAULT_ENABLE_THINKING_BUDGET = 8e3;
|
|
3605
|
+
var ANTHROPIC_EFFORT_ALIASES = { minimal: "low" };
|
|
3606
|
+
function resolveThinkingSpec(input) {
|
|
3607
|
+
const { model, maxTokens } = input;
|
|
3608
|
+
const normalizedEffort = input.reasoningEffort?.toLowerCase();
|
|
3609
|
+
const effortDisabled = normalizedEffort === "none" || normalizedEffort === "off";
|
|
3610
|
+
const effectiveEffort = normalizedEffort !== void 0 && !effortDisabled ? ANTHROPIC_EFFORT_ALIASES[normalizedEffort] ?? normalizedEffort : DEFAULT_THINKING_EFFORT;
|
|
3611
|
+
let thinkingBlock;
|
|
3612
|
+
let outputConfig;
|
|
3613
|
+
let finalMaxTokens = maxTokens;
|
|
3614
|
+
let finalTemperature = input.temperature;
|
|
3615
|
+
if (isAdaptiveThinkingModelId(model)) {
|
|
3616
|
+
if (effortDisabled) {
|
|
3617
|
+
thinkingBlock = { type: "disabled" };
|
|
3618
|
+
} else {
|
|
3619
|
+
thinkingBlock = { type: "adaptive", display: "summarized" };
|
|
3620
|
+
outputConfig = { effort: effectiveEffort };
|
|
3621
|
+
}
|
|
3622
|
+
} else {
|
|
3623
|
+
const injected = input.injectedThinking;
|
|
3624
|
+
const injectedBudget = injected?.type === "enabled" && typeof injected.budget_tokens === "number" ? injected.budget_tokens : void 0;
|
|
3625
|
+
const effortBudget = resolveThinkingBudget(input.reasoningEffort);
|
|
3626
|
+
const fallbackBudget = input.reasoningEffort === void 0 ? injectedBudget ?? (input.enableThinking === true ? typeof input.thinkingBudget === "number" ? input.thinkingBudget : DEFAULT_ENABLE_THINKING_BUDGET : DEFAULT_ENABLED_BUDGET) : void 0;
|
|
3627
|
+
const thinkingBudget = effortBudget ?? fallbackBudget;
|
|
3628
|
+
if (thinkingBudget !== void 0) {
|
|
3629
|
+
thinkingBlock = { type: "enabled", budget_tokens: thinkingBudget };
|
|
3630
|
+
finalMaxTokens = Math.max(maxTokens, thinkingBudget + 1);
|
|
3631
|
+
finalTemperature = 1;
|
|
3632
|
+
}
|
|
3633
|
+
}
|
|
3634
|
+
return {
|
|
3635
|
+
thinkingBlock,
|
|
3636
|
+
outputConfig,
|
|
3637
|
+
maxTokens: finalMaxTokens,
|
|
3638
|
+
temperature: finalTemperature
|
|
3639
|
+
};
|
|
3640
|
+
}
|
|
2778
3641
|
function stringValue(value) {
|
|
2779
3642
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
2780
3643
|
}
|
|
3644
|
+
function isCacheControl(value) {
|
|
3645
|
+
return Boolean(
|
|
3646
|
+
value && typeof value === "object" && !Array.isArray(value) && typeof value.type === "string"
|
|
3647
|
+
);
|
|
3648
|
+
}
|
|
2781
3649
|
function toAnthropicContent(content) {
|
|
2782
3650
|
if (typeof content === "string") {
|
|
2783
3651
|
return content.length > 0 ? [{ type: "text", text: content }] : [];
|
|
@@ -2788,17 +3656,23 @@ function toAnthropicContent(content) {
|
|
|
2788
3656
|
if (!raw || typeof raw !== "object") continue;
|
|
2789
3657
|
const part = raw;
|
|
2790
3658
|
if ((part.type === "text" || part.type === "input_text") && typeof part.text === "string") {
|
|
2791
|
-
if (part.text.length > 0)
|
|
3659
|
+
if (part.text.length > 0) {
|
|
3660
|
+
const block2 = { type: "text", text: part.text };
|
|
3661
|
+
if (isCacheControl(part.cache_control)) block2.cache_control = part.cache_control;
|
|
3662
|
+
blocks.push(block2);
|
|
3663
|
+
}
|
|
2792
3664
|
continue;
|
|
2793
3665
|
}
|
|
2794
3666
|
if (part.type !== "image_url") continue;
|
|
2795
3667
|
const imageUrl = typeof part.image_url === "string" ? part.image_url : stringValue(part.image_url?.url);
|
|
2796
3668
|
if (!imageUrl) continue;
|
|
2797
3669
|
const dataMatch = imageUrl.match(/^data:([^;,]+);base64,(.+)$/s);
|
|
2798
|
-
|
|
3670
|
+
const block = {
|
|
2799
3671
|
type: "image",
|
|
2800
3672
|
source: dataMatch ? { type: "base64", media_type: dataMatch[1], data: dataMatch[2] } : { type: "url", url: imageUrl }
|
|
2801
|
-
}
|
|
3673
|
+
};
|
|
3674
|
+
if (isCacheControl(part.cache_control)) block.cache_control = part.cache_control;
|
|
3675
|
+
blocks.push(block);
|
|
2802
3676
|
}
|
|
2803
3677
|
return blocks;
|
|
2804
3678
|
}
|
|
@@ -2832,7 +3706,15 @@ function buildAnthropicMessagesBody(args) {
|
|
|
2832
3706
|
const message = raw;
|
|
2833
3707
|
const role = String(message.role ?? "");
|
|
2834
3708
|
if (role === "system" || role === "developer") {
|
|
2835
|
-
|
|
3709
|
+
const stablePrefixChars = Number(message.stable_prefix_chars);
|
|
3710
|
+
if (typeof message.content === "string" && Number.isFinite(stablePrefixChars) && stablePrefixChars > 0 && stablePrefixChars <= message.content.length) {
|
|
3711
|
+
const stable = message.content.slice(0, stablePrefixChars);
|
|
3712
|
+
const dynamic = message.content.slice(stablePrefixChars);
|
|
3713
|
+
system.push({ type: "text", text: stable, cache_control: { type: "ephemeral" } });
|
|
3714
|
+
if (dynamic) system.push({ type: "text", text: dynamic });
|
|
3715
|
+
} else {
|
|
3716
|
+
system.push(...toAnthropicContent(message.content));
|
|
3717
|
+
}
|
|
2836
3718
|
continue;
|
|
2837
3719
|
}
|
|
2838
3720
|
if (role === "tool") {
|
|
@@ -2874,6 +3756,9 @@ function buildAnthropicMessagesBody(args) {
|
|
|
2874
3756
|
if (!hasClaudeCodeIdentity(system)) {
|
|
2875
3757
|
system.unshift({ type: "text", text: CLAUDE_CODE_SYSTEM_INSTRUCTION });
|
|
2876
3758
|
}
|
|
3759
|
+
if (system.length > 0 && !system.some((block) => isCacheControl(block.cache_control))) {
|
|
3760
|
+
system[system.length - 1].cache_control = { type: "ephemeral" };
|
|
3761
|
+
}
|
|
2877
3762
|
const tools = Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools.flatMap((raw) => {
|
|
2878
3763
|
if (!raw || typeof raw !== "object") return [];
|
|
2879
3764
|
const fn = raw.function;
|
|
@@ -2888,14 +3773,39 @@ function buildAnthropicMessagesBody(args) {
|
|
|
2888
3773
|
const model = stringValue(args.openAiBody.model) ?? args.agentConfig.model ?? "claude-sonnet-5";
|
|
2889
3774
|
const maxTokensRaw = args.openAiBody.max_completion_tokens ?? args.openAiBody.max_tokens ?? args.agentConfig.max_tokens;
|
|
2890
3775
|
const maxTokens = typeof maxTokensRaw === "number" && Number.isFinite(maxTokensRaw) ? Math.max(1, Math.floor(maxTokensRaw)) : 8192;
|
|
3776
|
+
const reasoningEffort = stringValue(args.openAiBody.reasoning_effort) ?? stringValue(args.agentConfig.reasoning_effort);
|
|
3777
|
+
const spec = resolveThinkingSpec({
|
|
3778
|
+
model,
|
|
3779
|
+
reasoningEffort,
|
|
3780
|
+
maxTokens,
|
|
3781
|
+
temperature: typeof args.openAiBody.temperature === "number" ? args.openAiBody.temperature : args.agentConfig.temperature,
|
|
3782
|
+
injectedThinking: args.openAiBody.thinking,
|
|
3783
|
+
enableThinking: args.agentConfig.enableThinking,
|
|
3784
|
+
thinkingBudget: args.agentConfig.thinkingBudget
|
|
3785
|
+
});
|
|
3786
|
+
const { thinkingBlock, outputConfig } = spec;
|
|
3787
|
+
const finalMaxTokens = spec.maxTokens;
|
|
3788
|
+
const finalTemperature = spec.temperature;
|
|
3789
|
+
if (messages.length > 0) {
|
|
3790
|
+
const lastMessage = messages[messages.length - 1];
|
|
3791
|
+
const content = Array.isArray(lastMessage.content) ? lastMessage.content : [];
|
|
3792
|
+
if (content.length > 0) {
|
|
3793
|
+
const lastBlock = content[content.length - 1];
|
|
3794
|
+
if (!isCacheControl(lastBlock.cache_control)) {
|
|
3795
|
+
lastBlock.cache_control = { type: "ephemeral" };
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
2891
3799
|
return {
|
|
2892
3800
|
model,
|
|
2893
3801
|
messages,
|
|
2894
|
-
max_tokens:
|
|
3802
|
+
max_tokens: finalMaxTokens,
|
|
2895
3803
|
stream: false,
|
|
3804
|
+
...thinkingBlock ? { thinking: thinkingBlock } : {},
|
|
3805
|
+
...outputConfig ? { output_config: outputConfig } : {},
|
|
2896
3806
|
...system.length > 0 ? { system } : {},
|
|
2897
3807
|
...tools.length > 0 ? { tools } : {},
|
|
2898
|
-
...typeof
|
|
3808
|
+
...typeof finalTemperature === "number" ? { temperature: finalTemperature } : {},
|
|
2899
3809
|
...typeof args.openAiBody.top_p === "number" ? { top_p: args.openAiBody.top_p } : {}
|
|
2900
3810
|
};
|
|
2901
3811
|
}
|
|
@@ -2919,6 +3829,8 @@ function mapAnthropicMessageToOpenAi(payload) {
|
|
|
2919
3829
|
}
|
|
2920
3830
|
const usage = payload.usage ?? {};
|
|
2921
3831
|
const inputTokens = (typeof usage.input_tokens === "number" ? usage.input_tokens : 0) + (typeof usage.cache_creation_input_tokens === "number" ? usage.cache_creation_input_tokens : 0) + (typeof usage.cache_read_input_tokens === "number" ? usage.cache_read_input_tokens : 0);
|
|
3832
|
+
const cacheCreationInputTokens = typeof usage.cache_creation_input_tokens === "number" ? usage.cache_creation_input_tokens : 0;
|
|
3833
|
+
const cacheReadInputTokens = typeof usage.cache_read_input_tokens === "number" ? usage.cache_read_input_tokens : 0;
|
|
2922
3834
|
const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : 0;
|
|
2923
3835
|
const stopReason = String(payload.stop_reason ?? "");
|
|
2924
3836
|
const message = { role: "assistant", content: text || null };
|
|
@@ -2934,9 +3846,16 @@ function mapAnthropicMessageToOpenAi(payload) {
|
|
|
2934
3846
|
finish_reason: toolCalls.length > 0 || stopReason === "tool_use" ? "tool_calls" : stopReason === "max_tokens" ? "length" : "stop"
|
|
2935
3847
|
}],
|
|
2936
3848
|
usage: {
|
|
3849
|
+
// prompt_tokens/input_tokens are total input, including cache read/write.
|
|
3850
|
+
// Preserve Anthropic's components so normalization and billing can apply
|
|
3851
|
+
// the correct cache prices without double-counting them.
|
|
2937
3852
|
prompt_tokens: inputTokens,
|
|
3853
|
+
input_tokens: inputTokens,
|
|
2938
3854
|
completion_tokens: outputTokens,
|
|
2939
|
-
|
|
3855
|
+
output_tokens: outputTokens,
|
|
3856
|
+
total_tokens: inputTokens + outputTokens,
|
|
3857
|
+
cache_creation_input_tokens: cacheCreationInputTokens,
|
|
3858
|
+
cache_read_input_tokens: cacheReadInputTokens
|
|
2940
3859
|
}
|
|
2941
3860
|
};
|
|
2942
3861
|
}
|
|
@@ -9011,6 +9930,262 @@ function isCursorOAuthAgent(agent) {
|
|
|
9011
9930
|
return agent.apiKeyRef?.trim().toLowerCase() === "cursor";
|
|
9012
9931
|
}
|
|
9013
9932
|
|
|
9933
|
+
// packages/agent-runtime/codexResponsesProvider.ts
|
|
9934
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
9935
|
+
var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
9936
|
+
var CODEX_CLIENT_VERSION = "0.144.1";
|
|
9937
|
+
var CODEX_ORIGINATOR = "codex_cli_rs";
|
|
9938
|
+
var CODEX_OPENAI_BETA = "responses=experimental";
|
|
9939
|
+
var OPENAI_AUTH_CLAIM = "https://api.openai.com/auth";
|
|
9940
|
+
var CODEX_INSTALLATION_ID = randomUUID4();
|
|
9941
|
+
function decodeCodexAccountId(accessToken) {
|
|
9942
|
+
const parts = accessToken.split(".");
|
|
9943
|
+
if (parts.length < 2) return void 0;
|
|
9944
|
+
try {
|
|
9945
|
+
const payload = JSON.parse(
|
|
9946
|
+
Buffer.from(parts[1], "base64").toString("utf8")
|
|
9947
|
+
);
|
|
9948
|
+
const claim = payload[OPENAI_AUTH_CLAIM];
|
|
9949
|
+
const value = claim && typeof claim === "object" ? claim.chatgpt_account_id : void 0;
|
|
9950
|
+
return typeof value === "string" && value ? value : void 0;
|
|
9951
|
+
} catch {
|
|
9952
|
+
return void 0;
|
|
9953
|
+
}
|
|
9954
|
+
}
|
|
9955
|
+
function createCodexRequestIdentity(installationId = CODEX_INSTALLATION_ID) {
|
|
9956
|
+
const sessionId = randomUUID4();
|
|
9957
|
+
const threadId = randomUUID4();
|
|
9958
|
+
const windowId = randomUUID4();
|
|
9959
|
+
const turnId = randomUUID4();
|
|
9960
|
+
const turnMetadata = {
|
|
9961
|
+
installation_id: installationId,
|
|
9962
|
+
session_id: sessionId,
|
|
9963
|
+
thread_id: threadId,
|
|
9964
|
+
turn_id: turnId,
|
|
9965
|
+
window_id: windowId,
|
|
9966
|
+
request_kind: "turn",
|
|
9967
|
+
turn_started_at_unix_ms: Date.now()
|
|
9968
|
+
};
|
|
9969
|
+
const turnMetadataJson = JSON.stringify(turnMetadata);
|
|
9970
|
+
return {
|
|
9971
|
+
sessionId,
|
|
9972
|
+
threadId,
|
|
9973
|
+
windowId,
|
|
9974
|
+
turnId,
|
|
9975
|
+
turnMetadataJson,
|
|
9976
|
+
clientMetadata: {
|
|
9977
|
+
"x-codex-installation-id": installationId,
|
|
9978
|
+
session_id: sessionId,
|
|
9979
|
+
thread_id: threadId,
|
|
9980
|
+
"x-codex-window-id": windowId,
|
|
9981
|
+
turn_id: turnId,
|
|
9982
|
+
"x-codex-turn-metadata": turnMetadataJson
|
|
9983
|
+
}
|
|
9984
|
+
};
|
|
9985
|
+
}
|
|
9986
|
+
function buildCodexCompatibilityHeaders(identity, accountId) {
|
|
9987
|
+
return {
|
|
9988
|
+
Authorization: "",
|
|
9989
|
+
// filled by caller with bearer token
|
|
9990
|
+
"Content-Type": "application/json",
|
|
9991
|
+
Accept: "text/event-stream",
|
|
9992
|
+
"chatgpt-account-id": accountId,
|
|
9993
|
+
"OpenAI-Beta": CODEX_OPENAI_BETA,
|
|
9994
|
+
originator: CODEX_ORIGINATOR,
|
|
9995
|
+
version: CODEX_CLIENT_VERSION,
|
|
9996
|
+
session_id: identity.sessionId,
|
|
9997
|
+
conversation_id: identity.sessionId,
|
|
9998
|
+
"x-client-request-id": identity.sessionId,
|
|
9999
|
+
"session-id": identity.sessionId,
|
|
10000
|
+
"thread-id": identity.threadId,
|
|
10001
|
+
"x-codex-window-id": identity.windowId,
|
|
10002
|
+
"x-codex-turn-metadata": identity.turnMetadataJson
|
|
10003
|
+
};
|
|
10004
|
+
}
|
|
10005
|
+
function collectInstructions(messages, agentPrompt) {
|
|
10006
|
+
const systemTexts = [];
|
|
10007
|
+
const prompt = agentPrompt?.trim();
|
|
10008
|
+
if (prompt) systemTexts.push(prompt);
|
|
10009
|
+
for (const raw of messages) {
|
|
10010
|
+
if (!raw || typeof raw !== "object") continue;
|
|
10011
|
+
const role = String(raw.role ?? "");
|
|
10012
|
+
if (role !== "system" && role !== "developer") continue;
|
|
10013
|
+
const content = raw.content;
|
|
10014
|
+
const stringContent = asOptionalTrimmedString(content);
|
|
10015
|
+
if (stringContent) {
|
|
10016
|
+
systemTexts.push(stringContent);
|
|
10017
|
+
} else if (Array.isArray(content)) {
|
|
10018
|
+
const text = content.filter(
|
|
10019
|
+
(p) => !!p && p.type === "text"
|
|
10020
|
+
).map((p) => p.text).join("\n").trim();
|
|
10021
|
+
if (text) systemTexts.push(text);
|
|
10022
|
+
}
|
|
10023
|
+
}
|
|
10024
|
+
return systemTexts.join("\n\n");
|
|
10025
|
+
}
|
|
10026
|
+
function collectStableInstructions(messages, fallbackPrompt) {
|
|
10027
|
+
const systemTexts = [];
|
|
10028
|
+
if (fallbackPrompt?.trim()) systemTexts.push(fallbackPrompt.trim());
|
|
10029
|
+
for (const raw of messages) {
|
|
10030
|
+
if (!raw || typeof raw !== "object") continue;
|
|
10031
|
+
const message = raw;
|
|
10032
|
+
const role = String(message.role ?? "");
|
|
10033
|
+
if (role !== "system" && role !== "developer") continue;
|
|
10034
|
+
if (typeof message.content === "string") {
|
|
10035
|
+
const boundary = Number(message.stable_prefix_chars);
|
|
10036
|
+
const text = Number.isFinite(boundary) && boundary > 0 ? message.content.slice(0, boundary) : message.content;
|
|
10037
|
+
if (text.trim()) systemTexts.push(text.trim());
|
|
10038
|
+
}
|
|
10039
|
+
}
|
|
10040
|
+
return systemTexts.join("\n\n");
|
|
10041
|
+
}
|
|
10042
|
+
function stablePromptCacheKey(parts) {
|
|
10043
|
+
const value = JSON.stringify(parts);
|
|
10044
|
+
let hash = 2166136261;
|
|
10045
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
10046
|
+
hash ^= value.charCodeAt(index);
|
|
10047
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
10048
|
+
}
|
|
10049
|
+
return `nolo-codex-${hash.toString(16).padStart(8, "0")}`;
|
|
10050
|
+
}
|
|
10051
|
+
function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
|
|
10052
|
+
const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
|
|
10053
|
+
const nonSystem = rawMessages.filter((m) => {
|
|
10054
|
+
const role = m && typeof m === "object" ? String(m.role) : "";
|
|
10055
|
+
return role !== "system" && role !== "developer";
|
|
10056
|
+
});
|
|
10057
|
+
const input = convertMessagesToResponsesInput(nonSystem);
|
|
10058
|
+
const instructions = collectInstructions(rawMessages, args.agentConfig.prompt);
|
|
10059
|
+
const stableInstructions = collectStableInstructions(rawMessages, args.agentConfig.prompt);
|
|
10060
|
+
const model = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gpt-5.5";
|
|
10061
|
+
const tools = toResponsesTools(
|
|
10062
|
+
Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
|
|
10063
|
+
);
|
|
10064
|
+
const body = {
|
|
10065
|
+
model,
|
|
10066
|
+
input,
|
|
10067
|
+
stream: true,
|
|
10068
|
+
store: false,
|
|
10069
|
+
// Keep routing stable across turns and request UUIDs. Growing input/history
|
|
10070
|
+
// is intentionally excluded; only stable request-prefix material belongs.
|
|
10071
|
+
prompt_cache_key: stablePromptCacheKey([model, stableInstructions, tools ?? []]),
|
|
10072
|
+
client_metadata: identity.clientMetadata
|
|
10073
|
+
};
|
|
10074
|
+
if (instructions) body.instructions = instructions;
|
|
10075
|
+
if (tools && tools.length > 0) {
|
|
10076
|
+
body.tools = tools;
|
|
10077
|
+
body.tool_choice = "auto";
|
|
10078
|
+
body.parallel_tool_calls = true;
|
|
10079
|
+
}
|
|
10080
|
+
return body;
|
|
10081
|
+
}
|
|
10082
|
+
function aggregateResponsesStream(events) {
|
|
10083
|
+
let text = "";
|
|
10084
|
+
const toolCalls = [];
|
|
10085
|
+
let usage;
|
|
10086
|
+
for (const ev of events) {
|
|
10087
|
+
const type = String(ev.type ?? "");
|
|
10088
|
+
if (type === "response.output_text.delta" && typeof ev.delta === "string") {
|
|
10089
|
+
text += ev.delta;
|
|
10090
|
+
continue;
|
|
10091
|
+
}
|
|
10092
|
+
if (type === "response.output_item.done") {
|
|
10093
|
+
const item = ev.item;
|
|
10094
|
+
if (item && item.type === "function_call") {
|
|
10095
|
+
const name = typeof item.name === "string" ? item.name : "";
|
|
10096
|
+
if (name) {
|
|
10097
|
+
toolCalls.push({
|
|
10098
|
+
id: typeof item.call_id === "string" && item.call_id ? item.call_id : `${name}_${toolCalls.length}`,
|
|
10099
|
+
type: "function",
|
|
10100
|
+
function: {
|
|
10101
|
+
name,
|
|
10102
|
+
arguments: typeof item.arguments === "string" ? item.arguments : "{}"
|
|
10103
|
+
}
|
|
10104
|
+
});
|
|
10105
|
+
}
|
|
10106
|
+
}
|
|
10107
|
+
continue;
|
|
10108
|
+
}
|
|
10109
|
+
if (type === "response.completed") {
|
|
10110
|
+
const response = ev.response;
|
|
10111
|
+
const u = response?.usage;
|
|
10112
|
+
if (u) {
|
|
10113
|
+
const prompt = typeof u.input_tokens === "number" ? u.input_tokens : 0;
|
|
10114
|
+
const completion = typeof u.output_tokens === "number" ? u.output_tokens : 0;
|
|
10115
|
+
const total = typeof u.total_tokens === "number" ? u.total_tokens : prompt + completion;
|
|
10116
|
+
usage = {
|
|
10117
|
+
prompt_tokens: prompt,
|
|
10118
|
+
completion_tokens: completion,
|
|
10119
|
+
total_tokens: total
|
|
10120
|
+
};
|
|
10121
|
+
}
|
|
10122
|
+
}
|
|
10123
|
+
}
|
|
10124
|
+
return { text, toolCalls, usage };
|
|
10125
|
+
}
|
|
10126
|
+
async function readSseEvents(response) {
|
|
10127
|
+
return readSseDataValues(response, (line) => {
|
|
10128
|
+
const ev = parseSseDataLineObject(line);
|
|
10129
|
+
return ev && !Array.isArray(ev) ? ev : null;
|
|
10130
|
+
});
|
|
10131
|
+
}
|
|
10132
|
+
async function fetchCodexResponsesCompletion(args) {
|
|
10133
|
+
const fetchImpl = args.fetchImpl ?? fetch;
|
|
10134
|
+
const accountId = args.accountId?.trim() || decodeCodexAccountId(args.accessToken);
|
|
10135
|
+
if (!accountId) {
|
|
10136
|
+
return {
|
|
10137
|
+
status: 401,
|
|
10138
|
+
body: {
|
|
10139
|
+
error: {
|
|
10140
|
+
message: "ChatGPT Codex credential is missing chatgpt_account_id. Re-run `nolo auth chatgpt`."
|
|
10141
|
+
}
|
|
10142
|
+
}
|
|
10143
|
+
};
|
|
10144
|
+
}
|
|
10145
|
+
const identity = createCodexRequestIdentity();
|
|
10146
|
+
const body = buildCodexRequestBody(args, identity);
|
|
10147
|
+
const headers = buildCodexCompatibilityHeaders(identity, accountId);
|
|
10148
|
+
headers.Authorization = `Bearer ${args.accessToken}`;
|
|
10149
|
+
const response = await fetchImpl(CODEX_RESPONSES_URL, {
|
|
10150
|
+
method: "POST",
|
|
10151
|
+
headers,
|
|
10152
|
+
body: JSON.stringify(body),
|
|
10153
|
+
signal: args.signal
|
|
10154
|
+
});
|
|
10155
|
+
if (!response.ok) {
|
|
10156
|
+
const errorText = await response.text();
|
|
10157
|
+
return {
|
|
10158
|
+
status: response.status,
|
|
10159
|
+
body: { error: { message: errorText || response.statusText } }
|
|
10160
|
+
};
|
|
10161
|
+
}
|
|
10162
|
+
const events = await readSseEvents(response);
|
|
10163
|
+
const { text, toolCalls, usage } = aggregateResponsesStream(events);
|
|
10164
|
+
const message = {
|
|
10165
|
+
role: "assistant",
|
|
10166
|
+
content: text || null
|
|
10167
|
+
};
|
|
10168
|
+
if (toolCalls.length > 0) message.tool_calls = toolCalls;
|
|
10169
|
+
return {
|
|
10170
|
+
status: 200,
|
|
10171
|
+
body: {
|
|
10172
|
+
choices: [
|
|
10173
|
+
{
|
|
10174
|
+
index: 0,
|
|
10175
|
+
message,
|
|
10176
|
+
finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop"
|
|
10177
|
+
}
|
|
10178
|
+
],
|
|
10179
|
+
...usage ? { usage } : {}
|
|
10180
|
+
}
|
|
10181
|
+
};
|
|
10182
|
+
}
|
|
10183
|
+
function isCodexOAuthAgent(agentConfig) {
|
|
10184
|
+
if (!agentConfig) return false;
|
|
10185
|
+
const apiKeyRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
|
|
10186
|
+
return apiKeyRef === "chatgpt";
|
|
10187
|
+
}
|
|
10188
|
+
|
|
9014
10189
|
// packages/agent-runtime/oauthProviders.ts
|
|
9015
10190
|
var XAI_ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
|
|
9016
10191
|
var decodeBase64 = (s) => Buffer.from(s, "base64").toString("utf8");
|
|
@@ -9504,7 +10679,7 @@ function buildOpenAiTools(args) {
|
|
|
9504
10679
|
const toolset = buildLocalWorkspaceToolsetForEnv(args);
|
|
9505
10680
|
const toolNameSet = new Set(args.toolNames ?? []);
|
|
9506
10681
|
const callAgentTools = toolNameSet.has("callAgent") ? prepareTools(["callAgent"]) : [];
|
|
9507
|
-
const uiAskChoiceTools = toolNameSet.has("
|
|
10682
|
+
const uiAskChoiceTools = toolNameSet.has("ask_user") ? prepareTools(["ask_user"]) : [];
|
|
9508
10683
|
const readPastedTextTools = toolNameSet.has("readPastedText") ? [
|
|
9509
10684
|
{
|
|
9510
10685
|
type: "function",
|
|
@@ -9564,10 +10739,10 @@ function buildOpenAiTools(args) {
|
|
|
9564
10739
|
var CLI_DEFAULT_TOOLS = ["exa_search", "fetchWebpage"];
|
|
9565
10740
|
function addDefaultCliCoreTools(toolNames, env, options) {
|
|
9566
10741
|
const declaredOnly = env && shouldUseDeclaredOnlyLocalWorkspaceTools(env);
|
|
9567
|
-
const forcedTools = options?.hasUserChoice === true ? FORCED_TOOLS : FORCED_TOOLS.filter((name) => name !== "
|
|
10742
|
+
const forcedTools = options?.hasUserChoice === true ? FORCED_TOOLS : FORCED_TOOLS.filter((name) => name !== "ask_user");
|
|
9568
10743
|
const injected = declaredOnly ? [...forcedTools] : [...forcedTools, ...CLI_DEFAULT_TOOLS];
|
|
9569
10744
|
const combined = [...toolNames, ...injected];
|
|
9570
|
-
const filtered = options?.hasUserChoice === true ? combined : combined.filter((name) => name !== "
|
|
10745
|
+
const filtered = options?.hasUserChoice === true ? combined : combined.filter((name) => name !== "ask_user");
|
|
9571
10746
|
return [...new Set(filtered)];
|
|
9572
10747
|
}
|
|
9573
10748
|
function resolveCliEffectiveEnabledPacks(args) {
|
|
@@ -9860,9 +11035,9 @@ function createCliCallAgentToolExecutor(deps, ctx) {
|
|
|
9860
11035
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
9861
11036
|
var currentMetaFile = fileURLToPath(import.meta.url);
|
|
9862
11037
|
var isJsBundle = extname(currentMetaFile) === ".js";
|
|
9863
|
-
var SOURCE_CLI_DIR = isJsBundle ?
|
|
9864
|
-
var CLI_DIR = isCompiledBinary() ?
|
|
9865
|
-
var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile :
|
|
11038
|
+
var SOURCE_CLI_DIR = isJsBundle ? dirname2(currentMetaFile) : dirname2(dirname2(currentMetaFile));
|
|
11039
|
+
var CLI_DIR = isCompiledBinary() ? dirname2(process.execPath) : SOURCE_CLI_DIR;
|
|
11040
|
+
var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join2(SOURCE_CLI_DIR, "index.ts");
|
|
9866
11041
|
function createCliLocalRuntimeAdapter(deps) {
|
|
9867
11042
|
const now = deps.now ?? Date.now;
|
|
9868
11043
|
const createId = deps.createId ?? createFallbackId;
|
|
@@ -10208,6 +11383,74 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10208
11383
|
}
|
|
10209
11384
|
};
|
|
10210
11385
|
}
|
|
11386
|
+
if (isCodexOAuthAgent(agentConfig)) {
|
|
11387
|
+
const accessToken = await apiKeyRefResolver("chatgpt");
|
|
11388
|
+
if (!accessToken) {
|
|
11389
|
+
throw new Error(
|
|
11390
|
+
'OAuth credential for "chatgpt" not found locally. Run `nolo auth chatgpt`.'
|
|
11391
|
+
);
|
|
11392
|
+
}
|
|
11393
|
+
const credential = readOAuthCredential("chatgpt");
|
|
11394
|
+
const accountId = credential?.accountId;
|
|
11395
|
+
const { requestedToolNames: requestedToolNames2, tools: tools2 } = resolveProviderOpenAiToolBundle(
|
|
11396
|
+
agentConfig,
|
|
11397
|
+
deps.env,
|
|
11398
|
+
buildProviderOpenAiTools,
|
|
11399
|
+
additionalToolNames,
|
|
11400
|
+
{ hasUserChoice: Boolean(deps.requestUserChoice) }
|
|
11401
|
+
);
|
|
11402
|
+
logLocalRuntimeDiagnostic("provider.selected", {
|
|
11403
|
+
agentKey: agentConfig.key,
|
|
11404
|
+
transport: "codex-responses",
|
|
11405
|
+
provider: "openai",
|
|
11406
|
+
model: agentConfig.model ?? "gpt-5.6-sol",
|
|
11407
|
+
hasApiKey: true
|
|
11408
|
+
});
|
|
11409
|
+
return {
|
|
11410
|
+
model: agentConfig.model || "gpt-5.6-sol",
|
|
11411
|
+
complete: async (messages, options) => {
|
|
11412
|
+
const result = await fetchCodexResponsesCompletion({
|
|
11413
|
+
agentConfig,
|
|
11414
|
+
accessToken,
|
|
11415
|
+
...accountId ? { accountId } : {},
|
|
11416
|
+
openAiBody: {
|
|
11417
|
+
model: agentConfig.model || "gpt-5.6-sol",
|
|
11418
|
+
messages,
|
|
11419
|
+
stream: false,
|
|
11420
|
+
...tools2.length > 0 ? { tools: tools2 } : {}
|
|
11421
|
+
},
|
|
11422
|
+
fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
|
|
11423
|
+
sleep: deps.sleep,
|
|
11424
|
+
loopbackRequest
|
|
11425
|
+
})
|
|
11426
|
+
});
|
|
11427
|
+
if (result.status < 200 || result.status >= 300) {
|
|
11428
|
+
const errMsg = result.body?.error && typeof result.body.error === "object" && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
|
|
11429
|
+
throw new Error(
|
|
11430
|
+
`local Codex OAuth provider failed: HTTP ${result.status} ${errMsg}`
|
|
11431
|
+
);
|
|
11432
|
+
}
|
|
11433
|
+
const choice = Array.isArray(result.body.choices) ? result.body.choices[0] : void 0;
|
|
11434
|
+
const message = choice?.message ?? {};
|
|
11435
|
+
const content = typeof message.content === "string" ? message.content : "";
|
|
11436
|
+
const tool_calls = Array.isArray(message.tool_calls) ? message.tool_calls : void 0;
|
|
11437
|
+
if (content && options?.onTextDelta) options.onTextDelta(content);
|
|
11438
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
11439
|
+
agentKey: agentConfig.key,
|
|
11440
|
+
transport: "codex-responses",
|
|
11441
|
+
ok: true,
|
|
11442
|
+
contentChars: content.length,
|
|
11443
|
+
toolCallCount: tool_calls?.length ?? 0,
|
|
11444
|
+
requestedToolNames: requestedToolNames2
|
|
11445
|
+
});
|
|
11446
|
+
return {
|
|
11447
|
+
content,
|
|
11448
|
+
...tool_calls ? { tool_calls } : {},
|
|
11449
|
+
trace: messages
|
|
11450
|
+
};
|
|
11451
|
+
}
|
|
11452
|
+
};
|
|
11453
|
+
}
|
|
10211
11454
|
if (isCursorOAuthAgent(agentConfig)) {
|
|
10212
11455
|
const accessToken = await apiKeyRefResolver("cursor");
|
|
10213
11456
|
if (!accessToken) {
|
|
@@ -10277,6 +11520,101 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10277
11520
|
}
|
|
10278
11521
|
};
|
|
10279
11522
|
}
|
|
11523
|
+
if (shouldUsePlatformChatProvider(deps.env, agentConfig) && isGemini3Model(agentConfig.model ?? "") && agentConfig.provider === "google") {
|
|
11524
|
+
const providerConfig2 = await resolvePlatformChatProviderConfig({
|
|
11525
|
+
agentConfig,
|
|
11526
|
+
env: deps.env,
|
|
11527
|
+
apiKeyRefResolver,
|
|
11528
|
+
credentialBroker,
|
|
11529
|
+
syncFetcher
|
|
11530
|
+
});
|
|
11531
|
+
const { requestedToolNames: requestedToolNames2, tools: tools2 } = resolveProviderOpenAiToolBundle(
|
|
11532
|
+
agentConfig,
|
|
11533
|
+
deps.env,
|
|
11534
|
+
buildProviderOpenAiTools,
|
|
11535
|
+
additionalToolNames,
|
|
11536
|
+
{ hasUserChoice: Boolean(deps.requestUserChoice) }
|
|
11537
|
+
);
|
|
11538
|
+
if (tools2.length > 0 && providerConfig2.apiKey && shouldUseGeminiNativeToolRoute(
|
|
11539
|
+
agentConfig.provider ?? "",
|
|
11540
|
+
agentConfig.model ?? "",
|
|
11541
|
+
tools2,
|
|
11542
|
+
() => false
|
|
11543
|
+
// CLI 端不区分 image 模型
|
|
11544
|
+
)) {
|
|
11545
|
+
logLocalRuntimeDiagnostic("provider.selected", {
|
|
11546
|
+
agentKey: agentConfig.key,
|
|
11547
|
+
transport: "gemini-native-tool",
|
|
11548
|
+
apiSource: agentConfig.apiSource ?? null,
|
|
11549
|
+
provider: providerConfig2.provider,
|
|
11550
|
+
model: providerConfig2.model,
|
|
11551
|
+
hasApiKey: Boolean(providerConfig2.apiKey)
|
|
11552
|
+
});
|
|
11553
|
+
return {
|
|
11554
|
+
model: providerConfig2.model,
|
|
11555
|
+
complete: async (messages, options) => {
|
|
11556
|
+
const requestBody = buildGeminiGenerateContentRequest({
|
|
11557
|
+
messages,
|
|
11558
|
+
tools: tools2,
|
|
11559
|
+
maxTokens: typeof agentConfig.max_tokens === "number" ? agentConfig.max_tokens : void 0,
|
|
11560
|
+
temperature: typeof agentConfig.temperature === "number" ? agentConfig.temperature : void 0,
|
|
11561
|
+
attachSkipThoughtSignature: true
|
|
11562
|
+
});
|
|
11563
|
+
const model = providerConfig2.model;
|
|
11564
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse`;
|
|
11565
|
+
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
11566
|
+
agentKey: agentConfig.key,
|
|
11567
|
+
transport: "gemini-native-tool",
|
|
11568
|
+
model,
|
|
11569
|
+
messageCount: messages.length,
|
|
11570
|
+
toolCount: tools2.length,
|
|
11571
|
+
requestedToolNames: requestedToolNames2
|
|
11572
|
+
});
|
|
11573
|
+
const res = await fetchImpl(url, {
|
|
11574
|
+
method: "POST",
|
|
11575
|
+
headers: {
|
|
11576
|
+
"Content-Type": "application/json",
|
|
11577
|
+
"x-goog-api-key": providerConfig2.apiKey ?? ""
|
|
11578
|
+
},
|
|
11579
|
+
body: JSON.stringify(requestBody),
|
|
11580
|
+
signal: AbortSignal.timeout(12e4)
|
|
11581
|
+
});
|
|
11582
|
+
if (!res.ok) {
|
|
11583
|
+
const errText = await res.text();
|
|
11584
|
+
logLocalRuntimeDiagnostic("provider.request.failed", {
|
|
11585
|
+
agentKey: agentConfig.key,
|
|
11586
|
+
transport: "gemini-native-tool",
|
|
11587
|
+
status: res.status,
|
|
11588
|
+
error: errText.slice(0, 200)
|
|
11589
|
+
});
|
|
11590
|
+
throw new Error(
|
|
11591
|
+
`gemini native tool provider failed: HTTP ${res.status} ${errText.slice(0, 500)}`
|
|
11592
|
+
);
|
|
11593
|
+
}
|
|
11594
|
+
const chunks = await readSseDataValues(res, parseSseDataLineJson);
|
|
11595
|
+
const { text, toolCalls, usage } = accumulateGeminiChunks(chunks);
|
|
11596
|
+
if (text && options?.onTextDelta) {
|
|
11597
|
+
options.onTextDelta(text);
|
|
11598
|
+
}
|
|
11599
|
+
const result = {
|
|
11600
|
+
content: text,
|
|
11601
|
+
model,
|
|
11602
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
11603
|
+
...usage ? { usage } : {},
|
|
11604
|
+
trace: messages
|
|
11605
|
+
};
|
|
11606
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
11607
|
+
agentKey: agentConfig.key,
|
|
11608
|
+
transport: "gemini-native-tool",
|
|
11609
|
+
ok: true,
|
|
11610
|
+
contentChars: text.length,
|
|
11611
|
+
toolCallCount: toolCalls.length
|
|
11612
|
+
});
|
|
11613
|
+
return result;
|
|
11614
|
+
}
|
|
11615
|
+
};
|
|
11616
|
+
}
|
|
11617
|
+
}
|
|
10280
11618
|
if (shouldUsePlatformChatProvider(deps.env, agentConfig)) {
|
|
10281
11619
|
const providerConfig2 = await resolvePlatformChatProviderConfig({
|
|
10282
11620
|
agentConfig,
|
|
@@ -10337,7 +11675,16 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10337
11675
|
},
|
|
10338
11676
|
{
|
|
10339
11677
|
sleep: deps.sleep,
|
|
10340
|
-
loopbackRequest
|
|
11678
|
+
loopbackRequest,
|
|
11679
|
+
// auto 档位转发 nolo.chat 时,网关层 502(server: Caddy、空 body)
|
|
11680
|
+
// 意味着请求根本没到 Bun 上游,provider 未受理,重试安全。
|
|
11681
|
+
// 与 429/503 同口径:不会重复计费/重复生成。
|
|
11682
|
+
retryableStatuses: /* @__PURE__ */ new Set([429, 502, 503]),
|
|
11683
|
+
onRetry: deps.activityReporter ? ({ attempt, maxAttempts, delayMs }) => {
|
|
11684
|
+
deps.activityReporter(
|
|
11685
|
+
`\u81EA\u52A8\u91CD\u8BD5 ${attempt}/${maxAttempts} \xB7 ${Math.ceil(delayMs / 1e3)}s`
|
|
11686
|
+
);
|
|
11687
|
+
} : void 0
|
|
10341
11688
|
}
|
|
10342
11689
|
);
|
|
10343
11690
|
if (!res.ok) {
|
|
@@ -10493,6 +11840,23 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10493
11840
|
};
|
|
10494
11841
|
},
|
|
10495
11842
|
executeTool: async (call, opts) => {
|
|
11843
|
+
const contextualCall = opts?.runtimeContext ? { ...call, runtimeContext: opts.runtimeContext } : call;
|
|
11844
|
+
let injectedCall = contextualCall;
|
|
11845
|
+
if (contextualCall.name === "startAgentRun" && deps.parentDialogId && typeof contextualCall.arguments === "string") {
|
|
11846
|
+
try {
|
|
11847
|
+
const args = JSON.parse(contextualCall.arguments);
|
|
11848
|
+
if (!args.parentDialogId) {
|
|
11849
|
+
injectedCall = {
|
|
11850
|
+
...contextualCall,
|
|
11851
|
+
arguments: JSON.stringify({
|
|
11852
|
+
...args,
|
|
11853
|
+
parentDialogId: deps.parentDialogId
|
|
11854
|
+
})
|
|
11855
|
+
};
|
|
11856
|
+
}
|
|
11857
|
+
} catch {
|
|
11858
|
+
}
|
|
11859
|
+
}
|
|
10496
11860
|
assertWithinLocalToolBudget({
|
|
10497
11861
|
toolName: call.name,
|
|
10498
11862
|
budgets: localToolBudgets,
|
|
@@ -10501,7 +11865,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10501
11865
|
const result = await executeLocalToolWithPolicy({
|
|
10502
11866
|
env: deps.env,
|
|
10503
11867
|
agentToolNames: activeAgentToolNames,
|
|
10504
|
-
call,
|
|
11868
|
+
call: injectedCall,
|
|
10505
11869
|
executors: localToolExecutors,
|
|
10506
11870
|
abortSignal: opts?.abortSignal,
|
|
10507
11871
|
detachMs: resolveExecShellDetachMs(deps.env),
|
|
@@ -10522,6 +11886,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10522
11886
|
export {
|
|
10523
11887
|
summarizeEndpoint,
|
|
10524
11888
|
isBuiltinNoloAgentRef,
|
|
11889
|
+
parseAgentRunEvent,
|
|
10525
11890
|
parseCliLocale,
|
|
10526
11891
|
getCliLocale,
|
|
10527
11892
|
setCliLocale,
|
|
@@ -10529,6 +11894,8 @@ export {
|
|
|
10529
11894
|
t,
|
|
10530
11895
|
toolLabel,
|
|
10531
11896
|
agentRunCardLabels,
|
|
11897
|
+
QUOTA_ERROR_PATTERNS,
|
|
11898
|
+
isQuotaExhaustedError,
|
|
10532
11899
|
clearCliLocalRuntimePreparedAgentCache,
|
|
10533
11900
|
createCliCallAgentToolExecutor,
|
|
10534
11901
|
createCliLocalRuntimeAdapter
|