nolo-cli 0.16.0-alpha.2 → 0.16.0-alpha.21
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-QAUS6B7J.js → _executeModel-GRCQXT5R.js} +51 -45
- package/{action-GUOZYYGN.js → action-LT7BRFLK.js} +10 -9
- package/{addContentAction-QDGHGUBH.js → addContentAction-PL3KKBDH.js} +9 -8
- package/{addDialogAgentAction-Z4YCYZIV.js → addDialogAgentAction-FCMSKYAF.js} +8 -7
- package/{agentDeleteCommand-365DMKHW.js → agentDeleteCommand-WNL3CNQX.js} +32 -29
- package/{agentEmailCommands-TQMXL36I.js → agentEmailCommands-MPEUMRAS.js} +63 -57
- package/{agentListCommands-6B5X4RC6.js → agentListCommands-YO4AOQMS.js} +31 -28
- package/{agentMachineCommands-LOEARB6V.js → agentMachineCommands-WYM6YRYJ.js} +30 -27
- package/{agentPullCommand-6HWUT3SW.js → agentPullCommand-ZZGU5KOY.js} +4 -4
- package/agentRecordCommands-BVWSHMIY.js +105 -0
- package/{agentRunCommand-SGMH67WT.js → agentRunCommand-E3ZI6RSF.js} +64 -55
- package/{agentRunControl-6ADXVYMR.js → agentRunControl-Y5AFH5PQ.js} +24 -1
- package/{agentRuntimeLocal-YSYZ33ER.js → agentRuntimeLocal-P4VGX6H6.js} +26 -25
- package/{agentSlice-IVE735EV.js → agentSlice-D33GU3JL.js} +9 -8
- package/{appDeleteCommands-6QYOO3JB.js → appDeleteCommands-VA4R2SWX.js} +29 -26
- package/{appDeployCommands-WTCT6XO6.js → appDeployCommands-JWMWQNG6.js} +29 -26
- package/{appDeployStatusCommands-CGWGZJKB.js → appDeployStatusCommands-KYXGLZSQ.js} +29 -26
- package/{appGetCommands-O4OCAMRW.js → appGetCommands-ELOO3JG6.js} +29 -26
- package/{appListCommands-UENFP4XY.js → appListCommands-SJUW4RLW.js} +29 -26
- package/{authCommand-YFTR3347.js → authCommand-WJZPOLSS.js} +16 -9
- package/{authCommands-YXGOXNBZ.js → authCommands-XTBV7OFZ.js} +6 -5
- package/{chunk-RKM3K52F.js → chunk-34WPV75U.js} +23 -2
- package/{chunk-VPTJB4HM.js → chunk-3ND52WIL.js} +2 -5
- package/{chunk-SOTZ6RDN.js → chunk-3Q7WHGCB.js} +1 -1
- package/{chunk-KKY4B2Q2.js → chunk-4PWB7JRR.js} +4 -1
- package/{chunk-U7LEGLEB.js → chunk-4T5F7YZQ.js} +1 -1
- package/{chunk-OQMPU2ML.js → chunk-5PGGCJGV.js} +6 -6
- package/chunk-7BUYEZ6U.js +671 -0
- package/{chunk-AS3ZQ3O2.js → chunk-7OBMZCRD.js} +1 -1
- package/{chunk-WA6KZL5V.js → chunk-AAODAAUQ.js} +23 -20
- package/{chunk-GRTFNYLR.js → chunk-AKVLLMOU.js} +3 -3
- package/{chunk-QLUFR47U.js → chunk-AL2V7U3E.js} +1 -1
- package/{chunk-MTU75CZ2.js → chunk-B5TOXZAK.js} +1 -1
- package/{chunk-QZVGMD5F.js → chunk-BE2GNT5E.js} +2 -8
- package/{chunk-JKWWVF2I.js → chunk-D3HVJJIA.js} +1 -1
- package/{chunk-B4KT7RN2.js → chunk-DKZFOK24.js} +18 -89
- package/chunk-DL6EPNIK.js +50 -0
- package/{chunk-YYIRR6QC.js → chunk-E5KQTMMJ.js} +212 -250
- package/{chunk-4QQFLN5C.js → chunk-EGPCU42M.js} +58 -8
- package/{chunk-XVP3C2KY.js → chunk-ELT65PZW.js} +2 -2
- package/{chunk-EMXI3N3Z.js → chunk-ENP2ELIL.js} +5 -5
- package/{chunk-6565R2TI.js → chunk-EXAEHRLI.js} +112 -191
- package/chunk-FQZZLA3C.js +223 -0
- package/{chunk-WPN6RMDF.js → chunk-GMZZ5EKJ.js} +3 -3
- package/{chunk-RSYUDGGZ.js → chunk-HQNPCMWL.js} +3 -3
- package/{chunk-OGGHETUE.js → chunk-HQPG2PIV.js} +62 -19
- package/{chunk-4NLUNENX.js → chunk-IQZ6TGVW.js} +10 -3
- package/{chunk-VE6XMVKG.js → chunk-J67FKTTY.js} +330 -213
- package/{chunk-G2MKOQCB.js → chunk-JFE7XW4D.js} +1 -1
- package/{setDialogExtraReferencesAction-2VLGWQKG.js → chunk-JLA4FXYC.js} +2 -17
- package/{chunk-OOIN7HSO.js → chunk-JP7REMYP.js} +19 -1
- package/chunk-KFEVY3ST.js +255 -0
- package/{chunk-I66RU7P7.js → chunk-KKWJ5VPZ.js} +1 -1
- package/{chunk-WRN5EQT7.js → chunk-L2RRMXNJ.js} +13 -4
- package/{chunk-ISYE6GZB.js → chunk-L6NVTGI7.js} +1 -1
- package/{chunk-HRQCKQA5.js → chunk-MUCU6ATG.js} +8 -257
- package/{chunk-BFRVXJJJ.js → chunk-MUIT5AAM.js} +112 -27
- package/{chunk-WNLPAOIT.js → chunk-MVQ4TBSD.js} +1 -1
- package/{chunk-O53CP2QR.js → chunk-N2HYIBLH.js} +6 -6
- package/{chunk-524BDL33.js → chunk-O6W2O2DA.js} +1 -15
- package/{chunk-YC3DJILJ.js → chunk-PUSK7HXJ.js} +64 -22
- package/{chunk-OOSFSFMA.js → chunk-R5V5G73M.js} +2 -0
- package/{chunk-4IJYA27C.js → chunk-RG2U2MTJ.js} +1 -1
- package/{chunk-Z24FGIU2.js → chunk-RIDWN7AP.js} +34 -15
- package/{chunk-IKXL2HZ3.js → chunk-RK5NYQEL.js} +1 -1
- package/{chunk-QLFCNUVQ.js → chunk-RUTSBLDM.js} +1629 -261
- package/{chunk-TTGAVETO.js → chunk-RVOUXDFU.js} +5 -5
- package/{chunk-JTINRTBT.js → chunk-SKDNBYZK.js} +2 -2
- package/{chunk-KMQPSTMJ.js → chunk-TRT4I4UD.js} +2 -2
- package/{chunk-EHLHSX7R.js → chunk-UB4RYYNQ.js} +9 -2
- package/{chunk-N5424GSW.js → chunk-UGUW3FHG.js} +4 -4
- package/{chunk-YNHQIXX5.js → chunk-UIOYWBU7.js} +395 -326
- package/chunk-V5R4NZP2.js +78 -0
- package/{chunk-MYMMNKYL.js → chunk-VNAEBGDK.js} +156 -6
- package/{chunk-J55UHASN.js → chunk-VST53WEL.js} +1 -1
- package/{chunk-6MHDWKOT.js → chunk-VVKQFITN.js} +25 -12
- 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-E237VE6U.js → chunk-XFYDGBXL.js} +4 -4
- package/{chunk-JS33TCQ3.js → chunk-XHG22OEX.js} +4 -4
- package/{chunk-DVRHHFEA.js → chunk-XMLRJUU5.js} +1 -1
- package/{chunk-V2J635L5.js → chunk-XOIF2TNF.js} +2 -2
- package/{chunk-SFXYKGK2.js → chunk-XRZJGPFI.js} +7 -7
- package/chunk-ZHXJ6M7T.js +27 -0
- package/chunk-ZZ2MH7LE.js +84 -0
- package/{cliExecutor-K3F7DMRO.js → cliExecutor-DNE7TCC4.js} +2 -2
- package/codingSkills-36KN5NQT.js +48 -0
- package/{createAgentAutomationAction-TS6NNZ4X.js → createAgentAutomationAction-ONKZ46XE.js} +22 -21
- package/{createDialogAction-5HVQ33EX.js → createDialogAction-7QWJEBKU.js} +24 -23
- package/{createPageAction-4F3ZGQJD.js → createPageAction-PB3KXZIA.js} +28 -27
- package/{dbSlice-OP6UPXKA.js → dbSlice-CGSRFJN3.js} +8 -7
- package/{deleteFile-WPWVZE4B.js → deleteFile-WDZ3VM7B.js} +3 -3
- package/{dialogCommands-ZL6L24BS.js → dialogCommands-YZFU4Q26.js} +30 -27
- package/{dialogSlice-FAWUQDJW.js → dialogSlice-53B5ISGQ.js} +22 -21
- package/{docCreateCommands-LYROQTFH.js → docCreateCommands-LOUC5PFB.js} +28 -25
- package/{docDeleteCommands-6TWGTZNR.js → docDeleteCommands-HHPGT4BR.js} +29 -26
- package/{docReadCommands-PRULNF26.js → docReadCommands-YPSN4HEF.js} +28 -25
- package/{docStore-2UHVWLTV.js → docStore-LJXXRB5W.js} +23 -22
- package/{docUpdateCommands-NNYYWJBI.js → docUpdateCommands-CJCZO54M.js} +28 -25
- package/{fetchMessages-KTNM7QAR.js → fetchMessages-BMGVZVSE.js} +4 -3
- package/{getPricing-UGDJHI7M.js → getPricing-RYY6OBA4.js} +4 -4
- package/handleSendMessageAction-ICGX4QCM.js +402 -0
- package/index.js +68 -68
- package/{localDialogRead-2VRI24F4.js → localDialogRead-HQZPVIE3.js} +1 -1
- package/{localRuntimeDb-LGDF6FQP.js → localRuntimeDb-THJZGAOJ.js} +1 -1
- package/{machineCommands-JQPEQFSE.js → machineCommands-YLDZXK4D.js} +64 -58
- package/{machineWsRunDispatch-FFFNWVEW.js → machineWsRunDispatch-LTQL3DRE.js} +56 -50
- package/{models-LSCRJJ6P.js → models-5K5G2CZI.js} +2 -2
- package/package.json +1 -1
- package/queryRunOverlay-O4LOMMPO.js +161 -0
- package/{read-HXHAZBKH.js → read-3FMPZPER.js} +3 -3
- package/{readDocTool-VPBDTO4G.js → readDocTool-VSYHKK3V.js} +1 -1
- package/{readlineWorkspace-QSXHSBHA.js → readlineWorkspace-OSPVWNAT.js} +699 -168
- package/{removeDialogAgentAction-HUFVN35S.js → removeDialogAgentAction-OAGA2G3U.js} +11 -10
- package/{runAgentClientLoop-A75BUU6D.js → runAgentClientLoop-76SUKKPX.js} +46 -40
- package/runOverlayPresentation-ZO4VCWEU.js +11 -0
- package/{runtimeDoctorCommands-THIHX2SY.js → runtimeDoctorCommands-E2OUORHK.js} +6 -6
- package/setDialogExtraReferencesAction-JZEXA5SL.js +27 -0
- package/{setPrimaryDialogAgentAction-VB4UV2CC.js → setPrimaryDialogAgentAction-4ZUQQKDG.js} +27 -18
- package/{settingSlice-7JYPQNAC.js → settingSlice-7MNKHZ6R.js} +9 -8
- package/{skillDiscovery-6M2BZUFN.js → skillDiscovery-KJWT7JBU.js} +3 -3
- package/{spaceCommands-4LE45GB7.js → spaceCommands-GIF7MKVD.js} +31 -28
- package/{spaceSlice-444MFUP6.js → spaceSlice-M4PVN5PO.js} +22 -21
- package/{streamAgentChatTurn-DJAE7USZ.js → streamAgentChatTurn-GCKTFSHQ.js} +96 -55
- package/{tableCommands-3P7MJ3PF.js → tableCommands-BEQAGE4I.js} +1 -1
- package/{tools-YB6LXSVN.js → tools-RJVFXOLR.js} +35 -30
- package/{tuiSummaryLlmCaller-QQL3JA5I.js → tuiSummaryLlmCaller-VUNVBRX3.js} +7 -6
- package/types-ZSTJ7MPR.js +7 -0
- package/{updateDialogTitleAction-6HGFBM64.js → updateDialogTitleAction-PSR67DLV.js} +25 -24
- package/agentRecordCommands-DCH2WBL2.js +0 -99
- package/chunk-BYXBJQAS.js +0 -0
- package/handleSendMessageAction-LJPUYNOH.js +0 -215
- package/{chunk-O4BU24WZ.js → chunk-6Y7A3OQQ.js} +3 -3
- 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-BE2GNT5E.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-L2RRMXNJ.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,18 +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
43
|
resolveEffectiveEnabledPacks
|
|
50
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-J67FKTTY.js";
|
|
51
45
|
import {
|
|
52
46
|
createDrainExhaustedResponse,
|
|
53
47
|
isCoreDrainingBody,
|
|
@@ -57,15 +51,18 @@ import {
|
|
|
57
51
|
import {
|
|
58
52
|
normalizeDialogTitle
|
|
59
53
|
} from "./chunk-OWOHNGCN.js";
|
|
54
|
+
import {
|
|
55
|
+
getDefaultCliLocalRuntimeDb
|
|
56
|
+
} from "./chunk-WJRJDX2W.js";
|
|
60
57
|
import {
|
|
61
58
|
prepareTokenUsageData
|
|
62
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-UIOYWBU7.js";
|
|
63
60
|
import {
|
|
64
61
|
BUILTIN_TITLE_LLM_CONFIG
|
|
65
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-XOIF2TNF.js";
|
|
66
63
|
import {
|
|
67
64
|
fetchServerSyncedCredential
|
|
68
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-5PGGCJGV.js";
|
|
69
66
|
import {
|
|
70
67
|
buildAgentRuntimeDialogWritePlan,
|
|
71
68
|
buildLocalWorkspaceOpenAiTools,
|
|
@@ -76,37 +73,39 @@ import {
|
|
|
76
73
|
executeLocalToolWithPolicy,
|
|
77
74
|
executeOpenAiCompatibleChatCompletion,
|
|
78
75
|
parseSseDataLineJson,
|
|
76
|
+
parseSseDataLineObject,
|
|
79
77
|
readOpenAiCompatibleSseCompletion,
|
|
80
78
|
resolveOpenAiCompatibleProviderConfig
|
|
81
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-PUSK7HXJ.js";
|
|
82
80
|
import {
|
|
83
81
|
buildPlatformChatCompletionRequest,
|
|
84
82
|
canUsePlatformChatProvider,
|
|
85
83
|
parsePlatformChatCompletionData,
|
|
86
84
|
parsePlatformChatCompletionResponse,
|
|
87
85
|
readSseDataValues,
|
|
88
|
-
resolveLegacyDeepSeekProxyChatFallback,
|
|
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-VVKQFITN.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-VNAEBGDK.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-FQZZLA3C.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,28 +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
|
-
PUBLIC_KIMI_K26_IMAGE_AGENT_KEY
|
|
175
|
-
|
|
176
|
-
} from "./chunk-VPTJB4HM.js";
|
|
189
|
+
PUBLIC_KIMI_K26_IMAGE_AGENT_KEY
|
|
190
|
+
} from "./chunk-3ND52WIL.js";
|
|
177
191
|
import {
|
|
178
192
|
asTrimmedString
|
|
179
193
|
} from "./chunk-3EUW3WEO.js";
|
|
@@ -263,6 +277,10 @@ var STRINGS = {
|
|
|
263
277
|
en: "Cleared current dialog messages.",
|
|
264
278
|
zh: "\u5DF2\u6E05\u9664\u5F53\u524D\u5BF9\u8BDD\u6D88\u606F\u3002"
|
|
265
279
|
},
|
|
280
|
+
persistentProcessesLeft: {
|
|
281
|
+
en: "{0} persistent process(es) left running in the background.",
|
|
282
|
+
zh: "\u4ECD\u6709 {0} \u4E2A\u5E38\u9A7B\u540E\u53F0\u8FDB\u7A0B\u5728\u540E\u53F0\u7EE7\u7EED\u8FD0\u884C\u3002"
|
|
283
|
+
},
|
|
266
284
|
clearNoDialog: {
|
|
267
285
|
en: "No current dialog messages to clear.",
|
|
268
286
|
zh: "\u5F53\u524D\u6CA1\u6709\u53EF\u6E05\u9664\u7684\u5BF9\u8BDD\u6D88\u606F\u3002"
|
|
@@ -463,6 +481,10 @@ var STRINGS = {
|
|
|
463
481
|
en: "Run stopped",
|
|
464
482
|
zh: "\u8FD0\u884C\u5DF2\u505C\u6B62"
|
|
465
483
|
},
|
|
484
|
+
runFinishedLabel: {
|
|
485
|
+
en: "Run finished",
|
|
486
|
+
zh: "\u8FD0\u884C\u5DF2\u7ED3\u675F"
|
|
487
|
+
},
|
|
466
488
|
runLogTailLabel: {
|
|
467
489
|
en: "Log tail:",
|
|
468
490
|
zh: "\u65E5\u5FD7\u5C3E\u90E8\uFF1A"
|
|
@@ -497,6 +519,10 @@ var STRINGS = {
|
|
|
497
519
|
en: "selected",
|
|
498
520
|
zh: "\u5DF2\u9009"
|
|
499
521
|
},
|
|
522
|
+
dialogMultiSelectRequired: {
|
|
523
|
+
en: "Pick at least one option to submit",
|
|
524
|
+
zh: "\u81F3\u5C11\u9009\u62E9\u4E00\u9879\u624D\u80FD\u63D0\u4EA4"
|
|
525
|
+
},
|
|
500
526
|
dialogConfirmHint: {
|
|
501
527
|
en: "(\u2191\u2193 move \xB7 Enter choose \xB7 Esc cancel)",
|
|
502
528
|
zh: "\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
|
|
@@ -537,7 +563,7 @@ var STRINGS = {
|
|
|
537
563
|
en: "abort the operation",
|
|
538
564
|
zh: "\u4E2D\u6B62\u64CD\u4F5C"
|
|
539
565
|
},
|
|
540
|
-
// --- Ask choice (
|
|
566
|
+
// --- Ask choice (ask_user) ------------------------------------------
|
|
541
567
|
askChoiceTitle: {
|
|
542
568
|
en: "question",
|
|
543
569
|
zh: "\u95EE\u9898"
|
|
@@ -928,11 +954,191 @@ function agentRunCardLabels() {
|
|
|
928
954
|
runStatus: t("runStatusLabel"),
|
|
929
955
|
runStarted: t("runStartedLabel"),
|
|
930
956
|
runStopped: t("runStoppedLabel"),
|
|
957
|
+
runFinished: t("runFinishedLabel"),
|
|
931
958
|
logTail: t("runLogTailLabel"),
|
|
932
959
|
runs: (count) => t("runsListLabel", String(count))
|
|
933
960
|
};
|
|
934
961
|
}
|
|
935
962
|
|
|
963
|
+
// packages/ai/tools/agent/quotaCircuitBreaker.ts
|
|
964
|
+
var QUOTA_ERROR_PATTERNS = [
|
|
965
|
+
/429/,
|
|
966
|
+
/quota/i,
|
|
967
|
+
/rate\s*limit/i,
|
|
968
|
+
/too\s*many\s*requests/i,
|
|
969
|
+
/额度/,
|
|
970
|
+
/上限/,
|
|
971
|
+
/用尽/,
|
|
972
|
+
/CliProviderQuotaError/i
|
|
973
|
+
];
|
|
974
|
+
var AGENT_NOT_FOUND_PATTERNS = [
|
|
975
|
+
/agent[^\n]{0,80}not\s+found/i,
|
|
976
|
+
/agent[^\n]{0,80}not\s+exist/i,
|
|
977
|
+
/agent[^\n]{0,80}不存在/i,
|
|
978
|
+
/agent[^\n]{0,80}未找到/i,
|
|
979
|
+
/AGENT_NOT_FOUND/
|
|
980
|
+
];
|
|
981
|
+
var AUTH_ERROR_PATTERNS = [
|
|
982
|
+
/401/,
|
|
983
|
+
/403/,
|
|
984
|
+
/unauthori[sz]ed/i,
|
|
985
|
+
/authentication\s+failed/i,
|
|
986
|
+
/invalid\s+(api[-\s]?key|token|credential)/i,
|
|
987
|
+
/api[-\s]?key\s+(invalid|missing|not\s+found)/i,
|
|
988
|
+
/token\s*(invalid|expired|失效|过期)/i,
|
|
989
|
+
/未授权/,
|
|
990
|
+
/认证失败/,
|
|
991
|
+
/凭证/
|
|
992
|
+
];
|
|
993
|
+
var NETWORK_ERROR_PATTERNS = [
|
|
994
|
+
/ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EHOSTUNREACH|EPIPE/i,
|
|
995
|
+
/getaddrinfo|DNS\s+(error|fail)/i,
|
|
996
|
+
/fetch\s+failed/i,
|
|
997
|
+
/network\s+(error|unreachable|down|disconnected)/i,
|
|
998
|
+
/socket\s+(hang|closed|error)/i,
|
|
999
|
+
/连接失败/,
|
|
1000
|
+
/网络错误|网络异常|无法连接/
|
|
1001
|
+
];
|
|
1002
|
+
function findActiveBreaker(now, table, target) {
|
|
1003
|
+
if (!Number.isFinite(now)) return void 0;
|
|
1004
|
+
for (const entry of table) {
|
|
1005
|
+
if (entry.target !== target) continue;
|
|
1006
|
+
if (typeof entry.until === "number" && entry.until > now) return entry;
|
|
1007
|
+
}
|
|
1008
|
+
return void 0;
|
|
1009
|
+
}
|
|
1010
|
+
function isCliProviderQuotaErrorShape(error) {
|
|
1011
|
+
if (!error || typeof error !== "object") return false;
|
|
1012
|
+
const e = error;
|
|
1013
|
+
return e.name === "CliProviderQuotaError" || typeof e.message === "string" && e.message.startsWith("[QUOTA_LIMITED:");
|
|
1014
|
+
}
|
|
1015
|
+
function isQuotaExhaustedError(error) {
|
|
1016
|
+
if (!error) return false;
|
|
1017
|
+
if (isCliProviderQuotaErrorShape(error)) return true;
|
|
1018
|
+
if (error instanceof Error) {
|
|
1019
|
+
return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error.message));
|
|
1020
|
+
}
|
|
1021
|
+
if (typeof error === "string") {
|
|
1022
|
+
return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error));
|
|
1023
|
+
}
|
|
1024
|
+
const maybeStatus = error.status;
|
|
1025
|
+
if (typeof maybeStatus === "number" && maybeStatus === 429) return true;
|
|
1026
|
+
const maybeStatusCode = error.statusCode;
|
|
1027
|
+
if (typeof maybeStatusCode === "number" && maybeStatusCode === 429) return true;
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
function isAgentNotFoundError(error) {
|
|
1031
|
+
if (!error) return false;
|
|
1032
|
+
const e = error;
|
|
1033
|
+
if (e.code === "AGENT_NOT_FOUND") return true;
|
|
1034
|
+
const message = typeof e.message === "string" ? e.message : typeof error === "string" ? error : "";
|
|
1035
|
+
if (AGENT_NOT_FOUND_PATTERNS.some((pattern) => pattern.test(message))) return true;
|
|
1036
|
+
if ((e.status === 404 || e.statusCode === 404) && /agent|不存在|未找到/i.test(message)) {
|
|
1037
|
+
return true;
|
|
1038
|
+
}
|
|
1039
|
+
return false;
|
|
1040
|
+
}
|
|
1041
|
+
function extractMessage(error) {
|
|
1042
|
+
if (typeof error === "string") return error;
|
|
1043
|
+
if (error instanceof Error) return error.message;
|
|
1044
|
+
if (error && typeof error === "object") {
|
|
1045
|
+
const m = error.message;
|
|
1046
|
+
return typeof m === "string" ? m : "";
|
|
1047
|
+
}
|
|
1048
|
+
return "";
|
|
1049
|
+
}
|
|
1050
|
+
function extractStatus(error) {
|
|
1051
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1052
|
+
const e = error;
|
|
1053
|
+
const s = typeof e.status === "number" ? e.status : void 0;
|
|
1054
|
+
const sc = typeof e.statusCode === "number" ? e.statusCode : void 0;
|
|
1055
|
+
return s ?? sc;
|
|
1056
|
+
}
|
|
1057
|
+
function parseResetsInMs(text) {
|
|
1058
|
+
if (!text) return void 0;
|
|
1059
|
+
const unitMs = (n, unit) => {
|
|
1060
|
+
if (/^d/.test(unit)) return n * 24 * 3600 * 1e3;
|
|
1061
|
+
if (/^h/.test(unit)) return n * 3600 * 1e3;
|
|
1062
|
+
if (/^m/.test(unit)) return n * 60 * 1e3;
|
|
1063
|
+
if (/^s/.test(unit)) return n * 1e3;
|
|
1064
|
+
return NaN;
|
|
1065
|
+
};
|
|
1066
|
+
const re = /(\d+)\s*(d(?:ay|ays)?|h(?:r|rs|our|ours)?|m(?:in|ins|inute|inutes)?|s(?:ec|ecs|econd|econds)?)/gi;
|
|
1067
|
+
let totalMs = 0;
|
|
1068
|
+
let matched = false;
|
|
1069
|
+
let m;
|
|
1070
|
+
while ((m = re.exec(text)) !== null) {
|
|
1071
|
+
const ms = unitMs(Number(m[1]), m[2]);
|
|
1072
|
+
if (!Number.isFinite(ms)) continue;
|
|
1073
|
+
totalMs += ms;
|
|
1074
|
+
matched = true;
|
|
1075
|
+
}
|
|
1076
|
+
return matched ? totalMs : void 0;
|
|
1077
|
+
}
|
|
1078
|
+
function extractProvider(error) {
|
|
1079
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1080
|
+
const p = error.provider;
|
|
1081
|
+
if (typeof p === "string" && p.length > 0) return p;
|
|
1082
|
+
const message = extractMessage(error);
|
|
1083
|
+
const tag = /\[QUOTA_LIMITED:([^\]]+)\]/i.exec(message);
|
|
1084
|
+
if (tag?.[1]) return tag[1];
|
|
1085
|
+
return void 0;
|
|
1086
|
+
}
|
|
1087
|
+
function extractRetryAfterHeader(error) {
|
|
1088
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1089
|
+
const headers = error.headers;
|
|
1090
|
+
if (!headers || typeof headers !== "object") return void 0;
|
|
1091
|
+
const raw = headers["retry-after"];
|
|
1092
|
+
if (typeof raw !== "string" && typeof raw !== "number") return void 0;
|
|
1093
|
+
const secs = Number(raw);
|
|
1094
|
+
return Number.isFinite(secs) && secs > 0 ? secs * 1e3 : void 0;
|
|
1095
|
+
}
|
|
1096
|
+
function classifyRunFailure(error) {
|
|
1097
|
+
const message = extractMessage(error);
|
|
1098
|
+
const status = extractStatus(error);
|
|
1099
|
+
const retryAfterMs = extractRetryAfterHeader(error) ?? parseResetsInMs(message);
|
|
1100
|
+
if (isQuotaExhaustedError(error)) {
|
|
1101
|
+
return {
|
|
1102
|
+
reason: "quota",
|
|
1103
|
+
provider: extractProvider(error),
|
|
1104
|
+
// 纯函数不取时钟:resetsAt 由调用方用 now + retryAfterMs 计算后补齐
|
|
1105
|
+
retryAfterMs,
|
|
1106
|
+
message
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
if (isAgentNotFoundError(error)) {
|
|
1110
|
+
return { reason: "agent-not-found", message };
|
|
1111
|
+
}
|
|
1112
|
+
if (isAuthError(error)) {
|
|
1113
|
+
return { reason: "auth", message };
|
|
1114
|
+
}
|
|
1115
|
+
if (isNetworkError(error)) {
|
|
1116
|
+
return { reason: "network", message };
|
|
1117
|
+
}
|
|
1118
|
+
return { reason: "other", message };
|
|
1119
|
+
}
|
|
1120
|
+
function isAuthError(error) {
|
|
1121
|
+
const message = extractMessage(error);
|
|
1122
|
+
const status = extractStatus(error);
|
|
1123
|
+
if (status === 401 || status === 403) return true;
|
|
1124
|
+
return AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
1125
|
+
}
|
|
1126
|
+
function isNetworkError(error) {
|
|
1127
|
+
const message = extractMessage(error);
|
|
1128
|
+
return NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
1129
|
+
}
|
|
1130
|
+
var DEFAULT_QUOTA_BREAKER_MS = 6 * 3600 * 1e3;
|
|
1131
|
+
var DEFAULT_AGENT_NOT_FOUND_BREAKER_MS = 15 * 60 * 1e3;
|
|
1132
|
+
function buildBreakerEntry(now, target, kind, retryAfterMs) {
|
|
1133
|
+
const ttl = kind === "quota" ? typeof retryAfterMs === "number" && retryAfterMs > 0 ? retryAfterMs : DEFAULT_QUOTA_BREAKER_MS : DEFAULT_AGENT_NOT_FOUND_BREAKER_MS;
|
|
1134
|
+
return {
|
|
1135
|
+
target,
|
|
1136
|
+
kind,
|
|
1137
|
+
until: now + ttl,
|
|
1138
|
+
...kind === "quota" && typeof retryAfterMs === "number" ? { resetsAt: now + retryAfterMs } : {}
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
|
|
936
1142
|
// packages/cli/client/localRuntimeDiagnostics.ts
|
|
937
1143
|
import { ulid } from "ulid";
|
|
938
1144
|
var preparedAgentRuntimeCache = /* @__PURE__ */ new Map();
|
|
@@ -972,7 +1178,7 @@ function summarizeOpenAiToolNames(tools) {
|
|
|
972
1178
|
}
|
|
973
1179
|
|
|
974
1180
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
975
|
-
import { dirname, extname, join } from "node:path";
|
|
1181
|
+
import { dirname as dirname2, extname, join as join2 } from "node:path";
|
|
976
1182
|
import { fileURLToPath } from "node:url";
|
|
977
1183
|
|
|
978
1184
|
// packages/core/summarizeEndpoint.ts
|
|
@@ -1123,6 +1329,11 @@ async function fetchWithTransientRetry(fetchImpl, input, init, options = {}) {
|
|
|
1123
1329
|
const attemptBudget = coreDraining ? coreDrainingMaxAttempts : maxAttempts;
|
|
1124
1330
|
if (attempt < attemptBudget) {
|
|
1125
1331
|
const delayMs = await resolveRetryAfterMs(response, attempt);
|
|
1332
|
+
options.onRetry?.({
|
|
1333
|
+
attempt: attempt + 1,
|
|
1334
|
+
maxAttempts: attemptBudget,
|
|
1335
|
+
delayMs
|
|
1336
|
+
});
|
|
1126
1337
|
await (options.sleep ?? defaultSleep)(delayMs);
|
|
1127
1338
|
continue;
|
|
1128
1339
|
}
|
|
@@ -1136,7 +1347,13 @@ async function fetchWithTransientRetry(fetchImpl, input, init, options = {}) {
|
|
|
1136
1347
|
if (!isTransientFetchError(error)) throw error;
|
|
1137
1348
|
lastError = error;
|
|
1138
1349
|
if (attempt < maxAttempts) {
|
|
1139
|
-
|
|
1350
|
+
const delayMs = transientFetchRetryDelayMs(attempt);
|
|
1351
|
+
options.onRetry?.({
|
|
1352
|
+
attempt: attempt + 1,
|
|
1353
|
+
maxAttempts,
|
|
1354
|
+
delayMs
|
|
1355
|
+
});
|
|
1356
|
+
await (options.sleep ?? defaultSleep)(delayMs);
|
|
1140
1357
|
}
|
|
1141
1358
|
}
|
|
1142
1359
|
}
|
|
@@ -1466,14 +1683,14 @@ var BUILTIN_PLATFORM_AGENT_CONFIGS = {
|
|
|
1466
1683
|
[PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY]: {
|
|
1467
1684
|
key: PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
|
|
1468
1685
|
name: "DeepSeek V4 Pro",
|
|
1469
|
-
provider: "
|
|
1686
|
+
provider: "nolo",
|
|
1470
1687
|
model: "deepseek-v4-pro",
|
|
1471
1688
|
apiSource: "platform",
|
|
1472
1689
|
useServerProxy: true,
|
|
1473
1690
|
rawRecord: {
|
|
1474
1691
|
dbKey: PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
|
|
1475
1692
|
isPublic: true,
|
|
1476
|
-
provider: "
|
|
1693
|
+
provider: "nolo",
|
|
1477
1694
|
model: "deepseek-v4-pro",
|
|
1478
1695
|
apiSource: "platform",
|
|
1479
1696
|
useServerProxy: true
|
|
@@ -1511,22 +1728,6 @@ var BUILTIN_PLATFORM_AGENT_CONFIGS = {
|
|
|
1511
1728
|
useServerProxy: true
|
|
1512
1729
|
}
|
|
1513
1730
|
},
|
|
1514
|
-
[PUBLIC_KIMI_K27_CODING_AGENT_KEY]: {
|
|
1515
|
-
key: PUBLIC_KIMI_K27_CODING_AGENT_KEY,
|
|
1516
|
-
name: "Kimi K2.7 Coding",
|
|
1517
|
-
provider: "nolo",
|
|
1518
|
-
model: "kimi-k2.7-code",
|
|
1519
|
-
apiSource: "platform",
|
|
1520
|
-
useServerProxy: true,
|
|
1521
|
-
rawRecord: {
|
|
1522
|
-
dbKey: PUBLIC_KIMI_K27_CODING_AGENT_KEY,
|
|
1523
|
-
isPublic: true,
|
|
1524
|
-
provider: "nolo",
|
|
1525
|
-
model: "kimi-k2.7-code",
|
|
1526
|
-
apiSource: "platform",
|
|
1527
|
-
useServerProxy: true
|
|
1528
|
-
}
|
|
1529
|
-
},
|
|
1530
1731
|
[BUILTIN_NOLO_AGENT_KEY]: {
|
|
1531
1732
|
key: BUILTIN_NOLO_AGENT_KEY,
|
|
1532
1733
|
name: "Nolo",
|
|
@@ -1599,23 +1800,6 @@ async function readAgentFromStore(args) {
|
|
|
1599
1800
|
if (!record || typeof record !== "object") continue;
|
|
1600
1801
|
return resolveAgentRuntimeConfigFromRecord(key, record);
|
|
1601
1802
|
}
|
|
1602
|
-
const normalizedRef = normalizeAgentHandle(args.agentRef);
|
|
1603
|
-
if (!normalizedRef) {
|
|
1604
|
-
return resolveBuiltinPlatformAgentConfig(args.agentRef);
|
|
1605
|
-
}
|
|
1606
|
-
try {
|
|
1607
|
-
const iterator = args.store.iterator({
|
|
1608
|
-
gte: "agent-",
|
|
1609
|
-
lte: "agent-\uFFFF"
|
|
1610
|
-
});
|
|
1611
|
-
for await (const [key, record] of iterator) {
|
|
1612
|
-
if (!record || typeof record !== "object") continue;
|
|
1613
|
-
const handle = normalizeAgentHandle(record.handle);
|
|
1614
|
-
if (handle !== normalizedRef) continue;
|
|
1615
|
-
return resolveAgentRuntimeConfigFromRecord(key, record);
|
|
1616
|
-
}
|
|
1617
|
-
} catch {
|
|
1618
|
-
}
|
|
1619
1803
|
return resolveBuiltinPlatformAgentConfig(args.agentRef);
|
|
1620
1804
|
}
|
|
1621
1805
|
async function readDialogMessages(args) {
|
|
@@ -1774,7 +1958,10 @@ var LOCAL_SERVER_WEB_TOOL_NAMES = ["fetchWebpage", "exa_search"];
|
|
|
1774
1958
|
var LOCAL_SERVER_WEB_TOOL_NAME_SET = new Set(
|
|
1775
1959
|
LOCAL_SERVER_WEB_TOOL_NAMES
|
|
1776
1960
|
);
|
|
1777
|
-
var LOCAL_SERVER_MEMORY_TOOL_NAMES = [
|
|
1961
|
+
var LOCAL_SERVER_MEMORY_TOOL_NAMES = [
|
|
1962
|
+
"queryMemory",
|
|
1963
|
+
"rememberMemory"
|
|
1964
|
+
];
|
|
1778
1965
|
var LOCAL_SERVER_MEMORY_TOOL_NAME_SET = new Set(
|
|
1779
1966
|
LOCAL_SERVER_MEMORY_TOOL_NAMES
|
|
1780
1967
|
);
|
|
@@ -2006,6 +2193,25 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
2006
2193
|
}
|
|
2007
2194
|
])
|
|
2008
2195
|
);
|
|
2196
|
+
const queryMemory = async (call) => {
|
|
2197
|
+
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
2198
|
+
const query = typeof parsed.query === "string" ? parsed.query.trim() : "";
|
|
2199
|
+
if (!query) {
|
|
2200
|
+
return {
|
|
2201
|
+
content: JSON.stringify({ error: "queryMemory \u9700\u8981\u975E\u7A7A query\u3002" }),
|
|
2202
|
+
metadata: { serverPlatformTool: true, memoryRead: false }
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
const body = { userInput: query };
|
|
2206
|
+
if (args.agentKey) body.agentKey = args.agentKey;
|
|
2207
|
+
const raw = await postServer("/api/memory/query", body, {
|
|
2208
|
+
retryTransient: true
|
|
2209
|
+
});
|
|
2210
|
+
return {
|
|
2211
|
+
content: raw,
|
|
2212
|
+
metadata: { serverPlatformTool: true, memoryRead: true }
|
|
2213
|
+
};
|
|
2214
|
+
};
|
|
2009
2215
|
const rememberMemory = async (call) => {
|
|
2010
2216
|
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
2011
2217
|
const content = typeof parsed.content === "string" ? parsed.content.trim() : "";
|
|
@@ -2032,11 +2238,368 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
2032
2238
|
metadata: { serverPlatformTool: true, memoryWrite: true }
|
|
2033
2239
|
};
|
|
2034
2240
|
};
|
|
2035
|
-
return { ...tableExecutors, ...webExecutors, rememberMemory };
|
|
2241
|
+
return { ...tableExecutors, ...webExecutors, queryMemory, rememberMemory };
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
// packages/cli/client/cliAgentRunToolExecutors.ts
|
|
2245
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
2246
|
+
|
|
2247
|
+
// packages/cli/client/agentRunSnapshot.ts
|
|
2248
|
+
function readString(value) {
|
|
2249
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2250
|
+
}
|
|
2251
|
+
function readLogLines(parsed) {
|
|
2252
|
+
if (Array.isArray(parsed.logLines)) return parsed.logLines;
|
|
2253
|
+
const tail = readString(parsed.logTail);
|
|
2254
|
+
return tail ? tail.split("\n") : void 0;
|
|
2255
|
+
}
|
|
2256
|
+
function readTimestamp(value) {
|
|
2257
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
|
|
2258
|
+
if (typeof value === "string" && value.trim()) {
|
|
2259
|
+
const parsed = Date.parse(value);
|
|
2260
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
2261
|
+
}
|
|
2262
|
+
return void 0;
|
|
2263
|
+
}
|
|
2264
|
+
function readToolNames(value) {
|
|
2265
|
+
if (!Array.isArray(value)) return void 0;
|
|
2266
|
+
const names = value.filter((n) => typeof n === "string" && Boolean(n.trim()));
|
|
2267
|
+
return names.length > 0 ? names : void 0;
|
|
2268
|
+
}
|
|
2269
|
+
function buildSnapshot(parsed, event) {
|
|
2270
|
+
const runId = readString(parsed.runId) ?? readString(event.metadata?.runId) ?? "";
|
|
2271
|
+
const label = resolveRunLabel({
|
|
2272
|
+
agentName: parsed.agentName,
|
|
2273
|
+
name: parsed.name,
|
|
2274
|
+
agentKey: parsed.agentKey
|
|
2275
|
+
});
|
|
2276
|
+
const logLines = readLogLines(parsed);
|
|
2277
|
+
const taskPreview = readString(parsed.taskPreview);
|
|
2278
|
+
const lastToolNames = readToolNames(parsed.lastToolNames);
|
|
2279
|
+
const lastAssistantText = readString(parsed.lastAssistantText);
|
|
2280
|
+
const errorMessage = readString(parsed.errorMessage);
|
|
2281
|
+
const startedAt = readTimestamp(parsed.startedAt);
|
|
2282
|
+
const finishedAt = readTimestamp(parsed.finishedAt) ?? readTimestamp(parsed.endedAt);
|
|
2283
|
+
return {
|
|
2284
|
+
runId,
|
|
2285
|
+
status: readString(parsed.status) ?? "running",
|
|
2286
|
+
// The literal `agent` fallback is dropped here rather than at each render
|
|
2287
|
+
// site: an unnamed run should render no name row, not the word "agent".
|
|
2288
|
+
...isAgentNameFallback(label) ? {} : { agentName: label },
|
|
2289
|
+
...taskPreview ? { taskPreview } : {},
|
|
2290
|
+
...typeof parsed.toolCallCount === "number" && Number.isFinite(parsed.toolCallCount) ? { toolCallCount: parsed.toolCallCount } : {},
|
|
2291
|
+
...lastToolNames ? { lastToolNames } : {},
|
|
2292
|
+
...lastAssistantText ? { lastAssistantText } : {},
|
|
2293
|
+
...errorMessage ? { errorMessage } : {},
|
|
2294
|
+
...startedAt !== void 0 ? { startedAt } : {},
|
|
2295
|
+
...finishedAt !== void 0 ? { finishedAt } : {},
|
|
2296
|
+
...logLines ? { logLines } : {},
|
|
2297
|
+
logKey: logLines && logLines.length > 0 ? logLines.join("\n") : ""
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
2300
|
+
var STOP_STATUSES = /* @__PURE__ */ new Set(["killed", "cancelled", "cancelling"]);
|
|
2301
|
+
function parseAgentRunEvent(event) {
|
|
2302
|
+
if (event.type !== "tool-result") return null;
|
|
2303
|
+
if (event.toolName !== "startAgentRun" && event.toolName !== "controlAgentRun") {
|
|
2304
|
+
return null;
|
|
2305
|
+
}
|
|
2306
|
+
const raw = typeof event.content === "string" ? event.content.trim() : "";
|
|
2307
|
+
if (!raw.startsWith("{")) return null;
|
|
2308
|
+
let parsed;
|
|
2309
|
+
try {
|
|
2310
|
+
parsed = JSON.parse(raw);
|
|
2311
|
+
} catch {
|
|
2312
|
+
return null;
|
|
2313
|
+
}
|
|
2314
|
+
if (Array.isArray(parsed.runs)) return null;
|
|
2315
|
+
const snapshot = buildSnapshot(parsed, event);
|
|
2316
|
+
const status = readString(parsed.status);
|
|
2317
|
+
if (event.toolName === "startAgentRun") {
|
|
2318
|
+
if (!snapshot.runId) return null;
|
|
2319
|
+
return { kind: "start", snapshot };
|
|
2320
|
+
}
|
|
2321
|
+
if (parsed.found === false || status === "not_found") {
|
|
2322
|
+
return { kind: "gone", snapshot: { ...snapshot, status: "not_found" } };
|
|
2323
|
+
}
|
|
2324
|
+
if (status && STOP_STATUSES.has(status)) {
|
|
2325
|
+
return { kind: "stop", snapshot };
|
|
2326
|
+
}
|
|
2327
|
+
if (!status) return null;
|
|
2328
|
+
if (!snapshot.runId) return null;
|
|
2329
|
+
return { kind: "status", snapshot };
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
// packages/ai/tools/agent/batchAggregation.ts
|
|
2333
|
+
var DEFAULT_BATCH_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
2334
|
+
var MAX_ERROR_SUMMARY_CHARS = 120;
|
|
2335
|
+
var MAX_FAILURE_LINES = 10;
|
|
2336
|
+
function isFailureStatus(status) {
|
|
2337
|
+
return isAgentRunTerminalStatus(status) && status !== "done";
|
|
2338
|
+
}
|
|
2339
|
+
function isOrphanedStatus(status) {
|
|
2340
|
+
return status === "orphaned";
|
|
2341
|
+
}
|
|
2342
|
+
function toEpochMs(iso) {
|
|
2343
|
+
if (!iso) return void 0;
|
|
2344
|
+
const ms = Date.parse(iso);
|
|
2345
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
2346
|
+
}
|
|
2347
|
+
function isOverTimeout(run, nowMs, timeoutMs) {
|
|
2348
|
+
const startedMs = toEpochMs(run.startedAt);
|
|
2349
|
+
if (startedMs === void 0) return false;
|
|
2350
|
+
return nowMs - startedMs >= timeoutMs;
|
|
2351
|
+
}
|
|
2352
|
+
function truncateErrorSummary(text, max = MAX_ERROR_SUMMARY_CHARS) {
|
|
2353
|
+
if (!text) return "";
|
|
2354
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
2355
|
+
if (collapsed.length <= max) return collapsed;
|
|
2356
|
+
return `${collapsed.slice(0, max - 1)}\u2026`;
|
|
2357
|
+
}
|
|
2358
|
+
function formatFailureLine(run) {
|
|
2359
|
+
const label = shortRunId(run.runId);
|
|
2360
|
+
const agent = run.agentName ? ` (${run.agentName})` : "";
|
|
2361
|
+
const error = truncateErrorSummary(run.errorSummary);
|
|
2362
|
+
return error ? `\u5931\u8D25: ${label}${agent} \u2014 ${error}` : `\u5931\u8D25: ${label}${agent}`;
|
|
2363
|
+
}
|
|
2364
|
+
function formatBatchSummary(batchId, counts, runs, reason) {
|
|
2365
|
+
const failures = runs.filter((r) => isFailureStatus(r.status));
|
|
2366
|
+
const unfinished = runs.filter((r) => !isAgentRunTerminalStatus(r.status));
|
|
2367
|
+
if (reason === "timeout") {
|
|
2368
|
+
const lines2 = [
|
|
2369
|
+
`\u6279\u6B21 ${batchId}: \u8D85\u65F6\u672A\u6536\u655B \u2014 ${counts.running} \u4E2A\u672A\u5B8C\u6210`
|
|
2370
|
+
];
|
|
2371
|
+
for (const run of unfinished.slice(0, MAX_FAILURE_LINES)) {
|
|
2372
|
+
const agent = run.agentName ? ` (${run.agentName})` : "";
|
|
2373
|
+
lines2.push(`\u672A\u5B8C\u6210: ${shortRunId(run.runId)}${agent}`);
|
|
2374
|
+
}
|
|
2375
|
+
const rest2 = unfinished.length - MAX_FAILURE_LINES;
|
|
2376
|
+
if (rest2 > 0) lines2.push(`\u2026 \u53CA\u53E6\u5916 ${rest2} \u4E2A\u672A\u5B8C\u6210`);
|
|
2377
|
+
return lines2.join("\n");
|
|
2378
|
+
}
|
|
2379
|
+
const tail = counts.running > 0 ? `, ${counts.running} \u4ECD\u5728\u8DD1` : "";
|
|
2380
|
+
const lines = [
|
|
2381
|
+
`\u6279\u6B21 ${batchId}: ${counts.success + counts.failed}/${counts.total} \u5B8C\u6210 \u2014 ${counts.success} \u6210\u529F, ${counts.failed} \u5931\u8D25${tail}`
|
|
2382
|
+
];
|
|
2383
|
+
for (const run of failures.slice(0, MAX_FAILURE_LINES)) {
|
|
2384
|
+
lines.push(formatFailureLine(run));
|
|
2385
|
+
}
|
|
2386
|
+
const rest = failures.length - MAX_FAILURE_LINES;
|
|
2387
|
+
if (rest > 0) lines.push(`\u2026 \u53CA\u53E6\u5916 ${rest} \u4E2A\u5931\u8D25`);
|
|
2388
|
+
return lines.join("\n");
|
|
2389
|
+
}
|
|
2390
|
+
function aggregateBatch(input) {
|
|
2391
|
+
const { batchId, runs, now } = input;
|
|
2392
|
+
const timeoutMs = input.timeoutMs ?? DEFAULT_BATCH_TIMEOUT_MS;
|
|
2393
|
+
const notified = new Set(input.notifiedReasons ?? []);
|
|
2394
|
+
const nowMs = toEpochMs(now) ?? 0;
|
|
2395
|
+
let success = 0;
|
|
2396
|
+
let failed = 0;
|
|
2397
|
+
let orphaned = 0;
|
|
2398
|
+
let running = 0;
|
|
2399
|
+
const unfinished = [];
|
|
2400
|
+
let timedOut = false;
|
|
2401
|
+
for (const run of runs) {
|
|
2402
|
+
if (isAgentRunTerminalStatus(run.status)) {
|
|
2403
|
+
if (run.status === "done") success += 1;
|
|
2404
|
+
else {
|
|
2405
|
+
failed += 1;
|
|
2406
|
+
if (isOrphanedStatus(run.status)) orphaned += 1;
|
|
2407
|
+
}
|
|
2408
|
+
} else {
|
|
2409
|
+
running += 1;
|
|
2410
|
+
unfinished.push(run.runId);
|
|
2411
|
+
if (isOverTimeout(run, nowMs, timeoutMs)) timedOut = true;
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
const converged = running === 0;
|
|
2415
|
+
let newWakeReasons = [];
|
|
2416
|
+
if (failed > 0 && !notified.has("failure")) {
|
|
2417
|
+
newWakeReasons = ["failure"];
|
|
2418
|
+
} else if (converged && !notified.has("converged")) {
|
|
2419
|
+
newWakeReasons = ["converged"];
|
|
2420
|
+
} else if (timedOut && !notified.has("timeout")) {
|
|
2421
|
+
newWakeReasons = ["timeout"];
|
|
2422
|
+
}
|
|
2423
|
+
const counts = {
|
|
2424
|
+
total: runs.length,
|
|
2425
|
+
success,
|
|
2426
|
+
failed,
|
|
2427
|
+
orphaned,
|
|
2428
|
+
running
|
|
2429
|
+
};
|
|
2430
|
+
const summary = newWakeReasons.length > 0 ? formatBatchSummary(batchId, counts, runs, newWakeReasons[0]) : "";
|
|
2431
|
+
return {
|
|
2432
|
+
batchId,
|
|
2433
|
+
converged,
|
|
2434
|
+
timedOut,
|
|
2435
|
+
counts,
|
|
2436
|
+
newWakeReasons,
|
|
2437
|
+
unfinished,
|
|
2438
|
+
summary
|
|
2439
|
+
};
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
// packages/ai/tools/agent/runtimeTodo.ts
|
|
2443
|
+
var TODO_REVIEW_BLOCK = "BLOCK";
|
|
2444
|
+
function deriveTodoStatus(input) {
|
|
2445
|
+
const { todo, runs } = input;
|
|
2446
|
+
if (todo.status === "abandoned") {
|
|
2447
|
+
return { status: "abandoned" };
|
|
2448
|
+
}
|
|
2449
|
+
if (runs.length === 0) {
|
|
2450
|
+
return { status: todo.status };
|
|
2451
|
+
}
|
|
2452
|
+
if (runs.some((r) => !isAgentRunTerminalStatus(r.status))) {
|
|
2453
|
+
return { status: "running", latestRun: latestRun(runs) };
|
|
2454
|
+
}
|
|
2455
|
+
const latest = latestRun(runs);
|
|
2456
|
+
if (latest?.reviewVerdict === TODO_REVIEW_BLOCK) {
|
|
2457
|
+
return {
|
|
2458
|
+
status: "blocked",
|
|
2459
|
+
latestRun: latest,
|
|
2460
|
+
blockedReason: clipSummary(latest.reviewReason, MAX_ERROR_SUMMARY_CHARS)
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
if (latest?.status === "done") {
|
|
2464
|
+
return { status: "done", latestRun: latest };
|
|
2465
|
+
}
|
|
2466
|
+
return { status: "pending", latestRun: latest };
|
|
2467
|
+
}
|
|
2468
|
+
function toEpochMs2(iso) {
|
|
2469
|
+
if (!iso) return void 0;
|
|
2470
|
+
const ms = Date.parse(iso);
|
|
2471
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
2472
|
+
}
|
|
2473
|
+
function latestRun(runs) {
|
|
2474
|
+
let latest;
|
|
2475
|
+
let latestScore = -1;
|
|
2476
|
+
for (const run of runs) {
|
|
2477
|
+
const score = toEpochMs2(run.finishedAt) ?? toEpochMs2(run.startedAt) ?? -1;
|
|
2478
|
+
if (latest === void 0 || score >= latestScore) {
|
|
2479
|
+
latest = run;
|
|
2480
|
+
latestScore = score;
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
return latest;
|
|
2484
|
+
}
|
|
2485
|
+
function clipSummary(text, max) {
|
|
2486
|
+
if (!text) return void 0;
|
|
2487
|
+
const folded = text.replace(/\s+/g, " ").trim();
|
|
2488
|
+
if (folded.length === 0) return void 0;
|
|
2489
|
+
return folded.length > max ? `${folded.slice(0, max - 1)}\u2026` : folded;
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
// packages/cli/client/fileSystemStores.ts
|
|
2493
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2494
|
+
import { homedir as nodeHomedir } from "node:os";
|
|
2495
|
+
import { dirname, join } from "node:path";
|
|
2496
|
+
var nodeFs = {
|
|
2497
|
+
mkdirSync,
|
|
2498
|
+
writeFileSync,
|
|
2499
|
+
readFileSync,
|
|
2500
|
+
existsSync
|
|
2501
|
+
};
|
|
2502
|
+
function resolveNoloHome(env, homedir) {
|
|
2503
|
+
const custom = env?.NOLO_HOME;
|
|
2504
|
+
if (custom && custom.trim()) return custom.trim();
|
|
2505
|
+
return join(homedir(), ".nolo");
|
|
2506
|
+
}
|
|
2507
|
+
function ensureDir(dir, fs) {
|
|
2508
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
2509
|
+
}
|
|
2510
|
+
function readJson(path, fs) {
|
|
2511
|
+
if (!fs.existsSync(path)) return void 0;
|
|
2512
|
+
try {
|
|
2513
|
+
const raw = fs.readFileSync(path, "utf8");
|
|
2514
|
+
return JSON.parse(String(raw));
|
|
2515
|
+
} catch {
|
|
2516
|
+
return void 0;
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
function writeJson(path, data, fs) {
|
|
2520
|
+
fs.writeFileSync(path, JSON.stringify(data, null, 2));
|
|
2521
|
+
}
|
|
2522
|
+
function createFileSystemCircuitBreakerStore(opts = {}) {
|
|
2523
|
+
const env = opts.env ?? process.env;
|
|
2524
|
+
const homedir = opts.homedir ?? nodeHomedir;
|
|
2525
|
+
const fs = opts.fs ?? nodeFs;
|
|
2526
|
+
const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "breakers.json");
|
|
2527
|
+
const loadMap = () => {
|
|
2528
|
+
const data = readJson(filePath, fs);
|
|
2529
|
+
const map = /* @__PURE__ */ new Map();
|
|
2530
|
+
if (data?.entries) {
|
|
2531
|
+
for (const entry of data.entries) {
|
|
2532
|
+
if (entry && typeof entry.target === "string") map.set(entry.target, entry);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
return map;
|
|
2536
|
+
};
|
|
2537
|
+
const persist = (map) => {
|
|
2538
|
+
ensureDir(dirname(filePath), fs);
|
|
2539
|
+
writeJson(filePath, { entries: [...map.values()] }, fs);
|
|
2540
|
+
};
|
|
2541
|
+
return {
|
|
2542
|
+
get(target) {
|
|
2543
|
+
return loadMap().get(target);
|
|
2544
|
+
},
|
|
2545
|
+
set(entry) {
|
|
2546
|
+
const map = loadMap();
|
|
2547
|
+
map.set(entry.target, entry);
|
|
2548
|
+
persist(map);
|
|
2549
|
+
},
|
|
2550
|
+
clear(target) {
|
|
2551
|
+
const map = loadMap();
|
|
2552
|
+
map.delete(target);
|
|
2553
|
+
persist(map);
|
|
2554
|
+
},
|
|
2555
|
+
clearAll() {
|
|
2556
|
+
persist(/* @__PURE__ */ new Map());
|
|
2557
|
+
}
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
function createFileSystemTodoStore(opts = {}) {
|
|
2561
|
+
const env = opts.env ?? process.env;
|
|
2562
|
+
const homedir = opts.homedir ?? nodeHomedir;
|
|
2563
|
+
const fs = opts.fs ?? nodeFs;
|
|
2564
|
+
const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "todos.json");
|
|
2565
|
+
const loadMap = () => {
|
|
2566
|
+
const data = readJson(filePath, fs);
|
|
2567
|
+
const map = /* @__PURE__ */ new Map();
|
|
2568
|
+
if (data?.todos) {
|
|
2569
|
+
for (const todo of data.todos) {
|
|
2570
|
+
if (todo && typeof todo.id === "string") map.set(todo.id, todo);
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
return map;
|
|
2574
|
+
};
|
|
2575
|
+
const persist = (map) => {
|
|
2576
|
+
ensureDir(dirname(filePath), fs);
|
|
2577
|
+
writeJson(filePath, { todos: [...map.values()] }, fs);
|
|
2578
|
+
};
|
|
2579
|
+
return {
|
|
2580
|
+
async getTodo(id) {
|
|
2581
|
+
return loadMap().get(id);
|
|
2582
|
+
},
|
|
2583
|
+
async listTodos(filter) {
|
|
2584
|
+
const all = [...loadMap().values()];
|
|
2585
|
+
if (!filter?.statuses || filter.statuses.length === 0) return all;
|
|
2586
|
+
const wanted = new Set(filter.statuses);
|
|
2587
|
+
return all.filter((t2) => wanted.has(t2.status));
|
|
2588
|
+
},
|
|
2589
|
+
async putTodo(todo) {
|
|
2590
|
+
const map = loadMap();
|
|
2591
|
+
map.set(todo.id, todo);
|
|
2592
|
+
persist(map);
|
|
2593
|
+
},
|
|
2594
|
+
async deleteTodo(id) {
|
|
2595
|
+
const map = loadMap();
|
|
2596
|
+
map.delete(id);
|
|
2597
|
+
persist(map);
|
|
2598
|
+
}
|
|
2599
|
+
};
|
|
2036
2600
|
}
|
|
2037
2601
|
|
|
2038
2602
|
// packages/cli/client/cliAgentRunToolExecutors.ts
|
|
2039
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2040
2603
|
var noopOutput = { write: () => {
|
|
2041
2604
|
} };
|
|
2042
2605
|
var parseCallArgs = (call) => {
|
|
@@ -2046,7 +2609,7 @@ var parseCallArgs = (call) => {
|
|
|
2046
2609
|
return {};
|
|
2047
2610
|
}
|
|
2048
2611
|
};
|
|
2049
|
-
var resolveFs = (deps) => deps.fs ?? { existsSync, readFileSync };
|
|
2612
|
+
var resolveFs = (deps) => deps.fs ?? { existsSync: existsSync2, readFileSync: readFileSync2 };
|
|
2050
2613
|
var tailFile = (logPath, tailLines, fs) => {
|
|
2051
2614
|
if (!fs.existsSync(logPath)) return void 0;
|
|
2052
2615
|
try {
|
|
@@ -2058,6 +2621,27 @@ var tailFile = (logPath, tailLines, fs) => {
|
|
|
2058
2621
|
return void 0;
|
|
2059
2622
|
}
|
|
2060
2623
|
};
|
|
2624
|
+
var resolveBreakerStore = (deps) => deps.breakerStore ?? createFileSystemCircuitBreakerStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2625
|
+
var resolveTodoStore = (deps) => deps.todoStore ?? createFileSystemTodoStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2626
|
+
var resolveNowMs = (deps) => typeof deps.nowMs === "function" ? deps.nowMs() : Date.now();
|
|
2627
|
+
var resolveTarget = (deps, agentKey) => typeof deps.resolveProviderTarget === "function" ? deps.resolveProviderTarget(agentKey) : agentKey;
|
|
2628
|
+
function buildProgressField(record, nowMs) {
|
|
2629
|
+
const activity = record.activity;
|
|
2630
|
+
if (!activity || isAgentRunTerminalStatus(record.status)) return {};
|
|
2631
|
+
const lastEventAt = Date.parse(activity.lastEventAt ?? "");
|
|
2632
|
+
const inFlight = activity.inFlight;
|
|
2633
|
+
const progress = {
|
|
2634
|
+
toolCalls: activity.counters?.toolCalls ?? 0,
|
|
2635
|
+
llmCalls: activity.counters?.llmCalls ?? 0,
|
|
2636
|
+
fileEdits: activity.counters?.fileEdits ?? 0,
|
|
2637
|
+
...Number.isFinite(lastEventAt) ? { idleMs: Math.max(0, nowMs - lastEventAt) } : {}
|
|
2638
|
+
};
|
|
2639
|
+
if (inFlight) {
|
|
2640
|
+
progress.inFlight = inFlight.name ? `${inFlight.kind}:${inFlight.name}` : inFlight.kind;
|
|
2641
|
+
if (Number.isFinite(inFlight.sinceMs)) progress.inFlightMs = Math.max(0, inFlight.sinceMs);
|
|
2642
|
+
}
|
|
2643
|
+
return { progress };
|
|
2644
|
+
}
|
|
2061
2645
|
function createCliStartAgentRunExecutor(deps = {}) {
|
|
2062
2646
|
return async (call) => {
|
|
2063
2647
|
const args = parseCallArgs(call);
|
|
@@ -2065,35 +2649,105 @@ function createCliStartAgentRunExecutor(deps = {}) {
|
|
|
2065
2649
|
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
2066
2650
|
if (!agentKey) throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
|
|
2067
2651
|
if (!task) throw new Error("startAgentRun: \u7F3A\u5C11\u6709\u6548\u7684 task \u6587\u672C\u63CF\u8FF0\u3002");
|
|
2652
|
+
const breakerStore = resolveBreakerStore(deps);
|
|
2653
|
+
const target = resolveTarget(deps, agentKey);
|
|
2654
|
+
const nowMs = resolveNowMs(deps);
|
|
2655
|
+
const activeBreaker = findActiveBreaker(
|
|
2656
|
+
nowMs,
|
|
2657
|
+
[breakerStore.get(target)].filter(Boolean),
|
|
2658
|
+
target
|
|
2659
|
+
);
|
|
2660
|
+
if (activeBreaker) {
|
|
2661
|
+
const resetsAt = activeBreaker.resetsAt;
|
|
2662
|
+
return {
|
|
2663
|
+
content: JSON.stringify({
|
|
2664
|
+
rejected: true,
|
|
2665
|
+
reason: "quota",
|
|
2666
|
+
provider: target,
|
|
2667
|
+
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
2668
|
+
message: `provider ${target} \u5904\u4E8E\u7194\u65AD\u671F\uFF08\u914D\u989D\u8017\u5C3D\uFF09\uFF0C\u5EFA\u8BAE\u6539\u6D3E\u5176\u5B83 provider\u3002`
|
|
2669
|
+
}),
|
|
2670
|
+
metadata: {
|
|
2671
|
+
displayData: `Run rejected \xB7 quota breaker active on ${target}`
|
|
2672
|
+
}
|
|
2673
|
+
};
|
|
2674
|
+
}
|
|
2068
2675
|
const message = typeof args.input === "undefined" ? task : `${task}
|
|
2069
2676
|
|
|
2070
2677
|
--- \u9644\u52A0\u8F93\u5165 ---
|
|
2071
2678
|
${JSON.stringify(args.input)}`;
|
|
2072
|
-
const rawArgs = [
|
|
2679
|
+
const rawArgs = [
|
|
2680
|
+
"--agent",
|
|
2681
|
+
agentKey,
|
|
2682
|
+
"--msg-file",
|
|
2683
|
+
"PLACEHOLDER",
|
|
2684
|
+
"--bg",
|
|
2685
|
+
// 非持久化派发(review 等一次性任务):透传 --ephemeral,run 完成后不留
|
|
2686
|
+
// dialog 记录。与 web 端 runAgentBackground 的 ephemeral: true 对齐。
|
|
2687
|
+
...args.ephemeral === true ? ["--ephemeral"] : []
|
|
2688
|
+
];
|
|
2073
2689
|
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
|
|
2690
|
+
const batchId = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
|
|
2691
|
+
const { runId, batchId: resolvedBatchId } = await spawnLocalBackgroundRun(
|
|
2075
2692
|
{
|
|
2076
2693
|
rawArgs,
|
|
2077
2694
|
commandPath: ["agent", "run"],
|
|
2078
2695
|
cliEntrypointPath: deps.cliEntrypoint,
|
|
2079
2696
|
agentKey,
|
|
2080
2697
|
...agentName ? { agentName } : {},
|
|
2698
|
+
...batchId ? { batchId } : {},
|
|
2699
|
+
...typeof args.parentDialogId === "string" && args.parentDialogId.trim() ? { parentDialogId: args.parentDialogId.trim() } : {},
|
|
2081
2700
|
cwd: deps.cwd ?? process.cwd(),
|
|
2082
2701
|
message,
|
|
2083
2702
|
output: noopOutput
|
|
2084
2703
|
},
|
|
2085
2704
|
deps
|
|
2086
2705
|
);
|
|
2087
|
-
const displayName = agentName
|
|
2706
|
+
const displayName = resolveRunLabel({ agentName, agentKey, runId });
|
|
2088
2707
|
const labels = agentRunCardLabels();
|
|
2708
|
+
const taskPreview = typeof args.task === "string" ? args.task.replace(/\s+/g, " ").trim().slice(0, TASK_PREVIEW_MAX) : "";
|
|
2709
|
+
const trackTodo = typeof args.trackTodo === "boolean" ? args.trackTodo : Boolean(resolvedBatchId);
|
|
2710
|
+
if (trackTodo) {
|
|
2711
|
+
try {
|
|
2712
|
+
const todoStore = resolveTodoStore(deps);
|
|
2713
|
+
const todoId = `todo-${resolvedBatchId}`;
|
|
2714
|
+
const existing = await todoStore.getTodo(todoId);
|
|
2715
|
+
const nowIso = new Date(nowMs).toISOString();
|
|
2716
|
+
const runIds = existing?.runIds ?? [];
|
|
2717
|
+
if (!runIds.includes(runId)) runIds.push(runId);
|
|
2718
|
+
const todo = {
|
|
2719
|
+
id: todoId,
|
|
2720
|
+
title: taskPreview || task.slice(0, 100),
|
|
2721
|
+
status: existing?.status ?? "pending",
|
|
2722
|
+
...existing?.specPath ? { specPath: existing.specPath } : {},
|
|
2723
|
+
...existing?.worktree ? { worktree: existing.worktree } : {},
|
|
2724
|
+
...existing?.branch ? { branch: existing.branch } : {},
|
|
2725
|
+
...deps.cwd ? { worktree: deps.cwd } : {},
|
|
2726
|
+
runIds,
|
|
2727
|
+
deps: existing?.deps ?? [],
|
|
2728
|
+
createdAt: existing?.createdAt ?? nowIso,
|
|
2729
|
+
updatedAt: nowIso
|
|
2730
|
+
};
|
|
2731
|
+
await todoStore.putTodo(todo);
|
|
2732
|
+
} catch {
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2089
2735
|
return {
|
|
2090
2736
|
content: JSON.stringify({
|
|
2091
2737
|
runId,
|
|
2092
2738
|
status: "running",
|
|
2093
|
-
|
|
2739
|
+
// batchId is always returned so the caller can later filter by it —
|
|
2740
|
+
// even when the caller didn't supply one, a fresh id was generated.
|
|
2741
|
+
batchId: resolvedBatchId,
|
|
2742
|
+
...agentName ? { agentName } : {},
|
|
2743
|
+
...taskPreview ? { taskPreview } : {}
|
|
2094
2744
|
}),
|
|
2095
2745
|
metadata: {
|
|
2096
|
-
displayData: formatStartRunCard(displayName, "running",
|
|
2746
|
+
displayData: formatStartRunCard(displayName, "running", {
|
|
2747
|
+
task: taskPreview,
|
|
2748
|
+
runId,
|
|
2749
|
+
labels
|
|
2750
|
+
})
|
|
2097
2751
|
}
|
|
2098
2752
|
};
|
|
2099
2753
|
};
|
|
@@ -2104,26 +2758,103 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2104
2758
|
const action = typeof args.action === "string" ? args.action : "";
|
|
2105
2759
|
const tailLines = typeof args.tailLines === "number" ? args.tailLines : 0;
|
|
2106
2760
|
if (action === "list") {
|
|
2107
|
-
|
|
2761
|
+
gcRunRecords(deps);
|
|
2762
|
+
const { runs: records, total, hasMore } = queryRunRecords(
|
|
2763
|
+
{
|
|
2764
|
+
...typeof args.batchId === "string" && args.batchId.trim() ? { batchId: args.batchId.trim() } : {},
|
|
2765
|
+
...typeof args.status === "string" && args.status.trim() ? { status: args.status.trim() } : typeof args.statusFilter === "string" && args.statusFilter.trim() ? { status: args.statusFilter.trim() } : {},
|
|
2766
|
+
...typeof args.limit === "number" ? { limit: args.limit } : {},
|
|
2767
|
+
...typeof args.offset === "number" ? { offset: args.offset } : {}
|
|
2768
|
+
},
|
|
2769
|
+
deps
|
|
2770
|
+
);
|
|
2108
2771
|
const runs = records.map((record2) => {
|
|
2109
|
-
const reconciled = checkStaleRun(record2.runId, deps) ?? record2;
|
|
2110
2772
|
return {
|
|
2111
|
-
runId:
|
|
2112
|
-
status:
|
|
2113
|
-
agentKey:
|
|
2114
|
-
...
|
|
2115
|
-
|
|
2116
|
-
|
|
2773
|
+
runId: record2.runId,
|
|
2774
|
+
status: record2.status,
|
|
2775
|
+
agentKey: record2.agentKey,
|
|
2776
|
+
...record2.agentName ? { agentName: record2.agentName } : {},
|
|
2777
|
+
...record2.batchId ? { batchId: record2.batchId } : {},
|
|
2778
|
+
pid: record2.pid ?? null,
|
|
2779
|
+
startedAt: record2.startedAt
|
|
2117
2780
|
};
|
|
2118
2781
|
});
|
|
2119
2782
|
const labels2 = agentRunCardLabels();
|
|
2783
|
+
const batchIdArg = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
|
|
2784
|
+
let batchSummary;
|
|
2785
|
+
if (batchIdArg && records.length > 0) {
|
|
2786
|
+
const batchRuns = records.map((r) => ({
|
|
2787
|
+
runId: r.runId,
|
|
2788
|
+
status: r.status,
|
|
2789
|
+
startedAt: r.startedAt,
|
|
2790
|
+
...r.agentName ? { agentName: r.agentName } : {}
|
|
2791
|
+
}));
|
|
2792
|
+
batchSummary = aggregateBatch({
|
|
2793
|
+
batchId: batchIdArg,
|
|
2794
|
+
runs: batchRuns,
|
|
2795
|
+
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2796
|
+
});
|
|
2797
|
+
}
|
|
2120
2798
|
return {
|
|
2121
|
-
content: JSON.stringify({
|
|
2799
|
+
content: JSON.stringify({
|
|
2800
|
+
runs,
|
|
2801
|
+
count: runs.length,
|
|
2802
|
+
total,
|
|
2803
|
+
hasMore,
|
|
2804
|
+
...batchSummary?.summary ? { batchSummary: batchSummary.summary } : {}
|
|
2805
|
+
}),
|
|
2122
2806
|
metadata: {
|
|
2123
2807
|
displayData: formatListRunsCard(runs, labels2)
|
|
2124
2808
|
}
|
|
2125
2809
|
};
|
|
2126
2810
|
}
|
|
2811
|
+
if (action === "todo") {
|
|
2812
|
+
const todoStore = resolveTodoStore(deps);
|
|
2813
|
+
const statusesRaw = typeof args.status === "string" ? args.status.trim() : void 0;
|
|
2814
|
+
const filter = statusesRaw && statusesRaw !== "all" ? { statuses: statusesRaw.split(",").map((s) => s.trim()).filter(Boolean) } : void 0;
|
|
2815
|
+
const todos = await todoStore.listTodos(filter);
|
|
2816
|
+
const enriched = await Promise.all(
|
|
2817
|
+
todos.map(async (todo) => {
|
|
2818
|
+
const runSummaries = [];
|
|
2819
|
+
for (const rid of todo.runIds) {
|
|
2820
|
+
const rec = findRunRecord(rid, deps);
|
|
2821
|
+
if (!rec) continue;
|
|
2822
|
+
runSummaries.push({
|
|
2823
|
+
runId: rec.runId,
|
|
2824
|
+
status: rec.status,
|
|
2825
|
+
startedAt: rec.startedAt,
|
|
2826
|
+
...rec.agentName ? { agentName: rec.agentName } : {}
|
|
2827
|
+
});
|
|
2828
|
+
}
|
|
2829
|
+
const derived = deriveTodoStatus({
|
|
2830
|
+
todo: { id: todo.id, status: todo.status },
|
|
2831
|
+
runs: runSummaries,
|
|
2832
|
+
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2833
|
+
});
|
|
2834
|
+
return {
|
|
2835
|
+
id: todo.id,
|
|
2836
|
+
title: todo.title,
|
|
2837
|
+
status: derived.status,
|
|
2838
|
+
runIds: todo.runIds,
|
|
2839
|
+
...derived.blockedReason ? { blockedReason: derived.blockedReason } : {},
|
|
2840
|
+
...derived.latestRun ? { latestRunId: derived.latestRun.runId, latestRunStatus: derived.latestRun.status } : {},
|
|
2841
|
+
updatedAt: todo.updatedAt
|
|
2842
|
+
};
|
|
2843
|
+
})
|
|
2844
|
+
);
|
|
2845
|
+
return {
|
|
2846
|
+
content: JSON.stringify({ todos: enriched, count: enriched.length }),
|
|
2847
|
+
metadata: {
|
|
2848
|
+
displayData: formatListRunsCard(
|
|
2849
|
+
enriched.map((t2) => ({
|
|
2850
|
+
agentName: t2.title,
|
|
2851
|
+
status: t2.status
|
|
2852
|
+
})),
|
|
2853
|
+
agentRunCardLabels()
|
|
2854
|
+
)
|
|
2855
|
+
}
|
|
2856
|
+
};
|
|
2857
|
+
}
|
|
2127
2858
|
if (action !== "status" && action !== "stop") {
|
|
2128
2859
|
throw new Error(`controlAgentRun: \u672A\u77E5 action "${action}"\u3002`);
|
|
2129
2860
|
}
|
|
@@ -2139,9 +2870,28 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2139
2870
|
if (action === "status") {
|
|
2140
2871
|
const reconciled = checkStaleRun(record.runId, deps) ?? record;
|
|
2141
2872
|
const logTail = tailLines > 0 ? tailFile(record.logPath, tailLines, resolveFs(deps)) : void 0;
|
|
2142
|
-
const name = reconciled
|
|
2873
|
+
const name = resolveRunLabel(reconciled);
|
|
2143
2874
|
const logLines = logTail ? logTail.split("\n") : void 0;
|
|
2144
2875
|
const labels2 = agentRunCardLabels();
|
|
2876
|
+
if (reconciled.status === "failed" || reconciled.status === "orphaned") {
|
|
2877
|
+
try {
|
|
2878
|
+
const failureSource = logTail ?? reconciled.note ?? "";
|
|
2879
|
+
const failureInfo = classifyRunFailure(
|
|
2880
|
+
failureSource || reconciled.status
|
|
2881
|
+
);
|
|
2882
|
+
if (failureInfo.reason === "quota") {
|
|
2883
|
+
const t2 = resolveTarget(deps, reconciled.agentKey);
|
|
2884
|
+
const entry = buildBreakerEntry(
|
|
2885
|
+
resolveNowMs(deps),
|
|
2886
|
+
t2,
|
|
2887
|
+
"quota",
|
|
2888
|
+
failureInfo.retryAfterMs
|
|
2889
|
+
);
|
|
2890
|
+
resolveBreakerStore(deps).set(entry);
|
|
2891
|
+
}
|
|
2892
|
+
} catch {
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2145
2895
|
return {
|
|
2146
2896
|
content: JSON.stringify({
|
|
2147
2897
|
runId: reconciled.runId,
|
|
@@ -2162,11 +2912,26 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2162
2912
|
// indistinguishable from a hung run without this field. Surfacing
|
|
2163
2913
|
// dialogId gives the caller a reliable way to fetch the result.
|
|
2164
2914
|
...reconciled.dialogId ? { dialogId: reconciled.dialogId } : {},
|
|
2915
|
+
// Progress is what makes tailLines:0 an actual answer to "is it
|
|
2916
|
+
// stuck?". Without it a poll returns `running` and a pid, so the only
|
|
2917
|
+
// way to tell a working run from a wedged one was to pull 30 lines of
|
|
2918
|
+
// log — the exact thing the orchestration prompt tells the model not
|
|
2919
|
+
// to do. The registry has been recording this all along and `nolo
|
|
2920
|
+
// agent status` has been printing it; only the tool was blind.
|
|
2921
|
+
...buildProgressField(reconciled, resolveNowMs(deps)),
|
|
2165
2922
|
...logTail !== void 0 ? { logTail } : {},
|
|
2166
2923
|
...logLines ? { logLines } : {}
|
|
2167
2924
|
}),
|
|
2168
2925
|
metadata: {
|
|
2169
|
-
displayData: formatStatusRunCard(name, reconciled.status, {
|
|
2926
|
+
displayData: formatStatusRunCard(name, reconciled.status, {
|
|
2927
|
+
runId: reconciled.runId,
|
|
2928
|
+
timing: {
|
|
2929
|
+
startedAt: readTimestamp(reconciled.startedAt),
|
|
2930
|
+
finishedAt: readTimestamp(reconciled.endedAt)
|
|
2931
|
+
},
|
|
2932
|
+
logLines,
|
|
2933
|
+
labels: labels2
|
|
2934
|
+
})
|
|
2170
2935
|
}
|
|
2171
2936
|
};
|
|
2172
2937
|
}
|
|
@@ -2304,7 +3069,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2304
3069
|
}
|
|
2305
3070
|
};
|
|
2306
3071
|
},
|
|
2307
|
-
|
|
3072
|
+
ask_user: async (call) => {
|
|
2308
3073
|
const parsedArgs = (() => {
|
|
2309
3074
|
try {
|
|
2310
3075
|
return JSON.parse(call.arguments || "{}");
|
|
@@ -2320,8 +3085,8 @@ function buildLocalToolExecutors(args) {
|
|
|
2320
3085
|
if (!hasQuestions && (!question || choices.length === 0)) {
|
|
2321
3086
|
return {
|
|
2322
3087
|
content: JSON.stringify({
|
|
2323
|
-
error: "
|
|
2324
|
-
detail: "
|
|
3088
|
+
error: "ask_user",
|
|
3089
|
+
detail: "ask_user \u9700\u8981 question+choices \u6216 questions\u3002"
|
|
2325
3090
|
}),
|
|
2326
3091
|
metadata: { uiAskChoice: true, error: true }
|
|
2327
3092
|
};
|
|
@@ -2337,7 +3102,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2337
3102
|
if (result.kind === "multi-submitted") {
|
|
2338
3103
|
return {
|
|
2339
3104
|
content: JSON.stringify({
|
|
2340
|
-
type: "
|
|
3105
|
+
type: "ask_user",
|
|
2341
3106
|
question,
|
|
2342
3107
|
choices,
|
|
2343
3108
|
blocking,
|
|
@@ -2354,7 +3119,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2354
3119
|
if (result.kind === "selected") {
|
|
2355
3120
|
return {
|
|
2356
3121
|
content: JSON.stringify({
|
|
2357
|
-
type: "
|
|
3122
|
+
type: "ask_user",
|
|
2358
3123
|
question,
|
|
2359
3124
|
choices,
|
|
2360
3125
|
blocking,
|
|
@@ -2369,7 +3134,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2369
3134
|
}
|
|
2370
3135
|
return {
|
|
2371
3136
|
content: JSON.stringify({
|
|
2372
|
-
type: "
|
|
3137
|
+
type: "ask_user",
|
|
2373
3138
|
question,
|
|
2374
3139
|
choices,
|
|
2375
3140
|
blocking,
|
|
@@ -2384,7 +3149,7 @@ function buildLocalToolExecutors(args) {
|
|
|
2384
3149
|
}
|
|
2385
3150
|
return {
|
|
2386
3151
|
content: JSON.stringify({
|
|
2387
|
-
type: "
|
|
3152
|
+
type: "ask_user",
|
|
2388
3153
|
question,
|
|
2389
3154
|
choices,
|
|
2390
3155
|
blocking,
|
|
@@ -2448,19 +3213,22 @@ function resolveAntigravityWireModel(logicalModelId) {
|
|
|
2448
3213
|
return { wireModelId: id };
|
|
2449
3214
|
}
|
|
2450
3215
|
|
|
2451
|
-
// packages/agent-runtime/
|
|
2452
|
-
var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
|
|
3216
|
+
// packages/agent-runtime/geminiNativeShared.ts
|
|
2453
3217
|
var SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
2454
|
-
function
|
|
3218
|
+
function isGemini3Model(modelId) {
|
|
2455
3219
|
return modelId.includes("gemini-3");
|
|
2456
3220
|
}
|
|
2457
3221
|
function messageText(content) {
|
|
2458
3222
|
if (typeof content === "string") return content;
|
|
2459
3223
|
if (!Array.isArray(content)) return "";
|
|
2460
|
-
return content.filter(
|
|
3224
|
+
return content.filter(
|
|
3225
|
+
(part) => part?.type === "text"
|
|
3226
|
+
).map((part) => part.text).join("\n").trim();
|
|
2461
3227
|
}
|
|
2462
3228
|
function parseDataUrlToInlineData(url) {
|
|
2463
|
-
const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
|
|
3229
|
+
const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
|
|
3230
|
+
url
|
|
3231
|
+
);
|
|
2464
3232
|
if (!match) return null;
|
|
2465
3233
|
return { mimeType: match[1], data: match[2] };
|
|
2466
3234
|
}
|
|
@@ -2477,7 +3245,7 @@ function extractInlineDataParts(content) {
|
|
|
2477
3245
|
}
|
|
2478
3246
|
return parts;
|
|
2479
3247
|
}
|
|
2480
|
-
function
|
|
3248
|
+
function convertOpenAiMessagesToGemini(messages, options) {
|
|
2481
3249
|
const contents = [];
|
|
2482
3250
|
const systemTexts = [];
|
|
2483
3251
|
const toolNamesById = /* @__PURE__ */ new Map();
|
|
@@ -2493,9 +3261,11 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2493
3261
|
};
|
|
2494
3262
|
const flushPendingFunctionCalls = () => {
|
|
2495
3263
|
if (pendingFunctionCalls.length === 0) return;
|
|
2496
|
-
const dummyResponses = pendingFunctionCalls.map(
|
|
2497
|
-
|
|
2498
|
-
|
|
3264
|
+
const dummyResponses = pendingFunctionCalls.map(
|
|
3265
|
+
({ name }) => ({
|
|
3266
|
+
functionResponse: { name, response: { output: "{}" } }
|
|
3267
|
+
})
|
|
3268
|
+
);
|
|
2499
3269
|
pendingFunctionCalls = [];
|
|
2500
3270
|
pushOrMergeContent("user", dummyResponses);
|
|
2501
3271
|
};
|
|
@@ -2504,13 +3274,17 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2504
3274
|
const role = String(raw.role);
|
|
2505
3275
|
const content = "content" in raw ? raw.content : null;
|
|
2506
3276
|
if (role === "system") {
|
|
2507
|
-
const text = messageText(
|
|
3277
|
+
const text = messageText(
|
|
3278
|
+
content
|
|
3279
|
+
);
|
|
2508
3280
|
if (text) systemTexts.push(text);
|
|
2509
3281
|
continue;
|
|
2510
3282
|
}
|
|
2511
3283
|
if (role === "user") {
|
|
2512
3284
|
flushPendingFunctionCalls();
|
|
2513
|
-
const text = messageText(
|
|
3285
|
+
const text = messageText(
|
|
3286
|
+
content
|
|
3287
|
+
);
|
|
2514
3288
|
const imageParts = extractInlineDataParts(
|
|
2515
3289
|
content
|
|
2516
3290
|
);
|
|
@@ -2524,7 +3298,9 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2524
3298
|
if (role === "assistant") {
|
|
2525
3299
|
flushPendingFunctionCalls();
|
|
2526
3300
|
const parts = [];
|
|
2527
|
-
const text = messageText(
|
|
3301
|
+
const text = messageText(
|
|
3302
|
+
content
|
|
3303
|
+
);
|
|
2528
3304
|
if (text) parts.push({ text });
|
|
2529
3305
|
const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
|
|
2530
3306
|
for (const call of toolCalls) {
|
|
@@ -2534,17 +3310,20 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2534
3310
|
toolNamesById.set(id, name);
|
|
2535
3311
|
pendingFunctionCalls.push({ name, id });
|
|
2536
3312
|
const realSignature = typeof call.thought_signature === "string" && call.thought_signature ? call.thought_signature : void 0;
|
|
2537
|
-
const isFirstFunctionCallPart = !parts.some(
|
|
2538
|
-
|
|
3313
|
+
const isFirstFunctionCallPart = !parts.some(
|
|
3314
|
+
(p) => "functionCall" in p
|
|
3315
|
+
);
|
|
3316
|
+
const signature = realSignature ?? (options.attachSkipThoughtSignature && isFirstFunctionCallPart ? SKIP_THOUGHT_SIGNATURE : void 0);
|
|
3317
|
+
const part = {
|
|
2539
3318
|
functionCall: {
|
|
2540
3319
|
name,
|
|
2541
|
-
args:
|
|
2542
|
-
id
|
|
3320
|
+
args: parseToolArgs(call.function?.arguments),
|
|
3321
|
+
...id ? { id } : {}
|
|
2543
3322
|
},
|
|
2544
|
-
...
|
|
2545
|
-
}
|
|
3323
|
+
...signature ? { thoughtSignature: signature } : {}
|
|
3324
|
+
};
|
|
3325
|
+
parts.push(part);
|
|
2546
3326
|
}
|
|
2547
|
-
if (parts.length === 0) continue;
|
|
2548
3327
|
pushOrMergeContent("model", parts);
|
|
2549
3328
|
continue;
|
|
2550
3329
|
}
|
|
@@ -2562,14 +3341,39 @@ function convertOpenAiMessagesToCca(messages, options) {
|
|
|
2562
3341
|
}
|
|
2563
3342
|
const output = messageText(content) || "{}";
|
|
2564
3343
|
pushOrMergeContent("user", [
|
|
2565
|
-
{
|
|
3344
|
+
{
|
|
3345
|
+
functionResponse: {
|
|
3346
|
+
name,
|
|
3347
|
+
response: { output },
|
|
3348
|
+
// 保留 OpenAI tool_call_id:antigravity Cloud Code Assist 网关把
|
|
3349
|
+
// Gemini contents 转成 Claude messages 时需要 functionResponse →
|
|
3350
|
+
// tool_result 的 tool_use_id;缺 id 时网关报
|
|
3351
|
+
// "tool_result.tool_use_id: Field required"(HTTP 400)。
|
|
3352
|
+
...toolCallId ? { id: toolCallId } : {}
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
2566
3355
|
]);
|
|
2567
3356
|
}
|
|
2568
3357
|
}
|
|
2569
3358
|
flushPendingFunctionCalls();
|
|
2570
3359
|
return { contents, systemTexts };
|
|
2571
3360
|
}
|
|
2572
|
-
function
|
|
3361
|
+
function parseToolArgs(raw) {
|
|
3362
|
+
if (typeof raw === "string") {
|
|
3363
|
+
try {
|
|
3364
|
+
const parsed = JSON.parse(raw);
|
|
3365
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3366
|
+
return parsed;
|
|
3367
|
+
}
|
|
3368
|
+
} catch {
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
3372
|
+
return raw;
|
|
3373
|
+
}
|
|
3374
|
+
return {};
|
|
3375
|
+
}
|
|
3376
|
+
function convertOpenAiToolsToGemini(tools) {
|
|
2573
3377
|
if (!Array.isArray(tools) || tools.length === 0) return void 0;
|
|
2574
3378
|
const declarations = [];
|
|
2575
3379
|
for (const tool of tools) {
|
|
@@ -2586,6 +3390,97 @@ function convertOpenAiTools(tools) {
|
|
|
2586
3390
|
if (declarations.length === 0) return void 0;
|
|
2587
3391
|
return [{ functionDeclarations: declarations }];
|
|
2588
3392
|
}
|
|
3393
|
+
function accumulateGeminiChunks(chunks) {
|
|
3394
|
+
let text = "";
|
|
3395
|
+
const toolCalls = [];
|
|
3396
|
+
let usage;
|
|
3397
|
+
let pendingThoughtSignature;
|
|
3398
|
+
for (const chunk of chunks) {
|
|
3399
|
+
if (!chunk || typeof chunk !== "object") continue;
|
|
3400
|
+
const response = "response" in chunk && chunk.response && typeof chunk.response === "object" ? chunk.response : chunk;
|
|
3401
|
+
if ("usageMetadata" in response && response.usageMetadata && typeof response.usageMetadata === "object") {
|
|
3402
|
+
const meta = response.usageMetadata;
|
|
3403
|
+
const prompt = typeof meta.promptTokenCount === "number" ? meta.promptTokenCount : 0;
|
|
3404
|
+
const candidates2 = typeof meta.candidatesTokenCount === "number" ? meta.candidatesTokenCount : 0;
|
|
3405
|
+
const total = typeof meta.totalTokenCount === "number" ? meta.totalTokenCount : prompt + candidates2;
|
|
3406
|
+
usage = {
|
|
3407
|
+
prompt_tokens: prompt,
|
|
3408
|
+
completion_tokens: candidates2,
|
|
3409
|
+
total_tokens: total
|
|
3410
|
+
};
|
|
3411
|
+
}
|
|
3412
|
+
const candidates = Array.isArray(response.candidates) ? response.candidates : [];
|
|
3413
|
+
for (const candidate of candidates) {
|
|
3414
|
+
if (!candidate || typeof candidate !== "object") continue;
|
|
3415
|
+
const parts = Array.isArray(
|
|
3416
|
+
candidate.content?.parts
|
|
3417
|
+
) ? candidate.content.parts : [];
|
|
3418
|
+
for (const part of parts) {
|
|
3419
|
+
if (!part || typeof part !== "object") continue;
|
|
3420
|
+
const partSignature = part.thoughtSignature;
|
|
3421
|
+
if ("text" in part && typeof part.text === "string") {
|
|
3422
|
+
const piece = part.text;
|
|
3423
|
+
if (!part.thought) {
|
|
3424
|
+
text += piece;
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
if (part.thought && typeof partSignature === "string" && partSignature) {
|
|
3428
|
+
pendingThoughtSignature = partSignature;
|
|
3429
|
+
}
|
|
3430
|
+
if ("functionCall" in part && part.functionCall) {
|
|
3431
|
+
const call = part.functionCall;
|
|
3432
|
+
const name = typeof call.name === "string" ? call.name : "tool";
|
|
3433
|
+
const id = typeof call.id === "string" ? call.id : `${name}_${toolCalls.length}`;
|
|
3434
|
+
const argsObj = call.args && typeof call.args === "object" ? call.args : {};
|
|
3435
|
+
const resolvedSignature = typeof partSignature === "string" && partSignature ? partSignature : pendingThoughtSignature;
|
|
3436
|
+
pendingThoughtSignature = void 0;
|
|
3437
|
+
toolCalls.push({
|
|
3438
|
+
id,
|
|
3439
|
+
type: "function",
|
|
3440
|
+
function: { name, arguments: JSON.stringify(argsObj) },
|
|
3441
|
+
...typeof resolvedSignature === "string" && resolvedSignature ? { thought_signature: resolvedSignature } : {}
|
|
3442
|
+
});
|
|
3443
|
+
}
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
return { text, toolCalls, usage };
|
|
3448
|
+
}
|
|
3449
|
+
function shouldUseGeminiNativeToolRoute(provider, model, tools, isImageModel) {
|
|
3450
|
+
return provider === "google" && !isImageModel(model) && isGemini3Model(model) && Array.isArray(tools) && tools.length > 0;
|
|
3451
|
+
}
|
|
3452
|
+
function buildGeminiGenerateContentRequest(args) {
|
|
3453
|
+
const { contents, systemTexts } = convertOpenAiMessagesToGemini(
|
|
3454
|
+
args.messages,
|
|
3455
|
+
{ attachSkipThoughtSignature: args.attachSkipThoughtSignature }
|
|
3456
|
+
);
|
|
3457
|
+
const request = { contents };
|
|
3458
|
+
if (systemTexts.length > 0) {
|
|
3459
|
+
request.systemInstruction = {
|
|
3460
|
+
role: "user",
|
|
3461
|
+
parts: systemTexts.map((text) => ({ text }))
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
const toolsResult = convertOpenAiToolsToGemini(args.tools);
|
|
3465
|
+
if (toolsResult) {
|
|
3466
|
+
request.tools = toolsResult;
|
|
3467
|
+
request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
|
|
3468
|
+
}
|
|
3469
|
+
const generationConfig = {};
|
|
3470
|
+
if (typeof args.maxTokens === "number" && args.maxTokens > 0) {
|
|
3471
|
+
generationConfig.maxOutputTokens = args.maxTokens;
|
|
3472
|
+
}
|
|
3473
|
+
if (typeof args.temperature === "number") {
|
|
3474
|
+
generationConfig.temperature = args.temperature;
|
|
3475
|
+
}
|
|
3476
|
+
if (Object.keys(generationConfig).length > 0) {
|
|
3477
|
+
request.generationConfig = generationConfig;
|
|
3478
|
+
}
|
|
3479
|
+
return request;
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3482
|
+
// packages/agent-runtime/antigravityCloudCodeProvider.ts
|
|
3483
|
+
var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
|
|
2589
3484
|
function buildCloudCodeAssistPayload(args) {
|
|
2590
3485
|
const projectId = readAntigravityProjectId(args.metadata);
|
|
2591
3486
|
if (!projectId) {
|
|
@@ -2596,8 +3491,9 @@ function buildCloudCodeAssistPayload(args) {
|
|
|
2596
3491
|
const logicalModel = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gemini-3.1-pro";
|
|
2597
3492
|
const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
|
|
2598
3493
|
const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
|
|
2599
|
-
const
|
|
2600
|
-
|
|
3494
|
+
const isClaude = model.toLowerCase().includes("claude");
|
|
3495
|
+
const { contents, systemTexts } = convertOpenAiMessagesToGemini(rawMessages, {
|
|
3496
|
+
attachSkipThoughtSignature: isGemini3Model(model)
|
|
2601
3497
|
});
|
|
2602
3498
|
if (contents.length === 0) {
|
|
2603
3499
|
throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
|
|
@@ -2611,7 +3507,7 @@ function buildCloudCodeAssistPayload(args) {
|
|
|
2611
3507
|
parts: systemTexts.map((text) => ({ text }))
|
|
2612
3508
|
};
|
|
2613
3509
|
}
|
|
2614
|
-
const tools =
|
|
3510
|
+
const tools = convertOpenAiToolsToGemini(
|
|
2615
3511
|
Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
|
|
2616
3512
|
);
|
|
2617
3513
|
if (tools) {
|
|
@@ -2631,83 +3527,31 @@ function buildCloudCodeAssistPayload(args) {
|
|
|
2631
3527
|
request.generationConfig = generationConfig;
|
|
2632
3528
|
}
|
|
2633
3529
|
const agentId = randomUUID();
|
|
2634
|
-
const trajectoryId = randomUUID();
|
|
2635
|
-
const step = 2;
|
|
2636
|
-
const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
|
|
2637
|
-
const
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
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) {
|
|
2662
|
-
let text = "";
|
|
2663
|
-
const toolCalls = [];
|
|
2664
|
-
let usage;
|
|
2665
|
-
for (const chunk of chunks) {
|
|
2666
|
-
if (!chunk || typeof chunk !== "object") continue;
|
|
2667
|
-
const response = "response" in chunk && chunk.response && typeof chunk.response === "object" ? chunk.response : chunk;
|
|
2668
|
-
if ("usageMetadata" in response && response.usageMetadata && typeof response.usageMetadata === "object") {
|
|
2669
|
-
const meta = response.usageMetadata;
|
|
2670
|
-
const prompt = typeof meta.promptTokenCount === "number" ? meta.promptTokenCount : 0;
|
|
2671
|
-
const candidates2 = typeof meta.candidatesTokenCount === "number" ? meta.candidatesTokenCount : 0;
|
|
2672
|
-
const total = typeof meta.totalTokenCount === "number" ? meta.totalTokenCount : prompt + candidates2;
|
|
2673
|
-
usage = {
|
|
2674
|
-
prompt_tokens: prompt,
|
|
2675
|
-
completion_tokens: candidates2,
|
|
2676
|
-
total_tokens: total
|
|
2677
|
-
};
|
|
2678
|
-
}
|
|
2679
|
-
const candidates = Array.isArray(response.candidates) ? response.candidates : [];
|
|
2680
|
-
for (const candidate of candidates) {
|
|
2681
|
-
if (!candidate || typeof candidate !== "object" || !("content" in candidate)) continue;
|
|
2682
|
-
const content = candidate.content;
|
|
2683
|
-
if (!content || typeof content !== "object" || !("parts" in content)) continue;
|
|
2684
|
-
const parts = content.parts;
|
|
2685
|
-
if (!Array.isArray(parts)) continue;
|
|
2686
|
-
for (const part of parts) {
|
|
2687
|
-
if (!part || typeof part !== "object") continue;
|
|
2688
|
-
const partSignature = part.thoughtSignature;
|
|
2689
|
-
if ("text" in part && typeof part.text === "string") {
|
|
2690
|
-
const piece = part.text;
|
|
2691
|
-
if (!part.thought) {
|
|
2692
|
-
text += piece;
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
if ("functionCall" in part && part.functionCall) {
|
|
2696
|
-
const call = part.functionCall;
|
|
2697
|
-
const name = typeof call.name === "string" ? call.name : "tool";
|
|
2698
|
-
const id = typeof call.id === "string" ? call.id : `${name}_${toolCalls.length}`;
|
|
2699
|
-
const argsObj = asRecordOrEmpty(call.args);
|
|
2700
|
-
toolCalls.push({
|
|
2701
|
-
id,
|
|
2702
|
-
type: "function",
|
|
2703
|
-
function: { name, arguments: JSON.stringify(argsObj) },
|
|
2704
|
-
...typeof partSignature === "string" && partSignature ? { thought_signature: partSignature } : {}
|
|
2705
|
-
});
|
|
2706
|
-
}
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
3530
|
+
const trajectoryId = randomUUID();
|
|
3531
|
+
const step = 2;
|
|
3532
|
+
const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
|
|
3533
|
+
const labels = {
|
|
3534
|
+
trajectory_id: trajectoryId,
|
|
3535
|
+
last_step_index: String(step - 1),
|
|
3536
|
+
used_claude: String(isClaude),
|
|
3537
|
+
used_claude_conservative: String(isClaude)
|
|
3538
|
+
};
|
|
3539
|
+
if (profile?.modelEnum) {
|
|
3540
|
+
labels.model_enum = profile.modelEnum;
|
|
2709
3541
|
}
|
|
2710
|
-
|
|
3542
|
+
request.labels = labels;
|
|
3543
|
+
request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
|
|
3544
|
+
return {
|
|
3545
|
+
url: `${resolveAntigravityCloudCodeBaseUrl(args.agentConfig.customProviderUrl)}${STREAM_PATH}`,
|
|
3546
|
+
envelope: {
|
|
3547
|
+
project: projectId,
|
|
3548
|
+
model,
|
|
3549
|
+
request,
|
|
3550
|
+
requestId,
|
|
3551
|
+
requestType: "agent",
|
|
3552
|
+
userAgent: "antigravity"
|
|
3553
|
+
}
|
|
3554
|
+
};
|
|
2711
3555
|
}
|
|
2712
3556
|
async function readSseJsonChunks(response) {
|
|
2713
3557
|
return readSseDataValues(response, parseSseDataLineJson);
|
|
@@ -2733,7 +3577,7 @@ async function fetchAntigravityCloudCodeCompletion(args) {
|
|
|
2733
3577
|
};
|
|
2734
3578
|
}
|
|
2735
3579
|
const chunks = await readSseJsonChunks(response);
|
|
2736
|
-
const { text, toolCalls, usage } =
|
|
3580
|
+
const { text, toolCalls, usage } = accumulateGeminiChunks(chunks);
|
|
2737
3581
|
const message = {
|
|
2738
3582
|
role: "assistant",
|
|
2739
3583
|
content: text || null
|
|
@@ -2769,28 +3613,94 @@ var CLAUDE_CODE_IDENTITY_PATTERNS = [
|
|
|
2769
3613
|
CLAUDE_CODE_SYSTEM_INSTRUCTION,
|
|
2770
3614
|
"You are Claude Code"
|
|
2771
3615
|
];
|
|
3616
|
+
var REASONING_EFFORT_TO_BUDGET = {
|
|
3617
|
+
minimal: 2048,
|
|
3618
|
+
low: 4096,
|
|
3619
|
+
medium: 8192,
|
|
3620
|
+
high: 16384,
|
|
3621
|
+
xhigh: 32e3,
|
|
3622
|
+
max: 32e3
|
|
3623
|
+
};
|
|
3624
|
+
function resolveThinkingBudget(effort) {
|
|
3625
|
+
if (!effort) return void 0;
|
|
3626
|
+
const normalized = effort.toLowerCase();
|
|
3627
|
+
if (normalized === "none" || normalized === "off") return void 0;
|
|
3628
|
+
return REASONING_EFFORT_TO_BUDGET[normalized];
|
|
3629
|
+
}
|
|
3630
|
+
var DEFAULT_THINKING_EFFORT = "medium";
|
|
3631
|
+
var DEFAULT_ENABLED_BUDGET = 8192;
|
|
3632
|
+
var DEFAULT_ENABLE_THINKING_BUDGET = 8e3;
|
|
3633
|
+
var ANTHROPIC_EFFORT_ALIASES = { minimal: "low" };
|
|
3634
|
+
function resolveThinkingSpec(input) {
|
|
3635
|
+
const { model, maxTokens } = input;
|
|
3636
|
+
const normalizedEffort = input.reasoningEffort?.toLowerCase();
|
|
3637
|
+
const effortDisabled = normalizedEffort === "none" || normalizedEffort === "off";
|
|
3638
|
+
const effectiveEffort = normalizedEffort !== void 0 && !effortDisabled ? ANTHROPIC_EFFORT_ALIASES[normalizedEffort] ?? normalizedEffort : DEFAULT_THINKING_EFFORT;
|
|
3639
|
+
let thinkingBlock;
|
|
3640
|
+
let outputConfig;
|
|
3641
|
+
let finalMaxTokens = maxTokens;
|
|
3642
|
+
let finalTemperature = input.temperature;
|
|
3643
|
+
if (isAdaptiveThinkingModelId(model)) {
|
|
3644
|
+
if (effortDisabled) {
|
|
3645
|
+
thinkingBlock = { type: "disabled" };
|
|
3646
|
+
} else {
|
|
3647
|
+
thinkingBlock = { type: "adaptive", display: "summarized" };
|
|
3648
|
+
outputConfig = { effort: effectiveEffort };
|
|
3649
|
+
}
|
|
3650
|
+
} else {
|
|
3651
|
+
const injected = input.injectedThinking;
|
|
3652
|
+
const injectedBudget = injected?.type === "enabled" && typeof injected.budget_tokens === "number" ? injected.budget_tokens : void 0;
|
|
3653
|
+
const effortBudget = resolveThinkingBudget(input.reasoningEffort);
|
|
3654
|
+
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;
|
|
3655
|
+
const thinkingBudget = effortBudget ?? fallbackBudget;
|
|
3656
|
+
if (thinkingBudget !== void 0) {
|
|
3657
|
+
thinkingBlock = { type: "enabled", budget_tokens: thinkingBudget };
|
|
3658
|
+
finalMaxTokens = Math.max(maxTokens, thinkingBudget + 1);
|
|
3659
|
+
finalTemperature = 1;
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
return {
|
|
3663
|
+
thinkingBlock,
|
|
3664
|
+
outputConfig,
|
|
3665
|
+
maxTokens: finalMaxTokens,
|
|
3666
|
+
temperature: finalTemperature
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
2772
3669
|
function stringValue(value) {
|
|
2773
3670
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
2774
3671
|
}
|
|
3672
|
+
function isCacheControl(value) {
|
|
3673
|
+
return Boolean(
|
|
3674
|
+
value && typeof value === "object" && !Array.isArray(value) && typeof value.type === "string"
|
|
3675
|
+
);
|
|
3676
|
+
}
|
|
2775
3677
|
function toAnthropicContent(content) {
|
|
2776
|
-
if (typeof content === "string")
|
|
3678
|
+
if (typeof content === "string") {
|
|
3679
|
+
return content.length > 0 ? [{ type: "text", text: content }] : [];
|
|
3680
|
+
}
|
|
2777
3681
|
if (!Array.isArray(content)) return [];
|
|
2778
3682
|
const blocks = [];
|
|
2779
3683
|
for (const raw of content) {
|
|
2780
3684
|
if (!raw || typeof raw !== "object") continue;
|
|
2781
3685
|
const part = raw;
|
|
2782
3686
|
if ((part.type === "text" || part.type === "input_text") && typeof part.text === "string") {
|
|
2783
|
-
|
|
3687
|
+
if (part.text.length > 0) {
|
|
3688
|
+
const block2 = { type: "text", text: part.text };
|
|
3689
|
+
if (isCacheControl(part.cache_control)) block2.cache_control = part.cache_control;
|
|
3690
|
+
blocks.push(block2);
|
|
3691
|
+
}
|
|
2784
3692
|
continue;
|
|
2785
3693
|
}
|
|
2786
3694
|
if (part.type !== "image_url") continue;
|
|
2787
3695
|
const imageUrl = typeof part.image_url === "string" ? part.image_url : stringValue(part.image_url?.url);
|
|
2788
3696
|
if (!imageUrl) continue;
|
|
2789
3697
|
const dataMatch = imageUrl.match(/^data:([^;,]+);base64,(.+)$/s);
|
|
2790
|
-
|
|
3698
|
+
const block = {
|
|
2791
3699
|
type: "image",
|
|
2792
3700
|
source: dataMatch ? { type: "base64", media_type: dataMatch[1], data: dataMatch[2] } : { type: "url", url: imageUrl }
|
|
2793
|
-
}
|
|
3701
|
+
};
|
|
3702
|
+
if (isCacheControl(part.cache_control)) block.cache_control = part.cache_control;
|
|
3703
|
+
blocks.push(block);
|
|
2794
3704
|
}
|
|
2795
3705
|
return blocks;
|
|
2796
3706
|
}
|
|
@@ -2824,7 +3734,15 @@ function buildAnthropicMessagesBody(args) {
|
|
|
2824
3734
|
const message = raw;
|
|
2825
3735
|
const role = String(message.role ?? "");
|
|
2826
3736
|
if (role === "system" || role === "developer") {
|
|
2827
|
-
|
|
3737
|
+
const stablePrefixChars = Number(message.stable_prefix_chars);
|
|
3738
|
+
if (typeof message.content === "string" && Number.isFinite(stablePrefixChars) && stablePrefixChars > 0 && stablePrefixChars <= message.content.length) {
|
|
3739
|
+
const stable = message.content.slice(0, stablePrefixChars);
|
|
3740
|
+
const dynamic = message.content.slice(stablePrefixChars);
|
|
3741
|
+
system.push({ type: "text", text: stable, cache_control: { type: "ephemeral" } });
|
|
3742
|
+
if (dynamic) system.push({ type: "text", text: dynamic });
|
|
3743
|
+
} else {
|
|
3744
|
+
system.push(...toAnthropicContent(message.content));
|
|
3745
|
+
}
|
|
2828
3746
|
continue;
|
|
2829
3747
|
}
|
|
2830
3748
|
if (role === "tool") {
|
|
@@ -2866,6 +3784,9 @@ function buildAnthropicMessagesBody(args) {
|
|
|
2866
3784
|
if (!hasClaudeCodeIdentity(system)) {
|
|
2867
3785
|
system.unshift({ type: "text", text: CLAUDE_CODE_SYSTEM_INSTRUCTION });
|
|
2868
3786
|
}
|
|
3787
|
+
if (system.length > 0 && !system.some((block) => isCacheControl(block.cache_control))) {
|
|
3788
|
+
system[system.length - 1].cache_control = { type: "ephemeral" };
|
|
3789
|
+
}
|
|
2869
3790
|
const tools = Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools.flatMap((raw) => {
|
|
2870
3791
|
if (!raw || typeof raw !== "object") return [];
|
|
2871
3792
|
const fn = raw.function;
|
|
@@ -2880,14 +3801,39 @@ function buildAnthropicMessagesBody(args) {
|
|
|
2880
3801
|
const model = stringValue(args.openAiBody.model) ?? args.agentConfig.model ?? "claude-sonnet-5";
|
|
2881
3802
|
const maxTokensRaw = args.openAiBody.max_completion_tokens ?? args.openAiBody.max_tokens ?? args.agentConfig.max_tokens;
|
|
2882
3803
|
const maxTokens = typeof maxTokensRaw === "number" && Number.isFinite(maxTokensRaw) ? Math.max(1, Math.floor(maxTokensRaw)) : 8192;
|
|
3804
|
+
const reasoningEffort = stringValue(args.openAiBody.reasoning_effort) ?? stringValue(args.agentConfig.reasoning_effort);
|
|
3805
|
+
const spec = resolveThinkingSpec({
|
|
3806
|
+
model,
|
|
3807
|
+
reasoningEffort,
|
|
3808
|
+
maxTokens,
|
|
3809
|
+
temperature: typeof args.openAiBody.temperature === "number" ? args.openAiBody.temperature : args.agentConfig.temperature,
|
|
3810
|
+
injectedThinking: args.openAiBody.thinking,
|
|
3811
|
+
enableThinking: args.agentConfig.enableThinking,
|
|
3812
|
+
thinkingBudget: args.agentConfig.thinkingBudget
|
|
3813
|
+
});
|
|
3814
|
+
const { thinkingBlock, outputConfig } = spec;
|
|
3815
|
+
const finalMaxTokens = spec.maxTokens;
|
|
3816
|
+
const finalTemperature = spec.temperature;
|
|
3817
|
+
if (messages.length > 0) {
|
|
3818
|
+
const lastMessage = messages[messages.length - 1];
|
|
3819
|
+
const content = Array.isArray(lastMessage.content) ? lastMessage.content : [];
|
|
3820
|
+
if (content.length > 0) {
|
|
3821
|
+
const lastBlock = content[content.length - 1];
|
|
3822
|
+
if (!isCacheControl(lastBlock.cache_control)) {
|
|
3823
|
+
lastBlock.cache_control = { type: "ephemeral" };
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
2883
3827
|
return {
|
|
2884
3828
|
model,
|
|
2885
3829
|
messages,
|
|
2886
|
-
max_tokens:
|
|
3830
|
+
max_tokens: finalMaxTokens,
|
|
2887
3831
|
stream: false,
|
|
3832
|
+
...thinkingBlock ? { thinking: thinkingBlock } : {},
|
|
3833
|
+
...outputConfig ? { output_config: outputConfig } : {},
|
|
2888
3834
|
...system.length > 0 ? { system } : {},
|
|
2889
3835
|
...tools.length > 0 ? { tools } : {},
|
|
2890
|
-
...typeof
|
|
3836
|
+
...typeof finalTemperature === "number" ? { temperature: finalTemperature } : {},
|
|
2891
3837
|
...typeof args.openAiBody.top_p === "number" ? { top_p: args.openAiBody.top_p } : {}
|
|
2892
3838
|
};
|
|
2893
3839
|
}
|
|
@@ -2911,6 +3857,8 @@ function mapAnthropicMessageToOpenAi(payload) {
|
|
|
2911
3857
|
}
|
|
2912
3858
|
const usage = payload.usage ?? {};
|
|
2913
3859
|
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);
|
|
3860
|
+
const cacheCreationInputTokens = typeof usage.cache_creation_input_tokens === "number" ? usage.cache_creation_input_tokens : 0;
|
|
3861
|
+
const cacheReadInputTokens = typeof usage.cache_read_input_tokens === "number" ? usage.cache_read_input_tokens : 0;
|
|
2914
3862
|
const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : 0;
|
|
2915
3863
|
const stopReason = String(payload.stop_reason ?? "");
|
|
2916
3864
|
const message = { role: "assistant", content: text || null };
|
|
@@ -2926,9 +3874,16 @@ function mapAnthropicMessageToOpenAi(payload) {
|
|
|
2926
3874
|
finish_reason: toolCalls.length > 0 || stopReason === "tool_use" ? "tool_calls" : stopReason === "max_tokens" ? "length" : "stop"
|
|
2927
3875
|
}],
|
|
2928
3876
|
usage: {
|
|
3877
|
+
// prompt_tokens/input_tokens are total input, including cache read/write.
|
|
3878
|
+
// Preserve Anthropic's components so normalization and billing can apply
|
|
3879
|
+
// the correct cache prices without double-counting them.
|
|
2929
3880
|
prompt_tokens: inputTokens,
|
|
3881
|
+
input_tokens: inputTokens,
|
|
2930
3882
|
completion_tokens: outputTokens,
|
|
2931
|
-
|
|
3883
|
+
output_tokens: outputTokens,
|
|
3884
|
+
total_tokens: inputTokens + outputTokens,
|
|
3885
|
+
cache_creation_input_tokens: cacheCreationInputTokens,
|
|
3886
|
+
cache_read_input_tokens: cacheReadInputTokens
|
|
2932
3887
|
}
|
|
2933
3888
|
};
|
|
2934
3889
|
}
|
|
@@ -9003,6 +9958,262 @@ function isCursorOAuthAgent(agent) {
|
|
|
9003
9958
|
return agent.apiKeyRef?.trim().toLowerCase() === "cursor";
|
|
9004
9959
|
}
|
|
9005
9960
|
|
|
9961
|
+
// packages/agent-runtime/codexResponsesProvider.ts
|
|
9962
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
9963
|
+
var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
9964
|
+
var CODEX_CLIENT_VERSION = "0.144.1";
|
|
9965
|
+
var CODEX_ORIGINATOR = "codex_cli_rs";
|
|
9966
|
+
var CODEX_OPENAI_BETA = "responses=experimental";
|
|
9967
|
+
var OPENAI_AUTH_CLAIM = "https://api.openai.com/auth";
|
|
9968
|
+
var CODEX_INSTALLATION_ID = randomUUID4();
|
|
9969
|
+
function decodeCodexAccountId(accessToken) {
|
|
9970
|
+
const parts = accessToken.split(".");
|
|
9971
|
+
if (parts.length < 2) return void 0;
|
|
9972
|
+
try {
|
|
9973
|
+
const payload = JSON.parse(
|
|
9974
|
+
Buffer.from(parts[1], "base64").toString("utf8")
|
|
9975
|
+
);
|
|
9976
|
+
const claim = payload[OPENAI_AUTH_CLAIM];
|
|
9977
|
+
const value = claim && typeof claim === "object" ? claim.chatgpt_account_id : void 0;
|
|
9978
|
+
return typeof value === "string" && value ? value : void 0;
|
|
9979
|
+
} catch {
|
|
9980
|
+
return void 0;
|
|
9981
|
+
}
|
|
9982
|
+
}
|
|
9983
|
+
function createCodexRequestIdentity(installationId = CODEX_INSTALLATION_ID) {
|
|
9984
|
+
const sessionId = randomUUID4();
|
|
9985
|
+
const threadId = randomUUID4();
|
|
9986
|
+
const windowId = randomUUID4();
|
|
9987
|
+
const turnId = randomUUID4();
|
|
9988
|
+
const turnMetadata = {
|
|
9989
|
+
installation_id: installationId,
|
|
9990
|
+
session_id: sessionId,
|
|
9991
|
+
thread_id: threadId,
|
|
9992
|
+
turn_id: turnId,
|
|
9993
|
+
window_id: windowId,
|
|
9994
|
+
request_kind: "turn",
|
|
9995
|
+
turn_started_at_unix_ms: Date.now()
|
|
9996
|
+
};
|
|
9997
|
+
const turnMetadataJson = JSON.stringify(turnMetadata);
|
|
9998
|
+
return {
|
|
9999
|
+
sessionId,
|
|
10000
|
+
threadId,
|
|
10001
|
+
windowId,
|
|
10002
|
+
turnId,
|
|
10003
|
+
turnMetadataJson,
|
|
10004
|
+
clientMetadata: {
|
|
10005
|
+
"x-codex-installation-id": installationId,
|
|
10006
|
+
session_id: sessionId,
|
|
10007
|
+
thread_id: threadId,
|
|
10008
|
+
"x-codex-window-id": windowId,
|
|
10009
|
+
turn_id: turnId,
|
|
10010
|
+
"x-codex-turn-metadata": turnMetadataJson
|
|
10011
|
+
}
|
|
10012
|
+
};
|
|
10013
|
+
}
|
|
10014
|
+
function buildCodexCompatibilityHeaders(identity, accountId) {
|
|
10015
|
+
return {
|
|
10016
|
+
Authorization: "",
|
|
10017
|
+
// filled by caller with bearer token
|
|
10018
|
+
"Content-Type": "application/json",
|
|
10019
|
+
Accept: "text/event-stream",
|
|
10020
|
+
"chatgpt-account-id": accountId,
|
|
10021
|
+
"OpenAI-Beta": CODEX_OPENAI_BETA,
|
|
10022
|
+
originator: CODEX_ORIGINATOR,
|
|
10023
|
+
version: CODEX_CLIENT_VERSION,
|
|
10024
|
+
session_id: identity.sessionId,
|
|
10025
|
+
conversation_id: identity.sessionId,
|
|
10026
|
+
"x-client-request-id": identity.sessionId,
|
|
10027
|
+
"session-id": identity.sessionId,
|
|
10028
|
+
"thread-id": identity.threadId,
|
|
10029
|
+
"x-codex-window-id": identity.windowId,
|
|
10030
|
+
"x-codex-turn-metadata": identity.turnMetadataJson
|
|
10031
|
+
};
|
|
10032
|
+
}
|
|
10033
|
+
function collectInstructions(messages, agentPrompt) {
|
|
10034
|
+
const systemTexts = [];
|
|
10035
|
+
const prompt = agentPrompt?.trim();
|
|
10036
|
+
if (prompt) systemTexts.push(prompt);
|
|
10037
|
+
for (const raw of messages) {
|
|
10038
|
+
if (!raw || typeof raw !== "object") continue;
|
|
10039
|
+
const role = String(raw.role ?? "");
|
|
10040
|
+
if (role !== "system" && role !== "developer") continue;
|
|
10041
|
+
const content = raw.content;
|
|
10042
|
+
const stringContent = asOptionalTrimmedString(content);
|
|
10043
|
+
if (stringContent) {
|
|
10044
|
+
systemTexts.push(stringContent);
|
|
10045
|
+
} else if (Array.isArray(content)) {
|
|
10046
|
+
const text = content.filter(
|
|
10047
|
+
(p) => !!p && p.type === "text"
|
|
10048
|
+
).map((p) => p.text).join("\n").trim();
|
|
10049
|
+
if (text) systemTexts.push(text);
|
|
10050
|
+
}
|
|
10051
|
+
}
|
|
10052
|
+
return systemTexts.join("\n\n");
|
|
10053
|
+
}
|
|
10054
|
+
function collectStableInstructions(messages, fallbackPrompt) {
|
|
10055
|
+
const systemTexts = [];
|
|
10056
|
+
if (fallbackPrompt?.trim()) systemTexts.push(fallbackPrompt.trim());
|
|
10057
|
+
for (const raw of messages) {
|
|
10058
|
+
if (!raw || typeof raw !== "object") continue;
|
|
10059
|
+
const message = raw;
|
|
10060
|
+
const role = String(message.role ?? "");
|
|
10061
|
+
if (role !== "system" && role !== "developer") continue;
|
|
10062
|
+
if (typeof message.content === "string") {
|
|
10063
|
+
const boundary = Number(message.stable_prefix_chars);
|
|
10064
|
+
const text = Number.isFinite(boundary) && boundary > 0 ? message.content.slice(0, boundary) : message.content;
|
|
10065
|
+
if (text.trim()) systemTexts.push(text.trim());
|
|
10066
|
+
}
|
|
10067
|
+
}
|
|
10068
|
+
return systemTexts.join("\n\n");
|
|
10069
|
+
}
|
|
10070
|
+
function stablePromptCacheKey(parts) {
|
|
10071
|
+
const value = JSON.stringify(parts);
|
|
10072
|
+
let hash = 2166136261;
|
|
10073
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
10074
|
+
hash ^= value.charCodeAt(index);
|
|
10075
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
10076
|
+
}
|
|
10077
|
+
return `nolo-codex-${hash.toString(16).padStart(8, "0")}`;
|
|
10078
|
+
}
|
|
10079
|
+
function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
|
|
10080
|
+
const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
|
|
10081
|
+
const nonSystem = rawMessages.filter((m) => {
|
|
10082
|
+
const role = m && typeof m === "object" ? String(m.role) : "";
|
|
10083
|
+
return role !== "system" && role !== "developer";
|
|
10084
|
+
});
|
|
10085
|
+
const input = convertMessagesToResponsesInput(nonSystem);
|
|
10086
|
+
const instructions = collectInstructions(rawMessages, args.agentConfig.prompt);
|
|
10087
|
+
const stableInstructions = collectStableInstructions(rawMessages, args.agentConfig.prompt);
|
|
10088
|
+
const model = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gpt-5.5";
|
|
10089
|
+
const tools = toResponsesTools(
|
|
10090
|
+
Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
|
|
10091
|
+
);
|
|
10092
|
+
const body = {
|
|
10093
|
+
model,
|
|
10094
|
+
input,
|
|
10095
|
+
stream: true,
|
|
10096
|
+
store: false,
|
|
10097
|
+
// Keep routing stable across turns and request UUIDs. Growing input/history
|
|
10098
|
+
// is intentionally excluded; only stable request-prefix material belongs.
|
|
10099
|
+
prompt_cache_key: stablePromptCacheKey([model, stableInstructions, tools ?? []]),
|
|
10100
|
+
client_metadata: identity.clientMetadata
|
|
10101
|
+
};
|
|
10102
|
+
if (instructions) body.instructions = instructions;
|
|
10103
|
+
if (tools && tools.length > 0) {
|
|
10104
|
+
body.tools = tools;
|
|
10105
|
+
body.tool_choice = "auto";
|
|
10106
|
+
body.parallel_tool_calls = true;
|
|
10107
|
+
}
|
|
10108
|
+
return body;
|
|
10109
|
+
}
|
|
10110
|
+
function aggregateResponsesStream(events) {
|
|
10111
|
+
let text = "";
|
|
10112
|
+
const toolCalls = [];
|
|
10113
|
+
let usage;
|
|
10114
|
+
for (const ev of events) {
|
|
10115
|
+
const type = String(ev.type ?? "");
|
|
10116
|
+
if (type === "response.output_text.delta" && typeof ev.delta === "string") {
|
|
10117
|
+
text += ev.delta;
|
|
10118
|
+
continue;
|
|
10119
|
+
}
|
|
10120
|
+
if (type === "response.output_item.done") {
|
|
10121
|
+
const item = ev.item;
|
|
10122
|
+
if (item && item.type === "function_call") {
|
|
10123
|
+
const name = typeof item.name === "string" ? item.name : "";
|
|
10124
|
+
if (name) {
|
|
10125
|
+
toolCalls.push({
|
|
10126
|
+
id: typeof item.call_id === "string" && item.call_id ? item.call_id : `${name}_${toolCalls.length}`,
|
|
10127
|
+
type: "function",
|
|
10128
|
+
function: {
|
|
10129
|
+
name,
|
|
10130
|
+
arguments: typeof item.arguments === "string" ? item.arguments : "{}"
|
|
10131
|
+
}
|
|
10132
|
+
});
|
|
10133
|
+
}
|
|
10134
|
+
}
|
|
10135
|
+
continue;
|
|
10136
|
+
}
|
|
10137
|
+
if (type === "response.completed") {
|
|
10138
|
+
const response = ev.response;
|
|
10139
|
+
const u = response?.usage;
|
|
10140
|
+
if (u) {
|
|
10141
|
+
const prompt = typeof u.input_tokens === "number" ? u.input_tokens : 0;
|
|
10142
|
+
const completion = typeof u.output_tokens === "number" ? u.output_tokens : 0;
|
|
10143
|
+
const total = typeof u.total_tokens === "number" ? u.total_tokens : prompt + completion;
|
|
10144
|
+
usage = {
|
|
10145
|
+
prompt_tokens: prompt,
|
|
10146
|
+
completion_tokens: completion,
|
|
10147
|
+
total_tokens: total
|
|
10148
|
+
};
|
|
10149
|
+
}
|
|
10150
|
+
}
|
|
10151
|
+
}
|
|
10152
|
+
return { text, toolCalls, usage };
|
|
10153
|
+
}
|
|
10154
|
+
async function readSseEvents(response) {
|
|
10155
|
+
return readSseDataValues(response, (line) => {
|
|
10156
|
+
const ev = parseSseDataLineObject(line);
|
|
10157
|
+
return ev && !Array.isArray(ev) ? ev : null;
|
|
10158
|
+
});
|
|
10159
|
+
}
|
|
10160
|
+
async function fetchCodexResponsesCompletion(args) {
|
|
10161
|
+
const fetchImpl = args.fetchImpl ?? fetch;
|
|
10162
|
+
const accountId = args.accountId?.trim() || decodeCodexAccountId(args.accessToken);
|
|
10163
|
+
if (!accountId) {
|
|
10164
|
+
return {
|
|
10165
|
+
status: 401,
|
|
10166
|
+
body: {
|
|
10167
|
+
error: {
|
|
10168
|
+
message: "ChatGPT Codex credential is missing chatgpt_account_id. Re-run `nolo auth chatgpt`."
|
|
10169
|
+
}
|
|
10170
|
+
}
|
|
10171
|
+
};
|
|
10172
|
+
}
|
|
10173
|
+
const identity = createCodexRequestIdentity();
|
|
10174
|
+
const body = buildCodexRequestBody(args, identity);
|
|
10175
|
+
const headers = buildCodexCompatibilityHeaders(identity, accountId);
|
|
10176
|
+
headers.Authorization = `Bearer ${args.accessToken}`;
|
|
10177
|
+
const response = await fetchImpl(CODEX_RESPONSES_URL, {
|
|
10178
|
+
method: "POST",
|
|
10179
|
+
headers,
|
|
10180
|
+
body: JSON.stringify(body),
|
|
10181
|
+
signal: args.signal
|
|
10182
|
+
});
|
|
10183
|
+
if (!response.ok) {
|
|
10184
|
+
const errorText = await response.text();
|
|
10185
|
+
return {
|
|
10186
|
+
status: response.status,
|
|
10187
|
+
body: { error: { message: errorText || response.statusText } }
|
|
10188
|
+
};
|
|
10189
|
+
}
|
|
10190
|
+
const events = await readSseEvents(response);
|
|
10191
|
+
const { text, toolCalls, usage } = aggregateResponsesStream(events);
|
|
10192
|
+
const message = {
|
|
10193
|
+
role: "assistant",
|
|
10194
|
+
content: text || null
|
|
10195
|
+
};
|
|
10196
|
+
if (toolCalls.length > 0) message.tool_calls = toolCalls;
|
|
10197
|
+
return {
|
|
10198
|
+
status: 200,
|
|
10199
|
+
body: {
|
|
10200
|
+
choices: [
|
|
10201
|
+
{
|
|
10202
|
+
index: 0,
|
|
10203
|
+
message,
|
|
10204
|
+
finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop"
|
|
10205
|
+
}
|
|
10206
|
+
],
|
|
10207
|
+
...usage ? { usage } : {}
|
|
10208
|
+
}
|
|
10209
|
+
};
|
|
10210
|
+
}
|
|
10211
|
+
function isCodexOAuthAgent(agentConfig) {
|
|
10212
|
+
if (!agentConfig) return false;
|
|
10213
|
+
const apiKeyRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
|
|
10214
|
+
return apiKeyRef === "chatgpt";
|
|
10215
|
+
}
|
|
10216
|
+
|
|
9006
10217
|
// packages/agent-runtime/oauthProviders.ts
|
|
9007
10218
|
var XAI_ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
|
|
9008
10219
|
var decodeBase64 = (s) => Buffer.from(s, "base64").toString("utf8");
|
|
@@ -9496,7 +10707,7 @@ function buildOpenAiTools(args) {
|
|
|
9496
10707
|
const toolset = buildLocalWorkspaceToolsetForEnv(args);
|
|
9497
10708
|
const toolNameSet = new Set(args.toolNames ?? []);
|
|
9498
10709
|
const callAgentTools = toolNameSet.has("callAgent") ? prepareTools(["callAgent"]) : [];
|
|
9499
|
-
const uiAskChoiceTools = toolNameSet.has("
|
|
10710
|
+
const uiAskChoiceTools = toolNameSet.has("ask_user") ? prepareTools(["ask_user"]) : [];
|
|
9500
10711
|
const readPastedTextTools = toolNameSet.has("readPastedText") ? [
|
|
9501
10712
|
{
|
|
9502
10713
|
type: "function",
|
|
@@ -9556,10 +10767,10 @@ function buildOpenAiTools(args) {
|
|
|
9556
10767
|
var CLI_DEFAULT_TOOLS = ["exa_search", "fetchWebpage"];
|
|
9557
10768
|
function addDefaultCliCoreTools(toolNames, env, options) {
|
|
9558
10769
|
const declaredOnly = env && shouldUseDeclaredOnlyLocalWorkspaceTools(env);
|
|
9559
|
-
const forcedTools = options?.hasUserChoice === true ? FORCED_TOOLS : FORCED_TOOLS.filter((name) => name !== "
|
|
10770
|
+
const forcedTools = options?.hasUserChoice === true ? FORCED_TOOLS : FORCED_TOOLS.filter((name) => name !== "ask_user");
|
|
9560
10771
|
const injected = declaredOnly ? [...forcedTools] : [...forcedTools, ...CLI_DEFAULT_TOOLS];
|
|
9561
10772
|
const combined = [...toolNames, ...injected];
|
|
9562
|
-
const filtered = options?.hasUserChoice === true ? combined : combined.filter((name) => name !== "
|
|
10773
|
+
const filtered = options?.hasUserChoice === true ? combined : combined.filter((name) => name !== "ask_user");
|
|
9563
10774
|
return [...new Set(filtered)];
|
|
9564
10775
|
}
|
|
9565
10776
|
function resolveCliEffectiveEnabledPacks(args) {
|
|
@@ -9852,9 +11063,9 @@ function createCliCallAgentToolExecutor(deps, ctx) {
|
|
|
9852
11063
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
9853
11064
|
var currentMetaFile = fileURLToPath(import.meta.url);
|
|
9854
11065
|
var isJsBundle = extname(currentMetaFile) === ".js";
|
|
9855
|
-
var SOURCE_CLI_DIR = isJsBundle ?
|
|
9856
|
-
var CLI_DIR = isCompiledBinary() ?
|
|
9857
|
-
var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile :
|
|
11066
|
+
var SOURCE_CLI_DIR = isJsBundle ? dirname2(currentMetaFile) : dirname2(dirname2(currentMetaFile));
|
|
11067
|
+
var CLI_DIR = isCompiledBinary() ? dirname2(process.execPath) : SOURCE_CLI_DIR;
|
|
11068
|
+
var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join2(SOURCE_CLI_DIR, "index.ts");
|
|
9858
11069
|
function createCliLocalRuntimeAdapter(deps) {
|
|
9859
11070
|
const now = deps.now ?? Date.now;
|
|
9860
11071
|
const createId = deps.createId ?? createFallbackId;
|
|
@@ -10200,6 +11411,74 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10200
11411
|
}
|
|
10201
11412
|
};
|
|
10202
11413
|
}
|
|
11414
|
+
if (isCodexOAuthAgent(agentConfig)) {
|
|
11415
|
+
const accessToken = await apiKeyRefResolver("chatgpt");
|
|
11416
|
+
if (!accessToken) {
|
|
11417
|
+
throw new Error(
|
|
11418
|
+
'OAuth credential for "chatgpt" not found locally. Run `nolo auth chatgpt`.'
|
|
11419
|
+
);
|
|
11420
|
+
}
|
|
11421
|
+
const credential = readOAuthCredential("chatgpt");
|
|
11422
|
+
const accountId = credential?.accountId;
|
|
11423
|
+
const { requestedToolNames: requestedToolNames2, tools: tools2 } = resolveProviderOpenAiToolBundle(
|
|
11424
|
+
agentConfig,
|
|
11425
|
+
deps.env,
|
|
11426
|
+
buildProviderOpenAiTools,
|
|
11427
|
+
additionalToolNames,
|
|
11428
|
+
{ hasUserChoice: Boolean(deps.requestUserChoice) }
|
|
11429
|
+
);
|
|
11430
|
+
logLocalRuntimeDiagnostic("provider.selected", {
|
|
11431
|
+
agentKey: agentConfig.key,
|
|
11432
|
+
transport: "codex-responses",
|
|
11433
|
+
provider: "openai",
|
|
11434
|
+
model: agentConfig.model ?? "gpt-5.6-sol",
|
|
11435
|
+
hasApiKey: true
|
|
11436
|
+
});
|
|
11437
|
+
return {
|
|
11438
|
+
model: agentConfig.model || "gpt-5.6-sol",
|
|
11439
|
+
complete: async (messages, options) => {
|
|
11440
|
+
const result = await fetchCodexResponsesCompletion({
|
|
11441
|
+
agentConfig,
|
|
11442
|
+
accessToken,
|
|
11443
|
+
...accountId ? { accountId } : {},
|
|
11444
|
+
openAiBody: {
|
|
11445
|
+
model: agentConfig.model || "gpt-5.6-sol",
|
|
11446
|
+
messages,
|
|
11447
|
+
stream: false,
|
|
11448
|
+
...tools2.length > 0 ? { tools: tools2 } : {}
|
|
11449
|
+
},
|
|
11450
|
+
fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
|
|
11451
|
+
sleep: deps.sleep,
|
|
11452
|
+
loopbackRequest
|
|
11453
|
+
})
|
|
11454
|
+
});
|
|
11455
|
+
if (result.status < 200 || result.status >= 300) {
|
|
11456
|
+
const errMsg = result.body?.error && typeof result.body.error === "object" && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
|
|
11457
|
+
throw new Error(
|
|
11458
|
+
`local Codex OAuth provider failed: HTTP ${result.status} ${errMsg}`
|
|
11459
|
+
);
|
|
11460
|
+
}
|
|
11461
|
+
const choice = Array.isArray(result.body.choices) ? result.body.choices[0] : void 0;
|
|
11462
|
+
const message = choice?.message ?? {};
|
|
11463
|
+
const content = typeof message.content === "string" ? message.content : "";
|
|
11464
|
+
const tool_calls = Array.isArray(message.tool_calls) ? message.tool_calls : void 0;
|
|
11465
|
+
if (content && options?.onTextDelta) options.onTextDelta(content);
|
|
11466
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
11467
|
+
agentKey: agentConfig.key,
|
|
11468
|
+
transport: "codex-responses",
|
|
11469
|
+
ok: true,
|
|
11470
|
+
contentChars: content.length,
|
|
11471
|
+
toolCallCount: tool_calls?.length ?? 0,
|
|
11472
|
+
requestedToolNames: requestedToolNames2
|
|
11473
|
+
});
|
|
11474
|
+
return {
|
|
11475
|
+
content,
|
|
11476
|
+
...tool_calls ? { tool_calls } : {},
|
|
11477
|
+
trace: messages
|
|
11478
|
+
};
|
|
11479
|
+
}
|
|
11480
|
+
};
|
|
11481
|
+
}
|
|
10203
11482
|
if (isCursorOAuthAgent(agentConfig)) {
|
|
10204
11483
|
const accessToken = await apiKeyRefResolver("cursor");
|
|
10205
11484
|
if (!accessToken) {
|
|
@@ -10269,6 +11548,101 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10269
11548
|
}
|
|
10270
11549
|
};
|
|
10271
11550
|
}
|
|
11551
|
+
if (shouldUsePlatformChatProvider(deps.env, agentConfig) && isGemini3Model(agentConfig.model ?? "") && agentConfig.provider === "google") {
|
|
11552
|
+
const providerConfig2 = await resolvePlatformChatProviderConfig({
|
|
11553
|
+
agentConfig,
|
|
11554
|
+
env: deps.env,
|
|
11555
|
+
apiKeyRefResolver,
|
|
11556
|
+
credentialBroker,
|
|
11557
|
+
syncFetcher
|
|
11558
|
+
});
|
|
11559
|
+
const { requestedToolNames: requestedToolNames2, tools: tools2 } = resolveProviderOpenAiToolBundle(
|
|
11560
|
+
agentConfig,
|
|
11561
|
+
deps.env,
|
|
11562
|
+
buildProviderOpenAiTools,
|
|
11563
|
+
additionalToolNames,
|
|
11564
|
+
{ hasUserChoice: Boolean(deps.requestUserChoice) }
|
|
11565
|
+
);
|
|
11566
|
+
if (tools2.length > 0 && providerConfig2.apiKey && shouldUseGeminiNativeToolRoute(
|
|
11567
|
+
agentConfig.provider ?? "",
|
|
11568
|
+
agentConfig.model ?? "",
|
|
11569
|
+
tools2,
|
|
11570
|
+
() => false
|
|
11571
|
+
// CLI 端不区分 image 模型
|
|
11572
|
+
)) {
|
|
11573
|
+
logLocalRuntimeDiagnostic("provider.selected", {
|
|
11574
|
+
agentKey: agentConfig.key,
|
|
11575
|
+
transport: "gemini-native-tool",
|
|
11576
|
+
apiSource: agentConfig.apiSource ?? null,
|
|
11577
|
+
provider: providerConfig2.provider,
|
|
11578
|
+
model: providerConfig2.model,
|
|
11579
|
+
hasApiKey: Boolean(providerConfig2.apiKey)
|
|
11580
|
+
});
|
|
11581
|
+
return {
|
|
11582
|
+
model: providerConfig2.model,
|
|
11583
|
+
complete: async (messages, options) => {
|
|
11584
|
+
const requestBody = buildGeminiGenerateContentRequest({
|
|
11585
|
+
messages,
|
|
11586
|
+
tools: tools2,
|
|
11587
|
+
maxTokens: typeof agentConfig.max_tokens === "number" ? agentConfig.max_tokens : void 0,
|
|
11588
|
+
temperature: typeof agentConfig.temperature === "number" ? agentConfig.temperature : void 0,
|
|
11589
|
+
attachSkipThoughtSignature: true
|
|
11590
|
+
});
|
|
11591
|
+
const model = providerConfig2.model;
|
|
11592
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse`;
|
|
11593
|
+
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
11594
|
+
agentKey: agentConfig.key,
|
|
11595
|
+
transport: "gemini-native-tool",
|
|
11596
|
+
model,
|
|
11597
|
+
messageCount: messages.length,
|
|
11598
|
+
toolCount: tools2.length,
|
|
11599
|
+
requestedToolNames: requestedToolNames2
|
|
11600
|
+
});
|
|
11601
|
+
const res = await fetchImpl(url, {
|
|
11602
|
+
method: "POST",
|
|
11603
|
+
headers: {
|
|
11604
|
+
"Content-Type": "application/json",
|
|
11605
|
+
"x-goog-api-key": providerConfig2.apiKey ?? ""
|
|
11606
|
+
},
|
|
11607
|
+
body: JSON.stringify(requestBody),
|
|
11608
|
+
signal: AbortSignal.timeout(12e4)
|
|
11609
|
+
});
|
|
11610
|
+
if (!res.ok) {
|
|
11611
|
+
const errText = await res.text();
|
|
11612
|
+
logLocalRuntimeDiagnostic("provider.request.failed", {
|
|
11613
|
+
agentKey: agentConfig.key,
|
|
11614
|
+
transport: "gemini-native-tool",
|
|
11615
|
+
status: res.status,
|
|
11616
|
+
error: errText.slice(0, 200)
|
|
11617
|
+
});
|
|
11618
|
+
throw new Error(
|
|
11619
|
+
`gemini native tool provider failed: HTTP ${res.status} ${errText.slice(0, 500)}`
|
|
11620
|
+
);
|
|
11621
|
+
}
|
|
11622
|
+
const chunks = await readSseDataValues(res, parseSseDataLineJson);
|
|
11623
|
+
const { text, toolCalls, usage } = accumulateGeminiChunks(chunks);
|
|
11624
|
+
if (text && options?.onTextDelta) {
|
|
11625
|
+
options.onTextDelta(text);
|
|
11626
|
+
}
|
|
11627
|
+
const result = {
|
|
11628
|
+
content: text,
|
|
11629
|
+
model,
|
|
11630
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
11631
|
+
...usage ? { usage } : {},
|
|
11632
|
+
trace: messages
|
|
11633
|
+
};
|
|
11634
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
11635
|
+
agentKey: agentConfig.key,
|
|
11636
|
+
transport: "gemini-native-tool",
|
|
11637
|
+
ok: true,
|
|
11638
|
+
contentChars: text.length,
|
|
11639
|
+
toolCallCount: toolCalls.length
|
|
11640
|
+
});
|
|
11641
|
+
return result;
|
|
11642
|
+
}
|
|
11643
|
+
};
|
|
11644
|
+
}
|
|
11645
|
+
}
|
|
10272
11646
|
if (shouldUsePlatformChatProvider(deps.env, agentConfig)) {
|
|
10273
11647
|
const providerConfig2 = await resolvePlatformChatProviderConfig({
|
|
10274
11648
|
agentConfig,
|
|
@@ -10329,47 +11703,20 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10329
11703
|
},
|
|
10330
11704
|
{
|
|
10331
11705
|
sleep: deps.sleep,
|
|
10332
|
-
loopbackRequest
|
|
11706
|
+
loopbackRequest,
|
|
11707
|
+
// auto 档位转发 nolo.chat 时,网关层 502(server: Caddy、空 body)
|
|
11708
|
+
// 意味着请求根本没到 Bun 上游,provider 未受理,重试安全。
|
|
11709
|
+
// 与 429/503 同口径:不会重复计费/重复生成。
|
|
11710
|
+
retryableStatuses: /* @__PURE__ */ new Set([429, 502, 503]),
|
|
11711
|
+
onRetry: deps.activityReporter ? ({ attempt, maxAttempts, delayMs }) => {
|
|
11712
|
+
deps.activityReporter(
|
|
11713
|
+
`\u81EA\u52A8\u91CD\u8BD5 ${attempt}/${maxAttempts} \xB7 ${Math.ceil(delayMs / 1e3)}s`
|
|
11714
|
+
);
|
|
11715
|
+
} : void 0
|
|
10333
11716
|
}
|
|
10334
11717
|
);
|
|
10335
|
-
let responseProviderConfig = providerConfig2;
|
|
10336
|
-
let firstErrorRaw;
|
|
10337
11718
|
if (!res.ok) {
|
|
10338
|
-
|
|
10339
|
-
const fallbackProviderConfig = resolveLegacyDeepSeekProxyChatFallback({
|
|
10340
|
-
providerConfig: providerConfig2,
|
|
10341
|
-
status: res.status,
|
|
10342
|
-
raw: firstErrorRaw
|
|
10343
|
-
});
|
|
10344
|
-
if (fallbackProviderConfig) {
|
|
10345
|
-
responseProviderConfig = fallbackProviderConfig;
|
|
10346
|
-
const fallbackRequest = buildPlatformChatCompletionRequest({
|
|
10347
|
-
providerConfig: fallbackProviderConfig,
|
|
10348
|
-
messages,
|
|
10349
|
-
tools: tools2,
|
|
10350
|
-
stream: false
|
|
10351
|
-
});
|
|
10352
|
-
logLocalRuntimeDiagnostic("provider.request.compatibility-fallback", {
|
|
10353
|
-
agentKey: agentConfig.key,
|
|
10354
|
-
provider: providerConfig2.provider,
|
|
10355
|
-
fromEndpoint: summarizeEndpoint(providerConfig2.endpoint) ?? null,
|
|
10356
|
-
toEndpoint: summarizeEndpoint(fallbackProviderConfig.endpoint) ?? null,
|
|
10357
|
-
reason: "legacy-proxy-responses-schema"
|
|
10358
|
-
});
|
|
10359
|
-
res = await fetchWithTransientRetry(
|
|
10360
|
-
fetchImpl,
|
|
10361
|
-
fallbackRequest.url,
|
|
10362
|
-
{ ...fallbackRequest.init },
|
|
10363
|
-
{
|
|
10364
|
-
sleep: deps.sleep,
|
|
10365
|
-
loopbackRequest
|
|
10366
|
-
}
|
|
10367
|
-
);
|
|
10368
|
-
firstErrorRaw = void 0;
|
|
10369
|
-
}
|
|
10370
|
-
}
|
|
10371
|
-
if (!res.ok) {
|
|
10372
|
-
const raw2 = firstErrorRaw ?? await res.text().catch(() => "");
|
|
11719
|
+
const raw2 = await res.text().catch(() => "");
|
|
10373
11720
|
const data2 = parsePlatformChatCompletionData(raw2);
|
|
10374
11721
|
const rawPreview = raw2.length > 200 ? `${raw2.slice(0, 200)}\u2026(${raw2.length}b)` : raw2;
|
|
10375
11722
|
const gatewayHeaders = [
|
|
@@ -10420,7 +11767,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10420
11767
|
});
|
|
10421
11768
|
const data = parsePlatformChatCompletionData(raw);
|
|
10422
11769
|
return parsePlatformChatCompletionResponse({
|
|
10423
|
-
providerConfig:
|
|
11770
|
+
providerConfig: providerConfig2,
|
|
10424
11771
|
data,
|
|
10425
11772
|
trace: messages
|
|
10426
11773
|
});
|
|
@@ -10521,6 +11868,23 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10521
11868
|
};
|
|
10522
11869
|
},
|
|
10523
11870
|
executeTool: async (call, opts) => {
|
|
11871
|
+
const contextualCall = opts?.runtimeContext ? { ...call, runtimeContext: opts.runtimeContext } : call;
|
|
11872
|
+
let injectedCall = contextualCall;
|
|
11873
|
+
if (contextualCall.name === "startAgentRun" && deps.parentDialogId && typeof contextualCall.arguments === "string") {
|
|
11874
|
+
try {
|
|
11875
|
+
const args = JSON.parse(contextualCall.arguments);
|
|
11876
|
+
if (!args.parentDialogId) {
|
|
11877
|
+
injectedCall = {
|
|
11878
|
+
...contextualCall,
|
|
11879
|
+
arguments: JSON.stringify({
|
|
11880
|
+
...args,
|
|
11881
|
+
parentDialogId: deps.parentDialogId
|
|
11882
|
+
})
|
|
11883
|
+
};
|
|
11884
|
+
}
|
|
11885
|
+
} catch {
|
|
11886
|
+
}
|
|
11887
|
+
}
|
|
10524
11888
|
assertWithinLocalToolBudget({
|
|
10525
11889
|
toolName: call.name,
|
|
10526
11890
|
budgets: localToolBudgets,
|
|
@@ -10529,7 +11893,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10529
11893
|
const result = await executeLocalToolWithPolicy({
|
|
10530
11894
|
env: deps.env,
|
|
10531
11895
|
agentToolNames: activeAgentToolNames,
|
|
10532
|
-
call,
|
|
11896
|
+
call: injectedCall,
|
|
10533
11897
|
executors: localToolExecutors,
|
|
10534
11898
|
abortSignal: opts?.abortSignal,
|
|
10535
11899
|
detachMs: resolveExecShellDetachMs(deps.env),
|
|
@@ -10550,6 +11914,8 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10550
11914
|
export {
|
|
10551
11915
|
summarizeEndpoint,
|
|
10552
11916
|
isBuiltinNoloAgentRef,
|
|
11917
|
+
readTimestamp,
|
|
11918
|
+
parseAgentRunEvent,
|
|
10553
11919
|
parseCliLocale,
|
|
10554
11920
|
getCliLocale,
|
|
10555
11921
|
setCliLocale,
|
|
@@ -10557,6 +11923,8 @@ export {
|
|
|
10557
11923
|
t,
|
|
10558
11924
|
toolLabel,
|
|
10559
11925
|
agentRunCardLabels,
|
|
11926
|
+
QUOTA_ERROR_PATTERNS,
|
|
11927
|
+
isQuotaExhaustedError,
|
|
10560
11928
|
clearCliLocalRuntimePreparedAgentCache,
|
|
10561
11929
|
createCliCallAgentToolExecutor,
|
|
10562
11930
|
createCliLocalRuntimeAdapter
|