nolo-cli 0.19.0 → 0.24.0-alpha.14
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/README.md +9 -18
- package/{_executeModel-X5PCIZN6.js → _executeModel-ZPNYAEFW.js} +46 -44
- package/{action-LT7BRFLK.js → action-5MNAXR5B.js} +7 -6
- package/{addContentAction-PL3KKBDH.js → addContentAction-UNSYTVTB.js} +5 -5
- package/{addDialogAgentAction-FCMSKYAF.js → addDialogAgentAction-LJGNP2AO.js} +5 -5
- package/{agentDeleteCommand-2BZDQV36.js → agentDeleteCommand-5ZV4433K.js} +27 -26
- package/{agentEmailCommands-2QJDGRMB.js → agentEmailCommands-Z7KOYDVQ.js} +57 -55
- package/{agentListCommands-6VEPTKBI.js → agentListCommands-UQUXJYUN.js} +30 -26
- package/{agentMachineCommands-NVVHNWYI.js → agentMachineCommands-53O6P6L5.js} +25 -24
- package/{agentRecordCommands-4GGRDMD4.js → agentRecordCommands-ZRYNBSSS.js} +52 -50
- package/{agentRunCommand-XOLQNKBZ.js → agentRunCommand-B73MKVOG.js} +55 -54
- package/{agentRunControl-Y5AFH5PQ.js → agentRunControl-SNUKXN6J.js} +6 -2
- package/{agentRuntimeLocal-7WYWCGL4.js → agentRuntimeLocal-GVNERRKQ.js} +21 -18
- package/{agentSlice-EAXPGEYV.js → agentSlice-OJBHIL34.js} +5 -5
- package/{appDeleteCommands-77KR2RJ4.js → appDeleteCommands-23Z3Z6KE.js} +23 -22
- package/{appDeployCommands-K7CAHGBI.js → appDeployCommands-3MFAR4Z7.js} +23 -22
- package/{appDeployStatusCommands-4OEKLTBT.js → appDeployStatusCommands-JHU6GSN4.js} +23 -22
- package/{appGetCommands-VM2WDLAZ.js → appGetCommands-24J55H2Y.js} +23 -22
- package/{appListCommands-GX6BBA6U.js → appListCommands-HE5KP3PH.js} +23 -22
- package/{authCommand-DY6UUL6O.js → authCommand-KGRK6MNU.js} +12 -13
- package/{authCommands-XTBV7OFZ.js → authCommands-JSOG2H4E.js} +4 -5
- package/{chunk-OWOHNGCN.js → chunk-2MBTWINN.js} +42 -3
- package/{chunk-MVQ4TBSD.js → chunk-54VHTARN.js} +1 -1
- package/{chunk-RQN4SEKL.js → chunk-5DWZ46RJ.js} +1 -1
- package/{chunk-VYHDJEQD.js → chunk-5EDKWSQN.js} +136 -78
- package/{chunk-Z4NR32XR.js → chunk-5RGU3J7P.js} +13 -0
- package/{chunk-7BUYEZ6U.js → chunk-7H3UTGPM.js} +12 -72
- package/{chunk-3ZX7PERL.js → chunk-AAWJ5S3G.js} +20 -7
- package/{chunk-SCTYAHYK.js → chunk-ADE6577S.js} +237 -142
- package/{chunk-PJSV3IZ5.js → chunk-AOPOTHFK.js} +1 -1
- package/{chunk-3ND52WIL.js → chunk-ATWUOTJP.js} +180 -24
- package/{chunk-SWDPIPOY.js → chunk-AZW5AHMW.js} +1 -1
- package/chunk-CF7S2RYZ.js +376 -0
- package/{chunk-L4F3I4SR.js → chunk-CV6BM7LU.js} +4 -6
- package/{chunk-G5U6LDLG.js → chunk-CWTT2NZ6.js} +6 -6
- package/{chunk-MKA6QE5E.js → chunk-CZHE6LLV.js} +135 -55
- package/{chunk-KFEVY3ST.js → chunk-D34RI6NI.js} +18 -8
- package/{chunk-XRZJGPFI.js → chunk-FON47ACC.js} +4 -4
- package/{chunk-K6EUAOW3.js → chunk-FXFGNOT2.js} +67 -1
- package/{chunk-LLWKHDG4.js → chunk-G36SUBHA.js} +14 -6
- package/{chunk-REA4JLBH.js → chunk-GD23ZX7Z.js} +7 -6
- package/{chunk-ROWQEJRP.js → chunk-GE6IWA5N.js} +12 -4
- package/{chunk-EDV7EBOI.js → chunk-GGB6MPHD.js} +2155 -1503
- package/{chunk-IYEXFJPC.js → chunk-GNGOZMU2.js} +64 -57
- package/{chunk-4T5F7YZQ.js → chunk-I6RJGORZ.js} +1 -1
- package/{chunk-DFCFMCY6.js → chunk-J2WT5CEO.js} +2 -2
- package/{chunk-AHCY2S2I.js → chunk-JJ2WUBFN.js} +1 -1
- package/{chunk-UGUW3FHG.js → chunk-JMSCXQUG.js} +2 -2
- package/{chunk-VDXCXCXH.js → chunk-KURQBS7S.js} +1 -1
- package/{chunk-FQZZLA3C.js → chunk-KXKQO4Q6.js} +17 -0
- package/{chunk-3Q7WHGCB.js → chunk-L65QKSVJ.js} +1 -1
- package/{chunk-UAIVG4J6.js → chunk-LEHTC2FI.js} +1 -8
- package/{chunk-UBHAWFQ6.js → chunk-LLDGWLML.js} +42 -19
- package/{chunk-JLA4FXYC.js → chunk-MALVZUYL.js} +1 -1
- package/{chunk-N54HIJVJ.js → chunk-MCXQNEJ3.js} +101 -9
- package/{chunk-GFUIQ4RY.js → chunk-MXFQHRSS.js} +1 -1
- package/{chunk-LSFAWXKC.js → chunk-N7J63Q6C.js} +1 -0
- package/{chunk-6Y7A3OQQ.js → chunk-NRY4GCKJ.js} +2 -0
- package/{chunk-ELT65PZW.js → chunk-OXLLFZNF.js} +1 -1
- package/{chunk-YGW4G5W5.js → chunk-P3RZ6DHN.js} +133 -25
- package/{chunk-5MIDPSSK.js → chunk-PB7G5MAM.js} +3 -3
- package/{chunk-HEGV7BH3.js → chunk-PMCKFQYC.js} +1 -1
- package/{chunk-23FZYPLC.js → chunk-PTKI7TIN.js} +911 -1064
- package/{chunk-MHSGJW4Z.js → chunk-PXPISYEH.js} +44 -14
- package/{chunk-I2ZJKTG5.js → chunk-PY7VGC5M.js} +29 -10
- package/{chunk-PIZYJVHQ.js → chunk-RM464B7I.js} +4 -4
- package/{chunk-XHG22OEX.js → chunk-ROJI6DRT.js} +2 -2
- package/{chunk-VNAEBGDK.js → chunk-RZNYL4LW.js} +123 -26
- package/{chunk-RVOUXDFU.js → chunk-S6KVFOUG.js} +6 -34
- package/{chunk-BV4VEE3W.js → chunk-S7AV3NCK.js} +277 -357
- package/{chunk-R35XMF6F.js → chunk-SIUEKVK4.js} +484 -67
- package/{chunk-B5TOXZAK.js → chunk-SIZQB7BD.js} +1 -1
- package/{chunk-DFFIZ25G.js → chunk-SLOGKB7M.js} +4 -1
- package/{chunk-MPVYDS7I.js → chunk-TLYHUIWF.js} +3 -3
- package/{chunk-HWW2M4SN.js → chunk-TNM27YZ7.js} +5 -4
- package/{chunk-OK6YSWLH.js → chunk-TWA4L7J7.js} +1 -1
- package/chunk-UZ6XXCVR.js +50 -0
- package/{chunk-DKZFOK24.js → chunk-WCP5FDTF.js} +16 -304
- package/{chunk-TRT4I4UD.js → chunk-WSQLK2KR.js} +2 -2
- package/{chunk-FXUSIQC2.js → chunk-XNZJVYFS.js} +1 -1
- package/{chunk-V3ED5AWK.js → chunk-YJY7HODU.js} +27 -16
- package/chunk-YYLHWIW6.js +48 -0
- package/{chunk-CZ6NYQTV.js → chunk-ZFL3LTU7.js} +2 -2
- package/{chunk-34WPV75U.js → chunk-ZUXIXYJI.js} +1 -1
- package/{chunk-VC6OZXO5.js → chunk-ZWJOGMKH.js} +2 -26
- package/{cliExecutor-DNE7TCC4.js → cliExecutor-K3F7DMRO.js} +2 -2
- package/{codingSkills-36KN5NQT.js → codingSkills-EN6Z6G6U.js} +4 -4
- package/{createAgentAutomationAction-GNFF524X.js → createAgentAutomationAction-PO62NUR7.js} +19 -18
- package/{createDialogAction-RB55KCLO.js → createDialogAction-ORFRYI3C.js} +22 -20
- package/{createPageAction-Y7343GLU.js → createPageAction-XWVMNTYH.js} +20 -19
- package/{db-W3O47YGF.js → db-W5UHK4P3.js} +150 -0
- package/{dbSlice-CGSRFJN3.js → dbSlice-5BKDURDL.js} +4 -4
- package/{dialogCommands-IAZK6YHQ.js → dialogCommands-XTJHROXM.js} +24 -23
- package/{dialogSlice-UQAXF23P.js → dialogSlice-DJXC53YW.js} +24 -18
- package/{docCreateCommands-I2EWZGCI.js → docCreateCommands-T2XRVXYS.js} +24 -27
- package/{docDeleteCommands-IZ45UZKG.js → docDeleteCommands-L7RXFXY3.js} +25 -24
- package/{docReadCommands-R6Z4QJYU.js → docReadCommands-M5PYNADQ.js} +24 -23
- package/{docStore-5HOJ4D7D.js → docStore-6LKLLFDW.js} +20 -19
- package/{docUpdateCommands-2LRBKQPY.js → docUpdateCommands-OA5EGPLQ.js} +24 -27
- package/{fetchMessages-BMGVZVSE.js → fetchMessages-W4IKHPCS.js} +2 -3
- package/{getPricing-G7DLAST6.js → getPricing-6C3C47Y4.js} +3 -3
- package/{handleSendMessageAction-Q4HY35WX.js → handleSendMessageAction-ILFGZTN5.js} +23 -20
- package/index.js +74 -74
- package/{localDialogRead-4H3QJFLW.js → localDialogRead-JXTAHW2E.js} +2 -2
- package/{machineCommands-PKBPQKTY.js → machineCommands-AKAQGPAO.js} +59 -57
- package/{machineWsRunDispatch-UZAW4OXJ.js → machineWsRunDispatch-RSBERM64.js} +51 -49
- package/{models-DJFSJ7SW.js → models-ILWKIX2Y.js} +2 -2
- package/package.json +1 -1
- package/{read-3FMPZPER.js → read-F3L3T2WJ.js} +2 -1
- package/{readDocTool-VSYHKK3V.js → readDocTool-FOHWVA4R.js} +1 -1
- package/{readlineWorkspace-Y2RDOFZG.js → readlineWorkspace-TUH3SFHO.js} +937 -430
- package/{removeDialogAgentAction-OAGA2G3U.js → removeDialogAgentAction-QCFGIUIH.js} +8 -7
- package/{runAgentClientLoop-NBPIKJ6J.js → runAgentClientLoop-C3QB2EXV.js} +45 -38
- package/{setDialogExtraReferencesAction-JZEXA5SL.js → setDialogExtraReferencesAction-DK4CKERU.js} +5 -5
- package/{setPrimaryDialogAgentAction-4ZUQQKDG.js → setPrimaryDialogAgentAction-SJSO6N27.js} +8 -7
- package/{settingSlice-7MNKHZ6R.js → settingSlice-XNM5AFPU.js} +6 -5
- package/{spaceCommands-DHCZ7J5I.js → spaceCommands-SXYOFGUJ.js} +25 -24
- package/{spaceSlice-ZXLLG3CR.js → spaceSlice-6BHMRP5O.js} +21 -18
- package/{streamAgentChatTurn-L3YW6LSB.js → streamAgentChatTurn-GF5W5OIP.js} +140 -98
- package/switchDialogAgentAction-4OAC6QRN.js +61 -0
- package/{tableCommands-BEQAGE4I.js → tableCommands-QSZILI7I.js} +1 -1
- package/{toolApiClient-QI3YBNWB.js → toolApiClient-ISM4ZQX4.js} +2 -2
- package/{tools-ECGXR5QF.js → tools-KBCLJ43G.js} +36 -33
- package/{tuiSummaryLlmCaller-OMSCNHXA.js → tuiSummaryLlmCaller-ARIMGILF.js} +6 -6
- package/{updateCommands-XTW55TOT.js → updateCommands-AK2RDOFR.js} +8 -2
- package/{updateDialogTitleAction-HQ2EUDFT.js → updateDialogTitleAction-LMHZUY4Q.js} +28 -27
- package/chunk-DL6EPNIK.js +0 -50
- package/chunk-V5R4NZP2.js +0 -78
- package/chunk-X4Q4UZEY.js +0 -26
- package/queryRunOverlay-O4LOMMPO.js +0 -161
- package/runOverlayPresentation-ZO4VCWEU.js +0 -11
- package/types-ZSTJ7MPR.js +0 -7
- package/{chunk-X7W4TNB4.js → chunk-CMKUBIGW.js} +3 -3
- package/{runtimeDoctorCommands-E2OUORHK.js → runtimeDoctorCommands-HSU632DY.js} +3 -3
|
@@ -3,11 +3,10 @@ import {
|
|
|
3
3
|
refreshAntigravityOAuthToken,
|
|
4
4
|
refreshOpenAiCodexToken,
|
|
5
5
|
refreshXaiOAuthToken
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TWA4L7J7.js";
|
|
7
7
|
import {
|
|
8
|
-
buildLocalAgentLookupKeys
|
|
9
|
-
|
|
10
|
-
} from "./chunk-SWDPIPOY.js";
|
|
8
|
+
buildLocalAgentLookupKeys
|
|
9
|
+
} from "./chunk-AZW5AHMW.js";
|
|
11
10
|
import {
|
|
12
11
|
LOCAL_CODEX_AGENT_ID,
|
|
13
12
|
LOCAL_CODEX_AGENT_KEY,
|
|
@@ -16,96 +15,111 @@ import {
|
|
|
16
15
|
} from "./chunk-VHBWHNVT.js";
|
|
17
16
|
import {
|
|
18
17
|
inferCaptureIntent
|
|
19
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-54VHTARN.js";
|
|
20
19
|
import {
|
|
21
20
|
inlineImageUrlsForCustomProvider,
|
|
22
21
|
prepareTools
|
|
23
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-ZFL3LTU7.js";
|
|
24
23
|
import {
|
|
25
24
|
getAntigravityUserAgent,
|
|
26
25
|
isAntigravityOAuthAgent,
|
|
27
26
|
readAntigravityProjectId,
|
|
28
27
|
resolveAntigravityCloudCodeBaseUrl
|
|
29
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-XNZJVYFS.js";
|
|
30
29
|
import {
|
|
31
|
-
FORCED_TOOLS,
|
|
32
|
-
addDefaultLightWebToolsForConfiguredAgents,
|
|
33
|
-
addDefaultSystemCapabilityTools,
|
|
34
|
-
appendEnabledPackPromptPatches,
|
|
35
|
-
applyDisabledTools,
|
|
36
|
-
applySystemBuiltinSkillFilter,
|
|
37
|
-
expandEnabledPacks,
|
|
38
30
|
readXPostFunc,
|
|
39
31
|
readXPostFunctionSchema,
|
|
40
32
|
readXhsProfileFunc,
|
|
41
33
|
readXhsProfileFunctionSchema,
|
|
42
34
|
rememberMemoryFunctionSchema,
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
resolveAgentRequiredPackIds,
|
|
36
|
+
setTodoListFunc
|
|
37
|
+
} from "./chunk-GGB6MPHD.js";
|
|
45
38
|
import {
|
|
46
39
|
createDrainExhaustedResponse,
|
|
47
40
|
isCoreDrainingBody,
|
|
48
41
|
normalizeNonNegativeMs,
|
|
49
42
|
parseRetryAfterHeaderMs
|
|
50
43
|
} from "./chunk-RQSOAMPJ.js";
|
|
51
|
-
import {
|
|
52
|
-
normalizeDialogTitle
|
|
53
|
-
} from "./chunk-OWOHNGCN.js";
|
|
54
44
|
import {
|
|
55
45
|
getDefaultCliLocalRuntimeDb
|
|
56
46
|
} from "./chunk-WJRJDX2W.js";
|
|
57
47
|
import {
|
|
58
|
-
|
|
59
|
-
|
|
48
|
+
applyTokenUsageToDayStats,
|
|
49
|
+
prepareTokenUsageData,
|
|
50
|
+
resolveBuiltinPlatformAgentConfig,
|
|
51
|
+
runKeyed
|
|
52
|
+
} from "./chunk-ADE6577S.js";
|
|
60
53
|
import {
|
|
61
54
|
BUILTIN_TITLE_LLM_CONFIG
|
|
62
55
|
} from "./chunk-XOIF2TNF.js";
|
|
63
56
|
import {
|
|
64
57
|
fetchServerSyncedCredential
|
|
65
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-GD23ZX7Z.js";
|
|
59
|
+
import {
|
|
60
|
+
require_date_fns
|
|
61
|
+
} from "./chunk-M76ECQRD.js";
|
|
62
|
+
import {
|
|
63
|
+
FORCED_TOOLS,
|
|
64
|
+
addDefaultLightWebToolsForConfiguredAgents,
|
|
65
|
+
addDefaultSystemCapabilityTools,
|
|
66
|
+
appendEnabledPackPromptPatches,
|
|
67
|
+
applyDisabledTools,
|
|
68
|
+
applySystemBuiltinSkillFilter,
|
|
69
|
+
expandEnabledPacks,
|
|
70
|
+
resolveEffectiveEnabledPacks
|
|
71
|
+
} from "./chunk-CF7S2RYZ.js";
|
|
66
72
|
import {
|
|
67
73
|
buildAgentRuntimeDialogWritePlan,
|
|
74
|
+
buildLoadSkillExecutor,
|
|
68
75
|
buildLocalWorkspaceOpenAiTools,
|
|
69
76
|
buildLocalWorkspaceToolset,
|
|
77
|
+
buildNoloWorkspaceCliToolExecutors,
|
|
70
78
|
createHybridRecordStore,
|
|
71
79
|
createLocalWorkspaceToolExecutors,
|
|
72
80
|
dialogMessageRecordToAgentRuntimeMessage,
|
|
73
81
|
executeLocalToolWithPolicy,
|
|
74
82
|
executeOpenAiCompatibleChatCompletion,
|
|
83
|
+
isAgentCoolingDown,
|
|
75
84
|
parseSseDataLineJson,
|
|
76
85
|
parseSseDataLineObject,
|
|
86
|
+
parseSyncServersEnv,
|
|
77
87
|
readOpenAiCompatibleSseCompletion,
|
|
88
|
+
resolveAgentNextAvailableAt,
|
|
78
89
|
resolveOpenAiCompatibleProviderConfig
|
|
79
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-SIUEKVK4.js";
|
|
80
91
|
import {
|
|
81
92
|
buildPlatformChatCompletionRequest,
|
|
82
93
|
canUsePlatformChatProvider,
|
|
94
|
+
hasDirectOpenAiCompatibleProvider,
|
|
83
95
|
parsePlatformChatCompletionData,
|
|
84
96
|
parsePlatformChatCompletionResponse,
|
|
85
97
|
readSseDataValues,
|
|
86
98
|
resolvePlatformChatProviderConfig,
|
|
87
99
|
shouldUsePlatformChatProvider
|
|
88
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-MCXQNEJ3.js";
|
|
89
101
|
import {
|
|
90
102
|
resolveAgentRuntimeConfigFromRecord
|
|
91
103
|
} from "./chunk-OIQPORYI.js";
|
|
92
104
|
import {
|
|
93
105
|
summarizeToolArguments
|
|
94
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-P3RZ6DHN.js";
|
|
95
107
|
import {
|
|
96
108
|
convertMessagesToResponsesInput,
|
|
97
109
|
toResponsesTools
|
|
98
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-D34RI6NI.js";
|
|
99
111
|
import {
|
|
100
112
|
resolvePlatformAuthToken
|
|
101
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-PXPISYEH.js";
|
|
102
114
|
import {
|
|
103
|
-
buildLoadSkillExecutor,
|
|
104
|
-
buildNoloWorkspaceCliToolExecutors,
|
|
105
115
|
buildNoloWorkspaceOpenAiTools,
|
|
106
116
|
parseNoloWorkspaceToolArguments,
|
|
107
117
|
resolveRuntimeToolSurfaceForAgent
|
|
108
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-WCP5FDTF.js";
|
|
119
|
+
import {
|
|
120
|
+
buildDialogFallbackTitleFromUserInput,
|
|
121
|
+
normalizeDialogTitle
|
|
122
|
+
} from "./chunk-2MBTWINN.js";
|
|
109
123
|
import {
|
|
110
124
|
clipCompactText
|
|
111
125
|
} from "./chunk-5MMAK75Q.js";
|
|
@@ -123,10 +137,7 @@ import {
|
|
|
123
137
|
} from "./chunk-JZPBVBIY.js";
|
|
124
138
|
import {
|
|
125
139
|
isAdaptiveThinkingModelId
|
|
126
|
-
} from "./chunk-
|
|
127
|
-
import {
|
|
128
|
-
toErrorMessage
|
|
129
|
-
} from "./chunk-HNMXYYJR.js";
|
|
140
|
+
} from "./chunk-LEHTC2FI.js";
|
|
130
141
|
import {
|
|
131
142
|
canonicalizeToolNames
|
|
132
143
|
} from "./chunk-ZZ2MH7LE.js";
|
|
@@ -134,13 +145,14 @@ import {
|
|
|
134
145
|
compactWhitespace
|
|
135
146
|
} from "./chunk-DWLEOOGR.js";
|
|
136
147
|
import {
|
|
148
|
+
ackRunRecord,
|
|
137
149
|
checkStaleRun,
|
|
138
150
|
finalizeRunRecord,
|
|
139
151
|
findRunRecord,
|
|
140
152
|
gcRunRecords,
|
|
141
153
|
queryRunRecords,
|
|
142
154
|
spawnLocalBackgroundRun
|
|
143
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-RZNYL4LW.js";
|
|
144
156
|
import {
|
|
145
157
|
TASK_PREVIEW_MAX,
|
|
146
158
|
formatListRunsCard,
|
|
@@ -152,14 +164,17 @@ import {
|
|
|
152
164
|
isAgentRunTerminalStatus,
|
|
153
165
|
resolveRunLabel,
|
|
154
166
|
shortRunId
|
|
155
|
-
} from "./chunk-
|
|
167
|
+
} from "./chunk-KXKQO4Q6.js";
|
|
156
168
|
import {
|
|
157
169
|
CliProviderQuotaError,
|
|
158
170
|
executeCli
|
|
159
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-CMKUBIGW.js";
|
|
160
172
|
import {
|
|
161
173
|
buildCliPrompt
|
|
162
174
|
} from "./chunk-ATNTHIZI.js";
|
|
175
|
+
import {
|
|
176
|
+
toErrorMessage
|
|
177
|
+
} from "./chunk-HNMXYYJR.js";
|
|
163
178
|
import {
|
|
164
179
|
isCompiledBinary,
|
|
165
180
|
parseUserIdFromAuthToken
|
|
@@ -169,9 +184,10 @@ import {
|
|
|
169
184
|
} from "./chunk-OLZBQWZU.js";
|
|
170
185
|
import {
|
|
171
186
|
createTokenKey,
|
|
187
|
+
createTokenStatsKey,
|
|
172
188
|
createUserKey,
|
|
173
189
|
dialogMessageRange
|
|
174
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-NRY4GCKJ.js";
|
|
175
191
|
import {
|
|
176
192
|
asOptionalFiniteNumber
|
|
177
193
|
} from "./chunk-WWC7I6TA.js";
|
|
@@ -182,15 +198,8 @@ import {
|
|
|
182
198
|
asTrimmedLowercaseString
|
|
183
199
|
} from "./chunk-QSJ3HFEF.js";
|
|
184
200
|
import {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
|
|
188
|
-
PUBLIC_GLM_52_AGENT_KEY,
|
|
189
|
-
PUBLIC_KIMI_K26_IMAGE_AGENT_KEY
|
|
190
|
-
} from "./chunk-3ND52WIL.js";
|
|
191
|
-
import {
|
|
192
|
-
asTrimmedString
|
|
193
|
-
} from "./chunk-3EUW3WEO.js";
|
|
201
|
+
isSystemBuiltinTrustedAgentKey
|
|
202
|
+
} from "./chunk-ATWUOTJP.js";
|
|
194
203
|
import {
|
|
195
204
|
isRecord
|
|
196
205
|
} from "./chunk-KUG52IAP.js";
|
|
@@ -206,6 +215,9 @@ import {
|
|
|
206
215
|
import {
|
|
207
216
|
asOptionalTrimmedString
|
|
208
217
|
} from "./chunk-G3SUCT4W.js";
|
|
218
|
+
import {
|
|
219
|
+
__toESM
|
|
220
|
+
} from "./chunk-4VNS5WPM.js";
|
|
209
221
|
|
|
210
222
|
// packages/cli/tui/i18n.ts
|
|
211
223
|
var ZH_PATTERNS = /^zh/i;
|
|
@@ -782,6 +794,18 @@ var STRINGS = {
|
|
|
782
794
|
en: "Forked dialog {0} \u2192 {1} (no summary needed).",
|
|
783
795
|
zh: "\u5DF2\u5206\u53C9\u5BF9\u8BDD {0} \u2192 {1}\uFF08\u65E0\u9700\u538B\u7F29\uFF09\u3002"
|
|
784
796
|
},
|
|
797
|
+
compactSuccess: {
|
|
798
|
+
en: "\u2713 Compacted dialog {0} \u2192 {1} in {2}.",
|
|
799
|
+
zh: "\u2713 \u5DF2\u538B\u7F29\u5BF9\u8BDD {0} \u2192 {1}\uFF0C\u8017\u65F6 {2}\u3002"
|
|
800
|
+
},
|
|
801
|
+
compactSuccessWithCount: {
|
|
802
|
+
en: "\u2713 Compacted dialog {0} \u2192 {1} in {2} ({3} messages compressed).",
|
|
803
|
+
zh: "\u2713 \u5DF2\u538B\u7F29\u5BF9\u8BDD {0} \u2192 {1}\uFF0C\u8017\u65F6 {2}\uFF08\u538B\u7F29 {3} \u6761\u6D88\u606F\uFF09\u3002"
|
|
804
|
+
},
|
|
805
|
+
compactForked: {
|
|
806
|
+
en: "\u2713 Forked dialog {0} \u2192 {1} in {2} (no summary needed).",
|
|
807
|
+
zh: "\u2713 \u5DF2\u5206\u53C9\u5BF9\u8BDD {0} \u2192 {1}\uFF0C\u8017\u65F6 {2}\uFF08\u65E0\u9700\u538B\u7F29\uFF09\u3002"
|
|
808
|
+
},
|
|
785
809
|
agentCurrent: { en: "Current agent: {0} ({1})", zh: "\u5F53\u524D agent\uFF1A{0}\uFF08{1}\uFF09" },
|
|
786
810
|
agentUnknown: {
|
|
787
811
|
en: `I don't know agent "{0}" yet.
|
|
@@ -849,6 +873,10 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`,
|
|
|
849
873
|
zh: "nolo {0}\n\u7528 nolo update \u66F4\u65B0\u5F53\u524D\u5B89\u88C5\u3002\n\u5982\u679C\u672C\u5730\u4ED3\u5E93\u8F93\u51FA\u7684\u7248\u672C\u4E0D\u540C\uFF0C\u8BF7\u5148\u53D1\u5E03/\u5B89\u88C5\u6700\u65B0\u7684 npm \u5305\u3002"
|
|
850
874
|
},
|
|
851
875
|
versionUnknown: { en: "unknown version", zh: "\u672A\u77E5\u7248\u672C" },
|
|
876
|
+
updateAvailable: {
|
|
877
|
+
en: "New nolo {0} available (you have {1}) \u2014 run /update to upgrade",
|
|
878
|
+
zh: "\u65B0\u7248\u672C nolo {0} \u53EF\u7528\uFF08\u5F53\u524D {1}\uFF09\u2014 \u8FD0\u884C /update \u5347\u7EA7"
|
|
879
|
+
},
|
|
852
880
|
// --- Dialog list / timestamps -----------------------------------------
|
|
853
881
|
recentDialogs: { en: "Recent dialogs:", zh: "\u6700\u8FD1\u5BF9\u8BDD\uFF1A" },
|
|
854
882
|
dialogListTip: {
|
|
@@ -915,6 +943,11 @@ var TOOL_LABELS = {
|
|
|
915
943
|
captureVisualState: { en: "Capture", zh: "\u622A\u5C4F" },
|
|
916
944
|
// Workspace / diagnostics
|
|
917
945
|
searchWorkspace: { en: "Search workspace", zh: "\u641C\u7D22\u5DE5\u4F5C\u533A" },
|
|
946
|
+
// 同一工具在 web/server 工具面用 snake_case 命名(packages/ai/tools/index.ts)。
|
|
947
|
+
search_workspace: { en: "Search workspace", zh: "\u641C\u7D22\u5DE5\u4F5C\u533A" },
|
|
948
|
+
// 全空间搜索:内置 skill search-all-spaces 声明的工作区工具,loadSkill 后进入
|
|
949
|
+
// 工具面;同样需要中英文标签,避免回退成裸工具名。
|
|
950
|
+
search_all_spaces: { en: "Search all spaces", zh: "\u641C\u7D22\u5168\u90E8\u7A7A\u95F4" },
|
|
918
951
|
cliDoctor: { en: "Doctor", zh: "\u81EA\u68C0" },
|
|
919
952
|
cliWhoami: { en: "Whoami", zh: "\u67E5\u770B\u8EAB\u4EFD" },
|
|
920
953
|
checkEnv: { en: "Check env", zh: "\u68C0\u67E5\u73AF\u5883" },
|
|
@@ -960,185 +993,6 @@ function agentRunCardLabels() {
|
|
|
960
993
|
};
|
|
961
994
|
}
|
|
962
995
|
|
|
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
|
-
|
|
1142
996
|
// packages/cli/client/localRuntimeDiagnostics.ts
|
|
1143
997
|
import { ulid } from "ulid";
|
|
1144
998
|
var preparedAgentRuntimeCache = /* @__PURE__ */ new Map();
|
|
@@ -1177,6 +1031,36 @@ function summarizeOpenAiToolNames(tools) {
|
|
|
1177
1031
|
}, []);
|
|
1178
1032
|
}
|
|
1179
1033
|
|
|
1034
|
+
// packages/agent-runtime/agentRunIsolation.ts
|
|
1035
|
+
var ORCHESTRATION_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1036
|
+
"startAgentRun",
|
|
1037
|
+
"controlAgentRun",
|
|
1038
|
+
"listAgents",
|
|
1039
|
+
"readAgent",
|
|
1040
|
+
"startAgentDialog",
|
|
1041
|
+
"runStreamingAgent",
|
|
1042
|
+
"streamParallelAgents"
|
|
1043
|
+
]);
|
|
1044
|
+
var SUBTASK_REMOVED_GIT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1045
|
+
"gitAdd",
|
|
1046
|
+
"gitCommit",
|
|
1047
|
+
"gitCreateBranch",
|
|
1048
|
+
"commitWorkspace"
|
|
1049
|
+
]);
|
|
1050
|
+
var SUBTASK_REMOVED_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1051
|
+
...ORCHESTRATION_TOOL_NAMES,
|
|
1052
|
+
...SUBTASK_REMOVED_GIT_TOOL_NAMES
|
|
1053
|
+
]);
|
|
1054
|
+
function isSubtaskRun(env) {
|
|
1055
|
+
if (!env) return false;
|
|
1056
|
+
const value = env.NOLO_AGENT_RUN_CHILD;
|
|
1057
|
+
return typeof value === "string" && value.length > 0 && value !== "0";
|
|
1058
|
+
}
|
|
1059
|
+
function filterToolNamesForRunKind(toolNames, isSubtask) {
|
|
1060
|
+
if (!isSubtask) return [...toolNames];
|
|
1061
|
+
return toolNames.filter((name) => !SUBTASK_REMOVED_TOOL_NAMES.has(name));
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1180
1064
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
1181
1065
|
import { dirname as dirname2, extname, join as join2 } from "node:path";
|
|
1182
1066
|
import { fileURLToPath } from "node:url";
|
|
@@ -1662,93 +1546,6 @@ function assertWithinLocalToolBudget(args) {
|
|
|
1662
1546
|
);
|
|
1663
1547
|
}
|
|
1664
1548
|
|
|
1665
|
-
// packages/agent-runtime/builtinPlatformAgentConfigs.ts
|
|
1666
|
-
var BUILTIN_PLATFORM_AGENT_CONFIGS = {
|
|
1667
|
-
[PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY]: {
|
|
1668
|
-
key: PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
|
|
1669
|
-
name: "DeepSeek V4 Flash",
|
|
1670
|
-
provider: "nolo",
|
|
1671
|
-
model: "deepseek-v4-flash",
|
|
1672
|
-
apiSource: "platform",
|
|
1673
|
-
useServerProxy: true,
|
|
1674
|
-
rawRecord: {
|
|
1675
|
-
dbKey: PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
|
|
1676
|
-
isPublic: true,
|
|
1677
|
-
provider: "nolo",
|
|
1678
|
-
model: "deepseek-v4-flash",
|
|
1679
|
-
apiSource: "platform",
|
|
1680
|
-
useServerProxy: true
|
|
1681
|
-
}
|
|
1682
|
-
},
|
|
1683
|
-
[PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY]: {
|
|
1684
|
-
key: PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
|
|
1685
|
-
name: "DeepSeek V4 Pro",
|
|
1686
|
-
provider: "nolo",
|
|
1687
|
-
model: "deepseek-v4-pro",
|
|
1688
|
-
apiSource: "platform",
|
|
1689
|
-
useServerProxy: true,
|
|
1690
|
-
rawRecord: {
|
|
1691
|
-
dbKey: PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
|
|
1692
|
-
isPublic: true,
|
|
1693
|
-
provider: "nolo",
|
|
1694
|
-
model: "deepseek-v4-pro",
|
|
1695
|
-
apiSource: "platform",
|
|
1696
|
-
useServerProxy: true
|
|
1697
|
-
}
|
|
1698
|
-
},
|
|
1699
|
-
[PUBLIC_GLM_52_AGENT_KEY]: {
|
|
1700
|
-
key: PUBLIC_GLM_52_AGENT_KEY,
|
|
1701
|
-
name: "GLM 5.2",
|
|
1702
|
-
provider: "nolo",
|
|
1703
|
-
model: "glm-5.2",
|
|
1704
|
-
apiSource: "platform",
|
|
1705
|
-
useServerProxy: true,
|
|
1706
|
-
rawRecord: {
|
|
1707
|
-
dbKey: PUBLIC_GLM_52_AGENT_KEY,
|
|
1708
|
-
isPublic: true,
|
|
1709
|
-
provider: "nolo",
|
|
1710
|
-
model: "glm-5.2",
|
|
1711
|
-
apiSource: "platform",
|
|
1712
|
-
useServerProxy: true
|
|
1713
|
-
}
|
|
1714
|
-
},
|
|
1715
|
-
[PUBLIC_KIMI_K26_IMAGE_AGENT_KEY]: {
|
|
1716
|
-
key: PUBLIC_KIMI_K26_IMAGE_AGENT_KEY,
|
|
1717
|
-
name: "Kimi K2.6",
|
|
1718
|
-
provider: "nolo",
|
|
1719
|
-
model: "kimi-k2.6",
|
|
1720
|
-
apiSource: "platform",
|
|
1721
|
-
useServerProxy: true,
|
|
1722
|
-
rawRecord: {
|
|
1723
|
-
dbKey: PUBLIC_KIMI_K26_IMAGE_AGENT_KEY,
|
|
1724
|
-
isPublic: true,
|
|
1725
|
-
provider: "nolo",
|
|
1726
|
-
model: "kimi-k2.6",
|
|
1727
|
-
apiSource: "platform",
|
|
1728
|
-
useServerProxy: true
|
|
1729
|
-
}
|
|
1730
|
-
},
|
|
1731
|
-
[BUILTIN_NOLO_AGENT_KEY]: {
|
|
1732
|
-
key: BUILTIN_NOLO_AGENT_KEY,
|
|
1733
|
-
name: "Nolo",
|
|
1734
|
-
provider: "nolo",
|
|
1735
|
-
model: "deepseek-v4-flash",
|
|
1736
|
-
apiSource: "platform",
|
|
1737
|
-
useServerProxy: true,
|
|
1738
|
-
rawRecord: {
|
|
1739
|
-
dbKey: BUILTIN_NOLO_AGENT_KEY,
|
|
1740
|
-
isPublic: true,
|
|
1741
|
-
provider: "nolo",
|
|
1742
|
-
model: "deepseek-v4-flash",
|
|
1743
|
-
apiSource: "platform",
|
|
1744
|
-
useServerProxy: true
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
};
|
|
1748
|
-
function resolveBuiltinPlatformAgentConfig(agentRef) {
|
|
1749
|
-
return BUILTIN_PLATFORM_AGENT_CONFIGS[agentRef] ?? null;
|
|
1750
|
-
}
|
|
1751
|
-
|
|
1752
1549
|
// packages/cli/client/localDialogRecords.ts
|
|
1753
1550
|
var localDialogMessageRecordToRuntimeMessage = dialogMessageRecordToAgentRuntimeMessage;
|
|
1754
1551
|
function buildLocalDialogWritePlan(args) {
|
|
@@ -1794,9 +1591,7 @@ function resolveBuiltinLocalCliAgentConfig(agentRef, userId) {
|
|
|
1794
1591
|
}
|
|
1795
1592
|
async function readAgentFromStore(args) {
|
|
1796
1593
|
for (const key of buildLocalAgentLookupKeys(args)) {
|
|
1797
|
-
const record = await args.store.read(key
|
|
1798
|
-
remote: shouldReadAgentKeyRemotely(key)
|
|
1799
|
-
});
|
|
1594
|
+
const record = await args.store.read(key);
|
|
1800
1595
|
if (!record || typeof record !== "object") continue;
|
|
1801
1596
|
return resolveAgentRuntimeConfigFromRecord(key, record);
|
|
1802
1597
|
}
|
|
@@ -1814,22 +1609,6 @@ async function readDialogMessages(args) {
|
|
|
1814
1609
|
}
|
|
1815
1610
|
|
|
1816
1611
|
// packages/cli/client/cliProviderHelpers.ts
|
|
1817
|
-
function buildDelegatedTaskContent(task, input) {
|
|
1818
|
-
if (input === void 0 || input === null) {
|
|
1819
|
-
return task;
|
|
1820
|
-
}
|
|
1821
|
-
if (typeof input === "string") {
|
|
1822
|
-
return `${task}
|
|
1823
|
-
|
|
1824
|
-
--- INPUT (text) ---
|
|
1825
|
-
${input}`;
|
|
1826
|
-
}
|
|
1827
|
-
const jsonStr = JSON.stringify(input, null, 2);
|
|
1828
|
-
return `${task}
|
|
1829
|
-
|
|
1830
|
-
--- INPUT (json) ---
|
|
1831
|
-
${jsonStr}`;
|
|
1832
|
-
}
|
|
1833
1612
|
function isCliProviderAgent(agentConfig) {
|
|
1834
1613
|
return Boolean(
|
|
1835
1614
|
agentConfig.apiSource === "cli" || agentConfig.provider === "cli" || agentConfig.cliProvider
|
|
@@ -1890,7 +1669,7 @@ function collectCliProviderImageInputs(messages) {
|
|
|
1890
1669
|
}
|
|
1891
1670
|
|
|
1892
1671
|
// packages/cli/client/cliAgentConfigHelpers.ts
|
|
1893
|
-
var
|
|
1672
|
+
var BUILTIN_NOLO_AGENT_KEY = NOLO_DEFAULT_AGENT_KEY;
|
|
1894
1673
|
var BUILTIN_NOLO_AGENT_ID = NOLO_DEFAULT_AGENT_ID;
|
|
1895
1674
|
function resolveLocalUserId(env) {
|
|
1896
1675
|
const explicitUserId = env.NOLO_LOCAL_USER_ID || env.NOLO_USER_ID;
|
|
@@ -1901,7 +1680,7 @@ function resolveLocalUserId(env) {
|
|
|
1901
1680
|
function isBuiltinNoloAgentRef(ref) {
|
|
1902
1681
|
if (typeof ref !== "string") return false;
|
|
1903
1682
|
const normalized = ref.trim();
|
|
1904
|
-
return normalized ===
|
|
1683
|
+
return normalized === BUILTIN_NOLO_AGENT_KEY || normalized === BUILTIN_NOLO_AGENT_ID || normalized.endsWith(`-${BUILTIN_NOLO_AGENT_ID}`);
|
|
1905
1684
|
}
|
|
1906
1685
|
function isBuiltinNoloAgentConfig(agentConfig) {
|
|
1907
1686
|
const key = agentConfig?.key || agentConfig?.rawRecord?.dbKey || agentConfig?.rawRecord?.agentKey;
|
|
@@ -1913,14 +1692,15 @@ function withResolvedRuntimeToolSurface(agentConfig, env) {
|
|
|
1913
1692
|
const currentUserId = resolveLocalUserId(env);
|
|
1914
1693
|
const rawRecord = agentConfig.rawRecord ?? {};
|
|
1915
1694
|
const ownerId = asOptionalTrimmedString(rawRecord.userId) ?? null;
|
|
1695
|
+
const agentKey = rawRecord.dbKey ?? agentConfig.key;
|
|
1916
1696
|
const toolSurface = resolveRuntimeToolSurfaceForAgent({
|
|
1917
1697
|
explicitToolNames: agentConfig.toolNames,
|
|
1918
1698
|
currentUserId,
|
|
1919
1699
|
agentOwnerId: ownerId,
|
|
1920
|
-
agentKey
|
|
1700
|
+
agentKey,
|
|
1921
1701
|
isPublic: !isBuiltinNoloAgentConfig(agentConfig) && rawRecord.isPublic === true,
|
|
1922
1702
|
sharingLevel: typeof rawRecord.sharingLevel === "string" ? rawRecord.sharingLevel : null,
|
|
1923
|
-
trustedPrivateInvocation: isBuiltinNoloAgentConfig(agentConfig),
|
|
1703
|
+
trustedPrivateInvocation: isBuiltinNoloAgentConfig(agentConfig) || isSystemBuiltinTrustedAgentKey(agentKey),
|
|
1924
1704
|
runtimeHost: "cli"
|
|
1925
1705
|
});
|
|
1926
1706
|
return {
|
|
@@ -2439,54 +2219,29 @@ function aggregateBatch(input) {
|
|
|
2439
2219
|
};
|
|
2440
2220
|
}
|
|
2441
2221
|
|
|
2442
|
-
// packages/ai/tools/agent/
|
|
2443
|
-
var
|
|
2444
|
-
|
|
2222
|
+
// packages/ai/tools/agent/agentRunTodo.ts
|
|
2223
|
+
var SUCCESS_STATUSES = /* @__PURE__ */ new Set(["completed", "done", "success", "passed", "finished"]);
|
|
2224
|
+
var FAILED_STATUSES = /* @__PURE__ */ new Set(["failed", "error", "stopped", "cancelled", "orphaned", "blocked"]);
|
|
2225
|
+
function deriveAgentRunTodoStatus(input) {
|
|
2445
2226
|
const { todo, runs } = input;
|
|
2446
|
-
if (
|
|
2447
|
-
return { status: "
|
|
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) };
|
|
2227
|
+
if (!runs || runs.length === 0) {
|
|
2228
|
+
return { status: todo.status ?? "pending" };
|
|
2454
2229
|
}
|
|
2455
|
-
const
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
};
|
|
2230
|
+
const latestRun = runs[runs.length - 1];
|
|
2231
|
+
const hasRunning = runs.some(
|
|
2232
|
+
(r) => r.status === "running" || r.status === "in_progress" || r.status === "executing"
|
|
2233
|
+
);
|
|
2234
|
+
if (hasRunning) {
|
|
2235
|
+
return { status: "running", latestRun };
|
|
2462
2236
|
}
|
|
2463
|
-
|
|
2464
|
-
|
|
2237
|
+
const runStatus = (latestRun.status || "").toLowerCase();
|
|
2238
|
+
if (SUCCESS_STATUSES.has(runStatus)) {
|
|
2239
|
+
return { status: "done", latestRun };
|
|
2465
2240
|
}
|
|
2466
|
-
|
|
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
|
-
}
|
|
2241
|
+
if (FAILED_STATUSES.has(runStatus)) {
|
|
2242
|
+
return { status: "failed", latestRun };
|
|
2482
2243
|
}
|
|
2483
|
-
return
|
|
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;
|
|
2244
|
+
return { status: todo.status ?? "pending", latestRun };
|
|
2490
2245
|
}
|
|
2491
2246
|
|
|
2492
2247
|
// packages/cli/client/fileSystemStores.ts
|
|
@@ -2519,50 +2274,41 @@ function readJson(path, fs) {
|
|
|
2519
2274
|
function writeJson(path, data, fs) {
|
|
2520
2275
|
fs.writeFileSync(path, JSON.stringify(data, null, 2));
|
|
2521
2276
|
}
|
|
2522
|
-
function
|
|
2277
|
+
function createFileSystemTodoStore(opts = {}) {
|
|
2523
2278
|
const env = opts.env ?? process.env;
|
|
2524
2279
|
const homedir = opts.homedir ?? nodeHomedir;
|
|
2525
2280
|
const fs = opts.fs ?? nodeFs;
|
|
2526
|
-
const
|
|
2281
|
+
const noloHome = resolveNoloHome(env, homedir);
|
|
2282
|
+
const filePath = opts.filePath ?? join(noloHome, "agent_run_todos.json");
|
|
2283
|
+
const oldFilePath = join(noloHome, "todos.json");
|
|
2527
2284
|
const loadMap = () => {
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2285
|
+
if (!opts.filePath && !fs.existsSync(filePath) && fs.existsSync(oldFilePath)) {
|
|
2286
|
+
const oldData = readJson(oldFilePath, fs);
|
|
2287
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
2288
|
+
if (oldData?.todos) {
|
|
2289
|
+
for (const item of oldData.todos) {
|
|
2290
|
+
if (item && typeof item.id === "string") {
|
|
2291
|
+
let status = "pending";
|
|
2292
|
+
if (item.status === "running") status = "running";
|
|
2293
|
+
else if (item.status === "done") status = "done";
|
|
2294
|
+
else if (item.status === "blocked" || item.status === "abandoned" || item.status === "failed") status = "failed";
|
|
2295
|
+
const rec = {
|
|
2296
|
+
...item,
|
|
2297
|
+
id: item.id,
|
|
2298
|
+
title: item.title || "Untitled Task",
|
|
2299
|
+
status,
|
|
2300
|
+
runIds: Array.isArray(item.runIds) ? item.runIds : [],
|
|
2301
|
+
createdAt: item.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
2302
|
+
updatedAt: item.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
2303
|
+
};
|
|
2304
|
+
map2.set(rec.id, rec);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2533
2307
|
}
|
|
2308
|
+
ensureDir(dirname(filePath), fs);
|
|
2309
|
+
writeJson(filePath, { todos: [...map2.values()] }, fs);
|
|
2310
|
+
return map2;
|
|
2534
2311
|
}
|
|
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
2312
|
const data = readJson(filePath, fs);
|
|
2567
2313
|
const map = /* @__PURE__ */ new Map();
|
|
2568
2314
|
if (data?.todos) {
|
|
@@ -2578,13 +2324,15 @@ function createFileSystemTodoStore(opts = {}) {
|
|
|
2578
2324
|
};
|
|
2579
2325
|
return {
|
|
2580
2326
|
async getTodo(id) {
|
|
2581
|
-
return loadMap().get(id);
|
|
2327
|
+
return loadMap().get(id) ?? null;
|
|
2582
2328
|
},
|
|
2583
|
-
async listTodos(
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2329
|
+
async listTodos() {
|
|
2330
|
+
return [...loadMap().values()];
|
|
2331
|
+
},
|
|
2332
|
+
async saveTodo(todo) {
|
|
2333
|
+
const map = loadMap();
|
|
2334
|
+
map.set(todo.id, todo);
|
|
2335
|
+
persist(map);
|
|
2588
2336
|
},
|
|
2589
2337
|
async putTodo(todo) {
|
|
2590
2338
|
const map = loadMap();
|
|
@@ -2593,8 +2341,10 @@ function createFileSystemTodoStore(opts = {}) {
|
|
|
2593
2341
|
},
|
|
2594
2342
|
async deleteTodo(id) {
|
|
2595
2343
|
const map = loadMap();
|
|
2344
|
+
const existed = map.has(id);
|
|
2596
2345
|
map.delete(id);
|
|
2597
2346
|
persist(map);
|
|
2347
|
+
return existed;
|
|
2598
2348
|
}
|
|
2599
2349
|
};
|
|
2600
2350
|
}
|
|
@@ -2621,10 +2371,8 @@ var tailFile = (logPath, tailLines, fs) => {
|
|
|
2621
2371
|
return void 0;
|
|
2622
2372
|
}
|
|
2623
2373
|
};
|
|
2624
|
-
var resolveBreakerStore = (deps) => deps.breakerStore ?? createFileSystemCircuitBreakerStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2625
2374
|
var resolveTodoStore = (deps) => deps.todoStore ?? createFileSystemTodoStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2626
2375
|
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
2376
|
function buildProgressField(record, nowMs) {
|
|
2629
2377
|
const activity = record.activity;
|
|
2630
2378
|
if (!activity || isAgentRunTerminalStatus(record.status)) return {};
|
|
@@ -2642,6 +2390,55 @@ function buildProgressField(record, nowMs) {
|
|
|
2642
2390
|
}
|
|
2643
2391
|
return { progress };
|
|
2644
2392
|
}
|
|
2393
|
+
var WAIT_POLL_INTERVAL_MS = 500;
|
|
2394
|
+
var DEFAULT_WAIT_TIMEOUT_MS = 1e5;
|
|
2395
|
+
function buildRunStatusPayload(reconciled, deps, opts = {}) {
|
|
2396
|
+
const logLines = opts.logTail ? opts.logTail.split("\n") : void 0;
|
|
2397
|
+
const name = resolveRunLabel(reconciled);
|
|
2398
|
+
const labels = agentRunCardLabels();
|
|
2399
|
+
return {
|
|
2400
|
+
content: JSON.stringify({
|
|
2401
|
+
runId: reconciled.runId,
|
|
2402
|
+
found: true,
|
|
2403
|
+
status: reconciled.status,
|
|
2404
|
+
pid: reconciled.pid ?? null,
|
|
2405
|
+
agentKey: reconciled.agentKey,
|
|
2406
|
+
...reconciled.agentName ? { agentName: reconciled.agentName } : {},
|
|
2407
|
+
startedAt: reconciled.startedAt,
|
|
2408
|
+
endedAt: reconciled.endedAt ?? null,
|
|
2409
|
+
exitCode: reconciled.exitCode ?? null,
|
|
2410
|
+
// Expose dialogId so the caller can read the agent's actual output
|
|
2411
|
+
// via `nolo dialog read <dialogId>`. The dialog is the authoritative
|
|
2412
|
+
// result store; the run log is the child process stdout/stderr,
|
|
2413
|
+
// whose contents vary by provider (some stream tokens to stdout,
|
|
2414
|
+
// some only emit startup + stderr). Because status does not carry
|
|
2415
|
+
// logTail by default, a "done" run with an empty logTail is
|
|
2416
|
+
// indistinguishable from a hung run without this field. Surfacing
|
|
2417
|
+
// dialogId gives the caller a reliable way to fetch the result.
|
|
2418
|
+
...reconciled.dialogId ? { dialogId: reconciled.dialogId } : {},
|
|
2419
|
+
// Progress is what makes tailLines:0 an actual answer to "is it
|
|
2420
|
+
// stuck?". Without it a poll returns `running` and a pid, so the only
|
|
2421
|
+
// way to tell a working run from a wedged one was to pull 30 lines of
|
|
2422
|
+
// log — the exact thing the orchestration prompt tells the model not
|
|
2423
|
+
// to do. The registry has been recording this all along and `nolo
|
|
2424
|
+
// agent status` has been printing it; only the tool was blind.
|
|
2425
|
+
...buildProgressField(reconciled, resolveNowMs(deps)),
|
|
2426
|
+
...opts.logTail !== void 0 ? { logTail: opts.logTail } : {},
|
|
2427
|
+
...logLines ? { logLines } : {}
|
|
2428
|
+
}),
|
|
2429
|
+
metadata: {
|
|
2430
|
+
displayData: formatStatusRunCard(name, reconciled.status, {
|
|
2431
|
+
runId: reconciled.runId,
|
|
2432
|
+
timing: {
|
|
2433
|
+
startedAt: readTimestamp(reconciled.startedAt),
|
|
2434
|
+
finishedAt: readTimestamp(reconciled.endedAt)
|
|
2435
|
+
},
|
|
2436
|
+
logLines,
|
|
2437
|
+
labels
|
|
2438
|
+
})
|
|
2439
|
+
}
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2645
2442
|
function createCliStartAgentRunExecutor(deps = {}) {
|
|
2646
2443
|
return async (call) => {
|
|
2647
2444
|
const args = parseCallArgs(call);
|
|
@@ -2649,29 +2446,7 @@ function createCliStartAgentRunExecutor(deps = {}) {
|
|
|
2649
2446
|
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
2650
2447
|
if (!agentKey) throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
|
|
2651
2448
|
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
2449
|
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
|
-
}
|
|
2675
2450
|
const message = typeof args.input === "undefined" ? task : `${task}
|
|
2676
2451
|
|
|
2677
2452
|
--- \u9644\u52A0\u8F93\u5165 ---
|
|
@@ -2719,16 +2494,15 @@ ${JSON.stringify(args.input)}`;
|
|
|
2719
2494
|
id: todoId,
|
|
2720
2495
|
title: taskPreview || task.slice(0, 100),
|
|
2721
2496
|
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
2497
|
runIds,
|
|
2727
|
-
deps: existing?.deps ?? [],
|
|
2728
2498
|
createdAt: existing?.createdAt ?? nowIso,
|
|
2729
2499
|
updatedAt: nowIso
|
|
2730
2500
|
};
|
|
2731
|
-
|
|
2501
|
+
if (typeof todoStore.saveTodo === "function") {
|
|
2502
|
+
await todoStore.saveTodo(todo);
|
|
2503
|
+
} else {
|
|
2504
|
+
await todoStore.putTodo(todo);
|
|
2505
|
+
}
|
|
2732
2506
|
} catch {
|
|
2733
2507
|
}
|
|
2734
2508
|
}
|
|
@@ -2808,12 +2582,11 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2808
2582
|
}
|
|
2809
2583
|
};
|
|
2810
2584
|
}
|
|
2811
|
-
if (action === "todo") {
|
|
2585
|
+
if (action === "todo" || action === "agentRunTodo" || action === "agent_run_todo") {
|
|
2812
2586
|
const todoStore = resolveTodoStore(deps);
|
|
2813
|
-
const
|
|
2814
|
-
const
|
|
2815
|
-
|
|
2816
|
-
const enriched = await Promise.all(
|
|
2587
|
+
const todos = await todoStore.listTodos();
|
|
2588
|
+
const statusFilter = typeof args.status === "string" ? args.status.trim().toLowerCase() : void 0;
|
|
2589
|
+
let enriched = await Promise.all(
|
|
2817
2590
|
todos.map(async (todo) => {
|
|
2818
2591
|
const runSummaries = [];
|
|
2819
2592
|
for (const rid of todo.runIds) {
|
|
@@ -2822,26 +2595,29 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2822
2595
|
runSummaries.push({
|
|
2823
2596
|
runId: rec.runId,
|
|
2824
2597
|
status: rec.status,
|
|
2825
|
-
startedAt: rec.startedAt,
|
|
2598
|
+
startedAt: readTimestamp(rec.startedAt)?.toString(),
|
|
2599
|
+
finishedAt: readTimestamp(rec.endedAt)?.toString(),
|
|
2826
2600
|
...rec.agentName ? { agentName: rec.agentName } : {}
|
|
2827
2601
|
});
|
|
2828
2602
|
}
|
|
2829
|
-
const derived =
|
|
2603
|
+
const derived = deriveAgentRunTodoStatus({
|
|
2830
2604
|
todo: { id: todo.id, status: todo.status },
|
|
2831
|
-
runs: runSummaries
|
|
2832
|
-
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2605
|
+
runs: runSummaries
|
|
2833
2606
|
});
|
|
2834
2607
|
return {
|
|
2835
2608
|
id: todo.id,
|
|
2836
2609
|
title: todo.title,
|
|
2837
2610
|
status: derived.status,
|
|
2838
2611
|
runIds: todo.runIds,
|
|
2839
|
-
...derived.blockedReason ? { blockedReason: derived.blockedReason } : {},
|
|
2840
2612
|
...derived.latestRun ? { latestRunId: derived.latestRun.runId, latestRunStatus: derived.latestRun.status } : {},
|
|
2841
2613
|
updatedAt: todo.updatedAt
|
|
2842
2614
|
};
|
|
2843
2615
|
})
|
|
2844
2616
|
);
|
|
2617
|
+
if (statusFilter && statusFilter !== "all") {
|
|
2618
|
+
const wanted = new Set(statusFilter.split(",").map((s) => s.trim()).filter(Boolean));
|
|
2619
|
+
enriched = enriched.filter((t2) => wanted.has(t2.status.toLowerCase()));
|
|
2620
|
+
}
|
|
2845
2621
|
return {
|
|
2846
2622
|
content: JSON.stringify({ todos: enriched, count: enriched.length }),
|
|
2847
2623
|
metadata: {
|
|
@@ -2855,7 +2631,7 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2855
2631
|
}
|
|
2856
2632
|
};
|
|
2857
2633
|
}
|
|
2858
|
-
if (action !== "status" && action !== "stop") {
|
|
2634
|
+
if (action !== "status" && action !== "stop" && action !== "wait") {
|
|
2859
2635
|
throw new Error(`controlAgentRun: \u672A\u77E5 action "${action}"\u3002`);
|
|
2860
2636
|
}
|
|
2861
2637
|
if (!args.runId) throw new Error(`controlAgentRun(action:"${action}"): \u7F3A\u5C11 runId\u3002`);
|
|
@@ -2870,70 +2646,43 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2870
2646
|
if (action === "status") {
|
|
2871
2647
|
const reconciled = checkStaleRun(record.runId, deps) ?? record;
|
|
2872
2648
|
const logTail = tailLines > 0 ? tailFile(record.logPath, tailLines, resolveFs(deps)) : void 0;
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2649
|
+
return buildRunStatusPayload(reconciled, deps, { logTail });
|
|
2650
|
+
}
|
|
2651
|
+
if (action === "wait") {
|
|
2652
|
+
const timeoutMs = typeof args.timeoutMs === "number" && args.timeoutMs > 0 ? args.timeoutMs : DEFAULT_WAIT_TIMEOUT_MS;
|
|
2653
|
+
const startMs = resolveNowMs(deps);
|
|
2654
|
+
const deadline = startMs + timeoutMs;
|
|
2655
|
+
const sleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2656
|
+
let reconciled = record;
|
|
2657
|
+
for (; ; ) {
|
|
2658
|
+
reconciled = checkStaleRun(record.runId, deps) ?? record;
|
|
2659
|
+
if (isAgentRunTerminalStatus(reconciled.status)) break;
|
|
2660
|
+
const nowMs = resolveNowMs(deps);
|
|
2661
|
+
const waitedMs = nowMs - startMs;
|
|
2662
|
+
if (nowMs >= deadline) {
|
|
2663
|
+
return {
|
|
2664
|
+
content: JSON.stringify({
|
|
2665
|
+
runId: reconciled.runId,
|
|
2666
|
+
found: true,
|
|
2667
|
+
status: "timeout",
|
|
2668
|
+
runStatus: reconciled.status,
|
|
2669
|
+
pid: reconciled.pid ?? null,
|
|
2670
|
+
agentKey: reconciled.agentKey,
|
|
2671
|
+
...reconciled.agentName ? { agentName: reconciled.agentName } : {},
|
|
2672
|
+
startedAt: reconciled.startedAt,
|
|
2673
|
+
waitedMs,
|
|
2674
|
+
timeoutMs,
|
|
2675
|
+
...buildProgressField(reconciled, nowMs)
|
|
2676
|
+
}),
|
|
2677
|
+
metadata: {
|
|
2678
|
+
displayData: `\u23F3 wait \u8D85\u65F6\uFF08${Math.round(waitedMs / 1e3)}s\uFF09\uFF0Crun \u4ECD\u5728\u8FD0\u884C\uFF1A\u53EF\u7A0D\u540E\u518D wait\uFF0C\u6216\u6539\u7528 status/stop`
|
|
2679
|
+
}
|
|
2680
|
+
};
|
|
2893
2681
|
}
|
|
2682
|
+
await sleep(WAIT_POLL_INTERVAL_MS);
|
|
2894
2683
|
}
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
runId: reconciled.runId,
|
|
2898
|
-
found: true,
|
|
2899
|
-
status: reconciled.status,
|
|
2900
|
-
pid: reconciled.pid ?? null,
|
|
2901
|
-
agentKey: reconciled.agentKey,
|
|
2902
|
-
...reconciled.agentName ? { agentName: reconciled.agentName } : {},
|
|
2903
|
-
startedAt: reconciled.startedAt,
|
|
2904
|
-
endedAt: reconciled.endedAt ?? null,
|
|
2905
|
-
exitCode: reconciled.exitCode ?? null,
|
|
2906
|
-
// Expose dialogId so the caller can read the agent's actual output
|
|
2907
|
-
// via `nolo dialog read <dialogId>`. The dialog is the authoritative
|
|
2908
|
-
// result store; the run log is the child process stdout/stderr,
|
|
2909
|
-
// whose contents vary by provider (some stream tokens to stdout,
|
|
2910
|
-
// some only emit startup + stderr). Because status does not carry
|
|
2911
|
-
// logTail by default, a "done" run with an empty logTail is
|
|
2912
|
-
// indistinguishable from a hung run without this field. Surfacing
|
|
2913
|
-
// dialogId gives the caller a reliable way to fetch the result.
|
|
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)),
|
|
2922
|
-
...logTail !== void 0 ? { logTail } : {},
|
|
2923
|
-
...logLines ? { logLines } : {}
|
|
2924
|
-
}),
|
|
2925
|
-
metadata: {
|
|
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
|
-
})
|
|
2935
|
-
}
|
|
2936
|
-
};
|
|
2684
|
+
ackRunRecord(reconciled.runId, deps);
|
|
2685
|
+
return buildRunStatusPayload(reconciled, deps);
|
|
2937
2686
|
}
|
|
2938
2687
|
if (typeof record.pid === "number") {
|
|
2939
2688
|
try {
|
|
@@ -3168,6 +2917,20 @@ function buildLocalToolExecutors(args) {
|
|
|
3168
2917
|
controlAgentRun: createCliControlAgentRunExecutor({
|
|
3169
2918
|
env: args.env
|
|
3170
2919
|
}),
|
|
2920
|
+
setTodoList: async (call) => {
|
|
2921
|
+
const parsedArgs = typeof call?.arguments === "string" ? (() => {
|
|
2922
|
+
try {
|
|
2923
|
+
return JSON.parse(call.arguments);
|
|
2924
|
+
} catch {
|
|
2925
|
+
return {};
|
|
2926
|
+
}
|
|
2927
|
+
})() : call?.arguments || {};
|
|
2928
|
+
const res = await setTodoListFunc(parsedArgs);
|
|
2929
|
+
return {
|
|
2930
|
+
content: JSON.stringify(res.rawData),
|
|
2931
|
+
metadata: { displayData: res.displayData }
|
|
2932
|
+
};
|
|
2933
|
+
},
|
|
3171
2934
|
...args.pastedTextStore ? { readPastedText: createReadPastedTextExecutor(args.pastedTextStore) } : {},
|
|
3172
2935
|
...args.localToolExecutors ?? {}
|
|
3173
2936
|
};
|
|
@@ -3178,6 +2941,9 @@ import { randomUUID } from "node:crypto";
|
|
|
3178
2941
|
|
|
3179
2942
|
// packages/agent-runtime/antigravityWireModel.ts
|
|
3180
2943
|
var WIRE_PROFILES = {
|
|
2944
|
+
"gemini-3.7-flash-low": { maxOutputTokens: 65536 },
|
|
2945
|
+
"gemini-3.7-flash-medium": { maxOutputTokens: 65536 },
|
|
2946
|
+
"gemini-3.7-flash-high": { maxOutputTokens: 65536 },
|
|
3181
2947
|
"gemini-3.6-flash-low": { maxOutputTokens: 65536 },
|
|
3182
2948
|
"gemini-3.6-flash-medium": { maxOutputTokens: 65536 },
|
|
3183
2949
|
"gemini-3.6-flash-high": { maxOutputTokens: 65536 },
|
|
@@ -3199,6 +2965,10 @@ function resolveAntigravityWireModel(logicalModelId) {
|
|
|
3199
2965
|
const wireModelId = "gemini-3.5-flash-low";
|
|
3200
2966
|
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
3201
2967
|
}
|
|
2968
|
+
if (lower === "gemini-3.7-flash") {
|
|
2969
|
+
const wireModelId = "gemini-3.7-flash-low";
|
|
2970
|
+
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
2971
|
+
}
|
|
3202
2972
|
if (lower === "gemini-3.6-flash") {
|
|
3203
2973
|
const wireModelId = "gemini-3.6-flash-low";
|
|
3204
2974
|
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
@@ -3297,12 +3067,15 @@ function convertOpenAiMessagesToGemini(messages, options) {
|
|
|
3297
3067
|
}
|
|
3298
3068
|
if (role === "assistant") {
|
|
3299
3069
|
flushPendingFunctionCalls();
|
|
3300
|
-
const parts = [];
|
|
3301
3070
|
const text = messageText(
|
|
3302
3071
|
content
|
|
3303
3072
|
);
|
|
3304
|
-
if (text) parts.push({ text });
|
|
3305
3073
|
const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
|
|
3074
|
+
if (text) pushOrMergeContent("model", [{ text }]);
|
|
3075
|
+
if (toolCalls.length > 0 && contents.length > 0 && contents[contents.length - 1]?.role !== "user") {
|
|
3076
|
+
contents.push({ role: "user", parts: [{ text: "" }] });
|
|
3077
|
+
}
|
|
3078
|
+
const parts = [];
|
|
3306
3079
|
for (const call of toolCalls) {
|
|
3307
3080
|
const name = call?.function?.name?.trim();
|
|
3308
3081
|
if (!name) continue;
|
|
@@ -3330,15 +3103,11 @@ function convertOpenAiMessagesToGemini(messages, options) {
|
|
|
3330
3103
|
if (role === "tool") {
|
|
3331
3104
|
const toolCallId = "tool_call_id" in raw && typeof raw.tool_call_id === "string" ? raw.tool_call_id : "";
|
|
3332
3105
|
const rawName = "name" in raw && typeof raw.name === "string" ? raw.name.trim() : "";
|
|
3333
|
-
const name = toolNamesById.get(toolCallId) || rawName || pendingFunctionCalls[0]?.name || "tool";
|
|
3334
3106
|
const pendingIndex = pendingFunctionCalls.findIndex(
|
|
3335
|
-
(p) => toolCallId ? p.id === toolCallId : p.name ===
|
|
3107
|
+
(p) => toolCallId ? p.id === toolCallId : rawName ? p.name === rawName : true
|
|
3336
3108
|
);
|
|
3337
|
-
if (pendingIndex
|
|
3338
|
-
|
|
3339
|
-
} else if (pendingFunctionCalls.length > 0) {
|
|
3340
|
-
pendingFunctionCalls.shift();
|
|
3341
|
-
}
|
|
3109
|
+
if (pendingIndex === -1) continue;
|
|
3110
|
+
const [{ name, id }] = pendingFunctionCalls.splice(pendingIndex, 1);
|
|
3342
3111
|
const output = messageText(content) || "{}";
|
|
3343
3112
|
pushOrMergeContent("user", [
|
|
3344
3113
|
{
|
|
@@ -3349,7 +3118,7 @@ function convertOpenAiMessagesToGemini(messages, options) {
|
|
|
3349
3118
|
// Gemini contents 转成 Claude messages 时需要 functionResponse →
|
|
3350
3119
|
// tool_result 的 tool_use_id;缺 id 时网关报
|
|
3351
3120
|
// "tool_result.tool_use_id: Field required"(HTTP 400)。
|
|
3352
|
-
...
|
|
3121
|
+
...id ? { id } : {}
|
|
3353
3122
|
}
|
|
3354
3123
|
}
|
|
3355
3124
|
]);
|
|
@@ -3798,6 +3567,9 @@ function buildAnthropicMessagesBody(args) {
|
|
|
3798
3567
|
input_schema: fn?.parameters && typeof fn.parameters === "object" ? fn.parameters : { type: "object", properties: {} }
|
|
3799
3568
|
}];
|
|
3800
3569
|
}) : [];
|
|
3570
|
+
if (tools.length > 0 && !tools.some((tool) => isCacheControl(tool.cache_control))) {
|
|
3571
|
+
tools[tools.length - 1].cache_control = { type: "ephemeral" };
|
|
3572
|
+
}
|
|
3801
3573
|
const model = stringValue(args.openAiBody.model) ?? args.agentConfig.model ?? "claude-sonnet-5";
|
|
3802
3574
|
const maxTokensRaw = args.openAiBody.max_completion_tokens ?? args.openAiBody.max_tokens ?? args.agentConfig.max_tokens;
|
|
3803
3575
|
const maxTokens = typeof maxTokensRaw === "number" && Number.isFinite(maxTokensRaw) ? Math.max(1, Math.floor(maxTokensRaw)) : 8192;
|
|
@@ -3905,7 +3677,7 @@ async function fetchAnthropicMessagesCompletion(args) {
|
|
|
3905
3677
|
const payload = await response.json().catch(async () => ({
|
|
3906
3678
|
error: { message: await response.text().catch(() => response.statusText) }
|
|
3907
3679
|
}));
|
|
3908
|
-
if (!response.ok) return { status: response.status, body: payload };
|
|
3680
|
+
if (!response.ok) return { status: response.status, body: payload, headers: response.headers };
|
|
3909
3681
|
return { status: 200, body: mapAnthropicMessageToOpenAi(payload) };
|
|
3910
3682
|
}
|
|
3911
3683
|
function isAnthropicOAuthAgent(agent) {
|
|
@@ -10076,13 +9848,25 @@ function stablePromptCacheKey(parts) {
|
|
|
10076
9848
|
}
|
|
10077
9849
|
return `nolo-codex-${hash.toString(16).padStart(8, "0")}`;
|
|
10078
9850
|
}
|
|
9851
|
+
function convertMessagesToCodexInput(messages) {
|
|
9852
|
+
return convertMessagesToResponsesInput(messages).map((item) => {
|
|
9853
|
+
if (item.type !== "reasoning") return item;
|
|
9854
|
+
return {
|
|
9855
|
+
type: "reasoning",
|
|
9856
|
+
summary: item.content.map((part) => ({
|
|
9857
|
+
type: "summary_text",
|
|
9858
|
+
text: part.text
|
|
9859
|
+
}))
|
|
9860
|
+
};
|
|
9861
|
+
});
|
|
9862
|
+
}
|
|
10079
9863
|
function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
|
|
10080
9864
|
const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
|
|
10081
9865
|
const nonSystem = rawMessages.filter((m) => {
|
|
10082
9866
|
const role = m && typeof m === "object" ? String(m.role) : "";
|
|
10083
9867
|
return role !== "system" && role !== "developer";
|
|
10084
9868
|
});
|
|
10085
|
-
const input =
|
|
9869
|
+
const input = convertMessagesToCodexInput(nonSystem);
|
|
10086
9870
|
const instructions = collectInstructions(rawMessages, args.agentConfig.prompt);
|
|
10087
9871
|
const stableInstructions = collectStableInstructions(rawMessages, args.agentConfig.prompt);
|
|
10088
9872
|
const model = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gpt-5.5";
|
|
@@ -10107,12 +9891,47 @@ function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
|
|
|
10107
9891
|
}
|
|
10108
9892
|
return body;
|
|
10109
9893
|
}
|
|
9894
|
+
function codexStreamFailureStatus(failure) {
|
|
9895
|
+
const marker = `${failure.code ?? ""} ${failure.type ?? ""}`.toLowerCase();
|
|
9896
|
+
if (marker.includes("overload") || marker.includes("service_unavailable")) return 503;
|
|
9897
|
+
if (marker.includes("rate_limit") || marker.includes("usage_limit")) return 429;
|
|
9898
|
+
return 502;
|
|
9899
|
+
}
|
|
9900
|
+
var RETRYABLE_CODEX_STREAM_STATUSES = /* @__PURE__ */ new Set([503]);
|
|
9901
|
+
var CODEX_STREAM_MAX_ATTEMPTS = 3;
|
|
9902
|
+
var CODEX_STREAM_RETRY_BASE_DELAY_MS = 500;
|
|
9903
|
+
function toStreamFailure(raw) {
|
|
9904
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
9905
|
+
const err = raw;
|
|
9906
|
+
const reason = typeof err.reason === "string" ? err.reason : void 0;
|
|
9907
|
+
const message = typeof err.message === "string" && err.message ? err.message : reason ? `Codex upstream ended incomplete: ${reason}.` : "";
|
|
9908
|
+
if (!message) return void 0;
|
|
9909
|
+
const code = typeof err.code === "string" ? err.code : reason;
|
|
9910
|
+
return {
|
|
9911
|
+
...code ? { code } : {},
|
|
9912
|
+
...typeof err.type === "string" ? { type: err.type } : {},
|
|
9913
|
+
message
|
|
9914
|
+
};
|
|
9915
|
+
}
|
|
10110
9916
|
function aggregateResponsesStream(events) {
|
|
10111
9917
|
let text = "";
|
|
10112
9918
|
const toolCalls = [];
|
|
10113
9919
|
let usage;
|
|
9920
|
+
let failure;
|
|
10114
9921
|
for (const ev of events) {
|
|
10115
9922
|
const type = String(ev.type ?? "");
|
|
9923
|
+
if (type === "error") {
|
|
9924
|
+
failure = failure ?? toStreamFailure(ev.error);
|
|
9925
|
+
continue;
|
|
9926
|
+
}
|
|
9927
|
+
if (type === "response.failed" || type === "response.incomplete") {
|
|
9928
|
+
const response = ev.response;
|
|
9929
|
+
failure = failure ?? toStreamFailure(response?.error) ?? toStreamFailure(response?.incomplete_details) ?? {
|
|
9930
|
+
code: type === "response.incomplete" ? "response_incomplete" : "response_failed",
|
|
9931
|
+
message: `Codex upstream ended with ${type}.`
|
|
9932
|
+
};
|
|
9933
|
+
continue;
|
|
9934
|
+
}
|
|
10116
9935
|
if (type === "response.output_text.delta" && typeof ev.delta === "string") {
|
|
10117
9936
|
text += ev.delta;
|
|
10118
9937
|
continue;
|
|
@@ -10149,7 +9968,7 @@ function aggregateResponsesStream(events) {
|
|
|
10149
9968
|
}
|
|
10150
9969
|
}
|
|
10151
9970
|
}
|
|
10152
|
-
return { text, toolCalls, usage };
|
|
9971
|
+
return { text, toolCalls, usage, failure };
|
|
10153
9972
|
}
|
|
10154
9973
|
async function readSseEvents(response) {
|
|
10155
9974
|
return readSseDataValues(response, (line) => {
|
|
@@ -10157,19 +9976,9 @@ async function readSseEvents(response) {
|
|
|
10157
9976
|
return ev && !Array.isArray(ev) ? ev : null;
|
|
10158
9977
|
});
|
|
10159
9978
|
}
|
|
10160
|
-
|
|
9979
|
+
var defaultSleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
9980
|
+
async function callCodexResponsesOnce(args, accountId) {
|
|
10161
9981
|
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
9982
|
const identity = createCodexRequestIdentity();
|
|
10174
9983
|
const body = buildCodexRequestBody(args, identity);
|
|
10175
9984
|
const headers = buildCodexCompatibilityHeaders(identity, accountId);
|
|
@@ -10188,7 +9997,19 @@ async function fetchCodexResponsesCompletion(args) {
|
|
|
10188
9997
|
};
|
|
10189
9998
|
}
|
|
10190
9999
|
const events = await readSseEvents(response);
|
|
10191
|
-
const { text, toolCalls, usage } = aggregateResponsesStream(events);
|
|
10000
|
+
const { text, toolCalls, usage, failure } = aggregateResponsesStream(events);
|
|
10001
|
+
if (failure) {
|
|
10002
|
+
return {
|
|
10003
|
+
status: codexStreamFailureStatus(failure),
|
|
10004
|
+
body: {
|
|
10005
|
+
error: {
|
|
10006
|
+
message: failure.message,
|
|
10007
|
+
...failure.code ? { code: failure.code } : {},
|
|
10008
|
+
...failure.type ? { type: failure.type } : {}
|
|
10009
|
+
}
|
|
10010
|
+
}
|
|
10011
|
+
};
|
|
10012
|
+
}
|
|
10192
10013
|
const message = {
|
|
10193
10014
|
role: "assistant",
|
|
10194
10015
|
content: text || null
|
|
@@ -10208,6 +10029,30 @@ async function fetchCodexResponsesCompletion(args) {
|
|
|
10208
10029
|
}
|
|
10209
10030
|
};
|
|
10210
10031
|
}
|
|
10032
|
+
async function fetchCodexResponsesCompletion(args) {
|
|
10033
|
+
const accountId = args.accountId?.trim() || decodeCodexAccountId(args.accessToken);
|
|
10034
|
+
if (!accountId) {
|
|
10035
|
+
return {
|
|
10036
|
+
status: 401,
|
|
10037
|
+
body: {
|
|
10038
|
+
error: {
|
|
10039
|
+
message: "ChatGPT Codex credential is missing chatgpt_account_id. Re-run `nolo auth chatgpt`."
|
|
10040
|
+
}
|
|
10041
|
+
}
|
|
10042
|
+
};
|
|
10043
|
+
}
|
|
10044
|
+
const sleep = args.sleep ?? defaultSleep2;
|
|
10045
|
+
const requestedMaxAttempts = Number(args.maxAttempts);
|
|
10046
|
+
const maxAttempts = Number.isFinite(requestedMaxAttempts) ? Math.min(10, Math.max(1, Math.floor(requestedMaxAttempts))) : CODEX_STREAM_MAX_ATTEMPTS;
|
|
10047
|
+
let result = await callCodexResponsesOnce(args, accountId);
|
|
10048
|
+
for (let attempt = 1; attempt < maxAttempts; attempt += 1) {
|
|
10049
|
+
if (!RETRYABLE_CODEX_STREAM_STATUSES.has(result.status)) break;
|
|
10050
|
+
if (args.signal?.aborted) break;
|
|
10051
|
+
await sleep(CODEX_STREAM_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
|
|
10052
|
+
result = await callCodexResponsesOnce(args, accountId);
|
|
10053
|
+
}
|
|
10054
|
+
return result;
|
|
10055
|
+
}
|
|
10211
10056
|
function isCodexOAuthAgent(agentConfig) {
|
|
10212
10057
|
if (!agentConfig) return false;
|
|
10213
10058
|
const apiKeyRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
|
|
@@ -10302,313 +10147,15 @@ function createOAuthApiKeyRefResolver(options = {}) {
|
|
|
10302
10147
|
};
|
|
10303
10148
|
}
|
|
10304
10149
|
|
|
10305
|
-
// packages/cli/client/
|
|
10306
|
-
function
|
|
10307
|
-
const
|
|
10308
|
-
|
|
10309
|
-
env.BASE_URL,
|
|
10310
|
-
...NOLO_CLUSTER_SERVERS
|
|
10311
|
-
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
10312
|
-
return [...new Set(values.map(normalizeServerOrigin))];
|
|
10150
|
+
// packages/cli/client/cliWorkspaceToolVariants.ts
|
|
10151
|
+
function shouldUseDeclaredOnlyLocalWorkspaceTools(env) {
|
|
10152
|
+
const value = env.NOLO_LOCAL_WORKSPACE_TOOLSET || env.NOLO_LOCAL_TOOLSET_MODE || "";
|
|
10153
|
+
return value === "declared-only" || value === "declared";
|
|
10313
10154
|
}
|
|
10314
|
-
function
|
|
10315
|
-
return
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
return createHybridRecordStore({
|
|
10319
|
-
db: deps.db,
|
|
10320
|
-
defaultServer: normalizeServerOrigin(
|
|
10321
|
-
deps.env.NOLO_SERVER || deps.env.BASE_URL || DEFAULT_NOLO_SERVER_URL
|
|
10322
|
-
),
|
|
10323
|
-
fallbackServers: resolveFallbackServers(deps.env),
|
|
10324
|
-
authToken: resolveAuthToken(deps.env),
|
|
10325
|
-
fetchImpl: deps.fetchImpl
|
|
10326
|
-
});
|
|
10327
|
-
}
|
|
10328
|
-
|
|
10329
|
-
// packages/agent-runtime/dialogTitleLlm.ts
|
|
10330
|
-
async function generateLocalDialogTitle(input) {
|
|
10331
|
-
const { env, messages, fallbackTitle } = input;
|
|
10332
|
-
const timeoutMs = input.timeoutMs ?? 15e3;
|
|
10333
|
-
const visibleMessages = messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-12).map((m) => ({
|
|
10334
|
-
role: m.role,
|
|
10335
|
-
content: typeof m.content === "string" ? m.content : extractText(m.content)
|
|
10336
|
-
}));
|
|
10337
|
-
if (visibleMessages.length === 0) {
|
|
10338
|
-
return { title: fallbackTitle, source: "fallback" };
|
|
10339
|
-
}
|
|
10340
|
-
try {
|
|
10341
|
-
const providerConfig = await input.resolveProviderConfig({
|
|
10342
|
-
agentConfig: { ...BUILTIN_TITLE_LLM_CONFIG, key: BUILTIN_TITLE_LLM_CONFIG.id },
|
|
10343
|
-
env
|
|
10344
|
-
});
|
|
10345
|
-
if (!providerConfig?.authToken) {
|
|
10346
|
-
return { title: fallbackTitle, source: "fallback" };
|
|
10347
|
-
}
|
|
10348
|
-
const request = input.buildRequest({
|
|
10349
|
-
providerConfig,
|
|
10350
|
-
messages: [
|
|
10351
|
-
{
|
|
10352
|
-
role: "user",
|
|
10353
|
-
content: JSON.stringify(
|
|
10354
|
-
visibleMessages.map((m) => ({ role: m.role, content: m.content }))
|
|
10355
|
-
)
|
|
10356
|
-
}
|
|
10357
|
-
],
|
|
10358
|
-
stream: false
|
|
10359
|
-
});
|
|
10360
|
-
const res = await input.fetchImpl(request.url, {
|
|
10361
|
-
...request.init,
|
|
10362
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
10363
|
-
});
|
|
10364
|
-
if (!res.ok) {
|
|
10365
|
-
return { title: fallbackTitle, source: "fallback" };
|
|
10366
|
-
}
|
|
10367
|
-
const raw = await res.text().catch(() => "");
|
|
10368
|
-
const data = safeParseJson(raw);
|
|
10369
|
-
if (!data) {
|
|
10370
|
-
return { title: fallbackTitle, source: "fallback" };
|
|
10371
|
-
}
|
|
10372
|
-
const parsed = input.parseResponse({ providerConfig, data });
|
|
10373
|
-
const generated = normalizeDialogTitle(parsed.content);
|
|
10374
|
-
if (!generated) {
|
|
10375
|
-
return { title: fallbackTitle, source: "fallback" };
|
|
10376
|
-
}
|
|
10377
|
-
return { title: generated, source: "llm" };
|
|
10378
|
-
} catch {
|
|
10379
|
-
return { title: fallbackTitle, source: "fallback" };
|
|
10380
|
-
}
|
|
10381
|
-
}
|
|
10382
|
-
function extractText(content) {
|
|
10383
|
-
if (typeof content === "string") return content;
|
|
10384
|
-
if (Array.isArray(content)) {
|
|
10385
|
-
return content.filter((part) => part?.type === "text").map((part) => part.text ?? "").join(" ");
|
|
10386
|
-
}
|
|
10387
|
-
return "";
|
|
10388
|
-
}
|
|
10389
|
-
function safeParseJson(raw) {
|
|
10390
|
-
try {
|
|
10391
|
-
return JSON.parse(raw);
|
|
10392
|
-
} catch {
|
|
10393
|
-
return null;
|
|
10394
|
-
}
|
|
10395
|
-
}
|
|
10396
|
-
|
|
10397
|
-
// packages/cli/client/localRuntimeDialog.ts
|
|
10398
|
-
async function resolveStore(deps) {
|
|
10399
|
-
if (deps.store) return deps.store;
|
|
10400
|
-
return createCliHybridRecordStore({
|
|
10401
|
-
db: deps.db ?? await defaultLocalRuntimeDb(),
|
|
10402
|
-
env: deps.env,
|
|
10403
|
-
fetchImpl: deps.fetchImpl
|
|
10404
|
-
});
|
|
10405
|
-
}
|
|
10406
|
-
async function getOrCreateSharedStore(deps) {
|
|
10407
|
-
if (deps.store) return deps.store;
|
|
10408
|
-
const cacheKey = normalizeRuntimeCacheCwd(deps.cwd);
|
|
10409
|
-
let storePromise = hybridStoreCache.get(cacheKey);
|
|
10410
|
-
if (!storePromise) {
|
|
10411
|
-
storePromise = resolveStore(deps);
|
|
10412
|
-
hybridStoreCache.set(cacheKey, storePromise);
|
|
10413
|
-
}
|
|
10414
|
-
return storePromise;
|
|
10415
|
-
}
|
|
10416
|
-
function createLocalDialogTitleGenerator(deps, ctx) {
|
|
10417
|
-
return async (input) => {
|
|
10418
|
-
if (!canUsePlatformChatProvider(deps.env)) {
|
|
10419
|
-
return null;
|
|
10420
|
-
}
|
|
10421
|
-
const result = await generateLocalDialogTitle({
|
|
10422
|
-
messages: input.messages,
|
|
10423
|
-
env: deps.env,
|
|
10424
|
-
fetchImpl: async (url, init) => fetchWithTransientRetry(
|
|
10425
|
-
deps.fetchImpl ?? fetch,
|
|
10426
|
-
url,
|
|
10427
|
-
init,
|
|
10428
|
-
{
|
|
10429
|
-
sleep: deps.sleep,
|
|
10430
|
-
loopbackRequest: ctx.loopbackRequest
|
|
10431
|
-
}
|
|
10432
|
-
),
|
|
10433
|
-
resolveProviderConfig: async (args) => resolvePlatformChatProviderConfig({
|
|
10434
|
-
agentConfig: args.agentConfig,
|
|
10435
|
-
env: args.env,
|
|
10436
|
-
apiKeyRefResolver: ctx.apiKeyRefResolver,
|
|
10437
|
-
credentialBroker: ctx.credentialBroker
|
|
10438
|
-
}),
|
|
10439
|
-
buildRequest: (args) => buildPlatformChatCompletionRequest({
|
|
10440
|
-
providerConfig: args.providerConfig,
|
|
10441
|
-
messages: args.messages,
|
|
10442
|
-
stream: false
|
|
10443
|
-
}),
|
|
10444
|
-
parseResponse: (args) => parsePlatformChatCompletionResponse({
|
|
10445
|
-
providerConfig: args.providerConfig,
|
|
10446
|
-
data: args.data,
|
|
10447
|
-
trace: []
|
|
10448
|
-
}),
|
|
10449
|
-
fallbackTitle: input.fallbackTitle,
|
|
10450
|
-
timeoutMs: 15e3
|
|
10451
|
-
});
|
|
10452
|
-
return result.source === "llm" ? result.title : null;
|
|
10453
|
-
};
|
|
10454
|
-
}
|
|
10455
|
-
async function writeLocalTokenRecord(args) {
|
|
10456
|
-
const rawUsage = args.input.result.usage;
|
|
10457
|
-
if (!rawUsage || typeof rawUsage !== "object" || Object.keys(rawUsage).length === 0) {
|
|
10458
|
-
return;
|
|
10459
|
-
}
|
|
10460
|
-
const timestamp = args.now();
|
|
10461
|
-
const prepared = prepareTokenUsageData({
|
|
10462
|
-
rawUsage,
|
|
10463
|
-
agentConfig: {
|
|
10464
|
-
model: args.input.result.model || "unknown",
|
|
10465
|
-
provider: args.input.result.provider,
|
|
10466
|
-
apiSource: "cli"
|
|
10467
|
-
},
|
|
10468
|
-
userId: args.userId,
|
|
10469
|
-
agentId: args.input.agentKey,
|
|
10470
|
-
dialogId: args.dialogId,
|
|
10471
|
-
timestamp,
|
|
10472
|
-
entry_path: "cli-local"
|
|
10473
|
-
});
|
|
10474
|
-
const recordKey = createTokenKey.record(args.userId, timestamp);
|
|
10475
|
-
const tokenRecord = {
|
|
10476
|
-
id: args.createId(),
|
|
10477
|
-
type: "token",
|
|
10478
|
-
...prepared.tokenData
|
|
10479
|
-
};
|
|
10480
|
-
await args.store.write(recordKey, tokenRecord);
|
|
10481
|
-
}
|
|
10482
|
-
async function writeDialog(args) {
|
|
10483
|
-
let existingDialog = null;
|
|
10484
|
-
if (args.input.continueDialogId) {
|
|
10485
|
-
const dialogKey = `dialog-${args.userId}-${args.input.continueDialogId}`;
|
|
10486
|
-
existingDialog = await args.store.read(dialogKey);
|
|
10487
|
-
}
|
|
10488
|
-
const authToken = resolveRuntimeAuthToken(args.env);
|
|
10489
|
-
const isLoggedIn = Boolean(
|
|
10490
|
-
authToken && (parseUserIdFromAuthToken(authToken) || args.env.NOLO_MACHINE_API_KEY?.trim())
|
|
10491
|
-
);
|
|
10492
|
-
const hasExistingTitle = typeof existingDialog?.title === "string" && existingDialog.title.trim();
|
|
10493
|
-
let titleOverride;
|
|
10494
|
-
if (isLoggedIn && !hasExistingTitle && args.titleGenerator) {
|
|
10495
|
-
const fallbackTitle = extractLastUserText(args.input.messages).trim().slice(0, 80) || "Local agent run";
|
|
10496
|
-
try {
|
|
10497
|
-
const generated = await args.titleGenerator({
|
|
10498
|
-
messages: args.input.messages,
|
|
10499
|
-
fallbackTitle
|
|
10500
|
-
});
|
|
10501
|
-
if (generated) {
|
|
10502
|
-
titleOverride = generated;
|
|
10503
|
-
}
|
|
10504
|
-
} catch {
|
|
10505
|
-
}
|
|
10506
|
-
}
|
|
10507
|
-
const plan = buildLocalDialogWritePlan({
|
|
10508
|
-
input: args.input,
|
|
10509
|
-
userId: args.userId,
|
|
10510
|
-
now: args.now(),
|
|
10511
|
-
createId: args.createId,
|
|
10512
|
-
existingDialog,
|
|
10513
|
-
cwd: args.cwd,
|
|
10514
|
-
...titleOverride ? { titleOverride } : {}
|
|
10515
|
-
});
|
|
10516
|
-
await args.store.batch(plan.ops);
|
|
10517
|
-
try {
|
|
10518
|
-
await writeLocalTokenRecord({
|
|
10519
|
-
store: args.store,
|
|
10520
|
-
input: args.input,
|
|
10521
|
-
userId: args.userId,
|
|
10522
|
-
dialogId: plan.dialogId,
|
|
10523
|
-
now: args.now,
|
|
10524
|
-
createId: args.createId,
|
|
10525
|
-
output: args.output
|
|
10526
|
-
});
|
|
10527
|
-
} catch (error) {
|
|
10528
|
-
args.output?.write(
|
|
10529
|
-
`[nolo] Token usage record write failed (non-fatal): ${toErrorMessage(error)}
|
|
10530
|
-
`
|
|
10531
|
-
);
|
|
10532
|
-
}
|
|
10533
|
-
const hasSubjectRefs = localTurnHasSubjectRefs(args.input);
|
|
10534
|
-
const isLocalUser = args.userId === "local";
|
|
10535
|
-
if (!isLocalUser) {
|
|
10536
|
-
try {
|
|
10537
|
-
const syncResult = await syncLocalDialogEvidenceToRemote({
|
|
10538
|
-
env: args.env,
|
|
10539
|
-
fetchImpl: args.fetchImpl,
|
|
10540
|
-
input: args.input,
|
|
10541
|
-
ops: plan.ops,
|
|
10542
|
-
output: args.output,
|
|
10543
|
-
userId: args.userId
|
|
10544
|
-
});
|
|
10545
|
-
if (!syncResult.attempted) {
|
|
10546
|
-
if (hasSubjectRefs) {
|
|
10547
|
-
args.output?.write(
|
|
10548
|
-
"[nolo] Local dialog evidence is local-only; set NOLO_SERVER and AUTH_TOKEN to make subjectRefs remotely queryable.\n"
|
|
10549
|
-
);
|
|
10550
|
-
}
|
|
10551
|
-
}
|
|
10552
|
-
} catch (error) {
|
|
10553
|
-
if (hasSubjectRefs) {
|
|
10554
|
-
throw error;
|
|
10555
|
-
}
|
|
10556
|
-
args.output?.write(
|
|
10557
|
-
`[nolo] Remote dialog evidence sync failed; local dialog only: ${toErrorMessage(
|
|
10558
|
-
error
|
|
10559
|
-
)}
|
|
10560
|
-
`
|
|
10561
|
-
);
|
|
10562
|
-
}
|
|
10563
|
-
}
|
|
10564
|
-
return { dialogId: plan.dialogId, title: plan.title };
|
|
10565
|
-
}
|
|
10566
|
-
function resolveCliDialogRecordKey(userId, dialogId) {
|
|
10567
|
-
if (dialogId.startsWith("dialog-") && !dialogId.includes("-msg-")) {
|
|
10568
|
-
return dialogId;
|
|
10569
|
-
}
|
|
10570
|
-
return `dialog-${userId}-${dialogId}`;
|
|
10571
|
-
}
|
|
10572
|
-
async function loadCliDialogSummary(args) {
|
|
10573
|
-
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10574
|
-
const record = await args.store.read(dialogKey);
|
|
10575
|
-
if (!record || typeof record !== "object") return null;
|
|
10576
|
-
const summary = typeof record.summary === "string" ? record.summary.trim() : "";
|
|
10577
|
-
if (!summary) return null;
|
|
10578
|
-
const summarizedBeforeId = record.summarizedBeforeId;
|
|
10579
|
-
return {
|
|
10580
|
-
summary,
|
|
10581
|
-
...typeof summarizedBeforeId === "string" && summarizedBeforeId ? { summarizedBeforeId } : {}
|
|
10582
|
-
};
|
|
10583
|
-
}
|
|
10584
|
-
async function saveCliDialogSummary(args) {
|
|
10585
|
-
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10586
|
-
const existing = await args.store.read(dialogKey) ?? {};
|
|
10587
|
-
const bareId = typeof existing.id === "string" && existing.id ? existing.id : args.dialogId.startsWith("dialog-") ? args.dialogId.slice(args.dialogId.lastIndexOf("-") + 1) : args.dialogId;
|
|
10588
|
-
const compressionCount = typeof existing.compressionCount === "number" ? existing.compressionCount + 1 : 1;
|
|
10589
|
-
await args.store.write(dialogKey, {
|
|
10590
|
-
...existing,
|
|
10591
|
-
id: bareId,
|
|
10592
|
-
dbKey: dialogKey,
|
|
10593
|
-
type: "dialog",
|
|
10594
|
-
userId: args.userId,
|
|
10595
|
-
summary: args.summary,
|
|
10596
|
-
...args.summarizedBeforeId !== void 0 ? { summarizedBeforeId: args.summarizedBeforeId } : {},
|
|
10597
|
-
compressionCount,
|
|
10598
|
-
summaryPending: false,
|
|
10599
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10600
|
-
});
|
|
10601
|
-
}
|
|
10602
|
-
|
|
10603
|
-
// packages/cli/client/cliWorkspaceToolVariants.ts
|
|
10604
|
-
function shouldUseDeclaredOnlyLocalWorkspaceTools(env) {
|
|
10605
|
-
const value = env.NOLO_LOCAL_WORKSPACE_TOOLSET || env.NOLO_LOCAL_TOOLSET_MODE || "";
|
|
10606
|
-
return value === "declared-only" || value === "declared";
|
|
10607
|
-
}
|
|
10608
|
-
function resolveGlobFilesDescriptionVariant(env) {
|
|
10609
|
-
return resolveLocalWorkspaceDescriptionVariant(
|
|
10610
|
-
env.NOLO_GLOBFILES_DESCRIPTION_VARIANT
|
|
10611
|
-
);
|
|
10155
|
+
function resolveGlobFilesDescriptionVariant(env) {
|
|
10156
|
+
return resolveLocalWorkspaceDescriptionVariant(
|
|
10157
|
+
env.NOLO_GLOBFILES_DESCRIPTION_VARIANT
|
|
10158
|
+
);
|
|
10612
10159
|
}
|
|
10613
10160
|
function resolveListFilesDescriptionVariant(env) {
|
|
10614
10161
|
return resolveLocalWorkspaceDescriptionVariant(
|
|
@@ -10652,61 +10199,10 @@ function resolveLocalWorkspaceParameterVariant(value) {
|
|
|
10652
10199
|
return value === "minimal" || value === "scoped" || value === "rich" ? value : "rich";
|
|
10653
10200
|
}
|
|
10654
10201
|
|
|
10655
|
-
// packages/cli/client/cliChildDialogPersist.ts
|
|
10656
|
-
async function persistCliPendingChildDialog(args) {
|
|
10657
|
-
const nowIso = new Date(args.now).toISOString();
|
|
10658
|
-
const dialogKey = `dialog-${args.userId}-${args.dialogId}`;
|
|
10659
|
-
const record = {
|
|
10660
|
-
id: args.dialogId,
|
|
10661
|
-
dbKey: dialogKey,
|
|
10662
|
-
type: "dialog",
|
|
10663
|
-
userId: args.userId,
|
|
10664
|
-
cybots: [args.agentKey],
|
|
10665
|
-
primaryAgentKey: args.agentKey,
|
|
10666
|
-
title: args.title.slice(0, 80),
|
|
10667
|
-
status: "pending",
|
|
10668
|
-
triggerType: "cli-local",
|
|
10669
|
-
executionMode: args.background ? "background" : "foreground",
|
|
10670
|
-
createdAt: nowIso,
|
|
10671
|
-
updatedAt: nowIso,
|
|
10672
|
-
...args.spaceId ? { spaceId: args.spaceId } : {},
|
|
10673
|
-
...args.parentDialogId ? { parentDialogId: args.parentDialogId } : {},
|
|
10674
|
-
...args.rootDialogId ? { rootDialogId: args.rootDialogId } : {},
|
|
10675
|
-
localRuntime: {
|
|
10676
|
-
host: "cli",
|
|
10677
|
-
workspaceRoot: args.workspaceRoot,
|
|
10678
|
-
workspaceKind: "current",
|
|
10679
|
-
workspaceAccess: "inherited"
|
|
10680
|
-
}
|
|
10681
|
-
};
|
|
10682
|
-
await args.store.batch([{ type: "put", key: dialogKey, value: record }]);
|
|
10683
|
-
}
|
|
10684
|
-
async function persistCliFailedChildDialog(args) {
|
|
10685
|
-
const dialogKey = `dialog-${args.userId}-${args.dialogId}`;
|
|
10686
|
-
const existing = await args.store.read(dialogKey);
|
|
10687
|
-
const existingRecord = existing && typeof existing === "object" ? existing : {};
|
|
10688
|
-
await args.store.batch([
|
|
10689
|
-
{
|
|
10690
|
-
type: "put",
|
|
10691
|
-
key: dialogKey,
|
|
10692
|
-
value: {
|
|
10693
|
-
...existingRecord,
|
|
10694
|
-
id: args.dialogId,
|
|
10695
|
-
dbKey: dialogKey,
|
|
10696
|
-
status: "failed",
|
|
10697
|
-
errorMessage: args.errorMessage,
|
|
10698
|
-
updatedAt: new Date(args.now).toISOString(),
|
|
10699
|
-
finishedAt: args.now
|
|
10700
|
-
}
|
|
10701
|
-
}
|
|
10702
|
-
]);
|
|
10703
|
-
}
|
|
10704
|
-
|
|
10705
10202
|
// packages/cli/client/localRuntimeTools.ts
|
|
10706
10203
|
function buildOpenAiTools(args) {
|
|
10707
10204
|
const toolset = buildLocalWorkspaceToolsetForEnv(args);
|
|
10708
10205
|
const toolNameSet = new Set(args.toolNames ?? []);
|
|
10709
|
-
const callAgentTools = toolNameSet.has("callAgent") ? prepareTools(["callAgent"]) : [];
|
|
10710
10206
|
const uiAskChoiceTools = toolNameSet.has("ask_user") ? prepareTools(["ask_user"]) : [];
|
|
10711
10207
|
const readPastedTextTools = toolNameSet.has("readPastedText") ? [
|
|
10712
10208
|
{
|
|
@@ -10740,7 +10236,6 @@ function buildOpenAiTools(args) {
|
|
|
10740
10236
|
}
|
|
10741
10237
|
] : [];
|
|
10742
10238
|
return [
|
|
10743
|
-
...callAgentTools,
|
|
10744
10239
|
...uiAskChoiceTools,
|
|
10745
10240
|
...readPastedTextTools,
|
|
10746
10241
|
...buildLocalWorkspaceOpenAiTools({
|
|
@@ -10775,7 +10270,7 @@ function addDefaultCliCoreTools(toolNames, env, options) {
|
|
|
10775
10270
|
}
|
|
10776
10271
|
function resolveCliEffectiveEnabledPacks(args) {
|
|
10777
10272
|
return resolveEffectiveEnabledPacks({
|
|
10778
|
-
enabledPacks: args
|
|
10273
|
+
enabledPacks: resolveAgentRequiredPackIds(args),
|
|
10779
10274
|
declaredOnly: args.declaredOnly,
|
|
10780
10275
|
emptyFallbackPacks: ["code"]
|
|
10781
10276
|
});
|
|
@@ -10804,6 +10299,7 @@ function resolveCliRequestedToolNames(agentConfig, env, systemBuiltinSkills, opt
|
|
|
10804
10299
|
expandEnabledPacks(
|
|
10805
10300
|
resolveCliEffectiveEnabledPacks({
|
|
10806
10301
|
enabledPacks: agentConfig?.enabledPacks,
|
|
10302
|
+
skills: agentConfig?.skills,
|
|
10807
10303
|
declaredOnly
|
|
10808
10304
|
}),
|
|
10809
10305
|
resolveRequestedRuntimeToolNames({ agentConfig })
|
|
@@ -10822,10 +10318,11 @@ function resolveCliRequestedToolNames(agentConfig, env, systemBuiltinSkills, opt
|
|
|
10822
10318
|
declaredOnly ? expanded : addDefaultSystemCapabilityTools(expanded),
|
|
10823
10319
|
systemBuiltinSkills
|
|
10824
10320
|
);
|
|
10825
|
-
|
|
10321
|
+
const afterDisabled = applyDisabledTools(
|
|
10826
10322
|
filtered,
|
|
10827
10323
|
agentConfig?.disabledTools
|
|
10828
10324
|
);
|
|
10325
|
+
return filterToolNamesForRunKind(afterDisabled, isSubtaskRun(env));
|
|
10829
10326
|
}
|
|
10830
10327
|
function resolveProviderOpenAiToolBundle(agentConfig, env, buildTools = buildOpenAiTools, additionalToolNames = [], options) {
|
|
10831
10328
|
const requestedToolNames = [
|
|
@@ -10898,167 +10395,480 @@ function buildServerPlatformOpenAiTools(args) {
|
|
|
10898
10395
|
...webTools
|
|
10899
10396
|
];
|
|
10900
10397
|
}
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
const
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
10931
|
-
|
|
10932
|
-
|
|
10398
|
+
|
|
10399
|
+
// packages/cli/client/hybridRecordStore.ts
|
|
10400
|
+
function resolveFallbackServers(env) {
|
|
10401
|
+
const values = [
|
|
10402
|
+
env.NOLO_SERVER_URL,
|
|
10403
|
+
env.BASE_URL,
|
|
10404
|
+
...parseSyncServersEnv(env),
|
|
10405
|
+
...NOLO_CLUSTER_SERVERS
|
|
10406
|
+
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
10407
|
+
return [...new Set(values.map(normalizeServerOrigin))];
|
|
10408
|
+
}
|
|
10409
|
+
function resolveAuthToken(env) {
|
|
10410
|
+
return resolvePlatformAuthToken(env);
|
|
10411
|
+
}
|
|
10412
|
+
function createCliHybridRecordStore(deps) {
|
|
10413
|
+
return createHybridRecordStore({
|
|
10414
|
+
db: deps.db,
|
|
10415
|
+
defaultServer: normalizeServerOrigin(
|
|
10416
|
+
deps.env.NOLO_SERVER || deps.env.BASE_URL || DEFAULT_NOLO_SERVER_URL
|
|
10417
|
+
),
|
|
10418
|
+
fallbackServers: resolveFallbackServers(deps.env),
|
|
10419
|
+
authToken: resolveAuthToken(deps.env),
|
|
10420
|
+
fetchImpl: deps.fetchImpl
|
|
10421
|
+
});
|
|
10422
|
+
}
|
|
10423
|
+
|
|
10424
|
+
// packages/agent-runtime/dialogTitleLlm.ts
|
|
10425
|
+
async function generateLocalDialogTitle(input) {
|
|
10426
|
+
const { env, messages, fallbackTitle } = input;
|
|
10427
|
+
const timeoutMs = input.timeoutMs ?? 15e3;
|
|
10428
|
+
const normalized = messages.filter((m) => m.role === "user" || m.role === "assistant").map((m, index) => ({
|
|
10429
|
+
id: m.id || `msg-${index}`,
|
|
10430
|
+
role: m.role,
|
|
10431
|
+
content: typeof m.content === "string" ? m.content : extractText(m.content)
|
|
10432
|
+
})).filter((m) => Boolean(m.content.trim()));
|
|
10433
|
+
if (normalized.length === 0) {
|
|
10434
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10435
|
+
}
|
|
10436
|
+
const earlyUserTurns = normalized.filter((m) => m.role === "user").slice(0, 2);
|
|
10437
|
+
const recentTurns = normalized.slice(-10);
|
|
10438
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10439
|
+
const visibleMessages = [...earlyUserTurns, ...recentTurns].filter((m) => {
|
|
10440
|
+
if (seen.has(m.id)) return false;
|
|
10441
|
+
seen.add(m.id);
|
|
10442
|
+
return true;
|
|
10443
|
+
}).map((m) => {
|
|
10444
|
+
const content = m.content.length > 500 ? `${m.content.slice(0, 500)}...` : m.content;
|
|
10445
|
+
return { role: m.role, content };
|
|
10446
|
+
});
|
|
10447
|
+
while (visibleMessages.length > 1 && JSON.stringify(visibleMessages).length > 4e3) {
|
|
10448
|
+
visibleMessages.shift();
|
|
10449
|
+
}
|
|
10450
|
+
if (visibleMessages.length === 0) {
|
|
10451
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10452
|
+
}
|
|
10453
|
+
if (input.resolveProviderConfig && input.buildRequest && input.parseResponse) {
|
|
10454
|
+
try {
|
|
10455
|
+
const providerConfig = await input.resolveProviderConfig({
|
|
10456
|
+
agentConfig: { ...BUILTIN_TITLE_LLM_CONFIG, key: BUILTIN_TITLE_LLM_CONFIG.id },
|
|
10457
|
+
env
|
|
10458
|
+
});
|
|
10459
|
+
if (providerConfig?.authToken) {
|
|
10460
|
+
const request = input.buildRequest({
|
|
10461
|
+
providerConfig,
|
|
10462
|
+
messages: [
|
|
10463
|
+
{
|
|
10464
|
+
role: "user",
|
|
10465
|
+
content: JSON.stringify(visibleMessages)
|
|
10466
|
+
}
|
|
10467
|
+
],
|
|
10468
|
+
stream: false
|
|
10469
|
+
});
|
|
10470
|
+
const res = await input.fetchImpl(request.url, {
|
|
10471
|
+
...request.init,
|
|
10472
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
10473
|
+
});
|
|
10474
|
+
if (res.ok) {
|
|
10475
|
+
const raw = await res.text().catch(() => "");
|
|
10476
|
+
const data = safeParseJson(raw);
|
|
10477
|
+
if (data) {
|
|
10478
|
+
const parsed = input.parseResponse({ providerConfig, data });
|
|
10479
|
+
const generated = normalizeDialogTitle(parsed.content);
|
|
10480
|
+
if (generated) {
|
|
10481
|
+
return { title: generated, source: "llm" };
|
|
10482
|
+
}
|
|
10483
|
+
}
|
|
10484
|
+
}
|
|
10485
|
+
}
|
|
10486
|
+
} catch {
|
|
10487
|
+
}
|
|
10488
|
+
}
|
|
10489
|
+
if (input.resolveDirectProviderConfig) {
|
|
10490
|
+
try {
|
|
10491
|
+
const envApiKey = env.OPENAI_API_KEY || env.NOLO_LOCAL_OPENAI_API_KEY || "";
|
|
10492
|
+
const directAgentConfig = input.agentConfig && input.agentConfig.apiSource !== "platform" ? {
|
|
10493
|
+
...input.agentConfig,
|
|
10494
|
+
// Fill env key only when the caller's agentConfig has no key of
|
|
10495
|
+
// its own; never overwrite an explicit agentConfig.apiKey.
|
|
10496
|
+
...envApiKey && !input.agentConfig.apiKey ? { apiKey: envApiKey } : {}
|
|
10497
|
+
} : {
|
|
10498
|
+
...BUILTIN_TITLE_LLM_CONFIG,
|
|
10499
|
+
apiSource: "custom",
|
|
10500
|
+
useServerProxy: false,
|
|
10501
|
+
key: BUILTIN_TITLE_LLM_CONFIG.id,
|
|
10502
|
+
...envApiKey ? { apiKey: envApiKey } : {}
|
|
10933
10503
|
};
|
|
10504
|
+
const directConfig = await input.resolveDirectProviderConfig({
|
|
10505
|
+
agentConfig: directAgentConfig,
|
|
10506
|
+
env
|
|
10507
|
+
});
|
|
10508
|
+
if (directConfig?.endpoint) {
|
|
10509
|
+
const apiKeyHeader = directConfig.apiKeyHeader || "Authorization";
|
|
10510
|
+
const apiKey = directConfig.apiKey || "";
|
|
10511
|
+
if (!apiKey && isRemoteAuthEndpoint(directConfig.endpoint)) {
|
|
10512
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10513
|
+
}
|
|
10514
|
+
const authValue = apiKeyHeader.toLowerCase() === "authorization" && apiKey && !apiKey.startsWith("Bearer ") ? `Bearer ${apiKey}` : apiKey;
|
|
10515
|
+
const headers = {
|
|
10516
|
+
"content-type": "application/json",
|
|
10517
|
+
...apiKey ? { [apiKeyHeader]: authValue } : {}
|
|
10518
|
+
};
|
|
10519
|
+
const res = await input.fetchImpl(directConfig.endpoint, {
|
|
10520
|
+
method: "POST",
|
|
10521
|
+
headers,
|
|
10522
|
+
body: JSON.stringify({
|
|
10523
|
+
model: directConfig.model || input.agentConfig?.model || BUILTIN_TITLE_LLM_CONFIG.model,
|
|
10524
|
+
messages: [
|
|
10525
|
+
{ role: "system", content: BUILTIN_TITLE_LLM_CONFIG.prompt },
|
|
10526
|
+
{ role: "user", content: JSON.stringify(visibleMessages) }
|
|
10527
|
+
],
|
|
10528
|
+
stream: false
|
|
10529
|
+
}),
|
|
10530
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
10531
|
+
});
|
|
10532
|
+
if (res.ok) {
|
|
10533
|
+
const raw = await res.text().catch(() => "");
|
|
10534
|
+
const data = safeParseJson(raw);
|
|
10535
|
+
const rawContent = data?.choices?.[0]?.message?.content ?? "";
|
|
10536
|
+
const generated = normalizeDialogTitle(rawContent);
|
|
10537
|
+
if (generated) {
|
|
10538
|
+
return { title: generated, source: "llm" };
|
|
10539
|
+
}
|
|
10540
|
+
}
|
|
10541
|
+
}
|
|
10542
|
+
} catch {
|
|
10934
10543
|
}
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
10940
|
-
|
|
10941
|
-
const
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
10544
|
+
}
|
|
10545
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10546
|
+
}
|
|
10547
|
+
function extractText(content) {
|
|
10548
|
+
if (typeof content === "string") return content;
|
|
10549
|
+
if (Array.isArray(content)) {
|
|
10550
|
+
const parts = content.map((part) => {
|
|
10551
|
+
if (!part) return "";
|
|
10552
|
+
if (typeof part === "string") return part;
|
|
10553
|
+
if (part.type === "text") return part.text ?? "";
|
|
10554
|
+
return "[\u56FE\u7247]";
|
|
10555
|
+
}).filter(Boolean);
|
|
10556
|
+
return parts.join(" ");
|
|
10557
|
+
}
|
|
10558
|
+
if (content && typeof content === "object") {
|
|
10559
|
+
const part = content;
|
|
10560
|
+
if (part.type === "text") return part.text ?? "";
|
|
10561
|
+
return "[\u56FE\u7247]";
|
|
10562
|
+
}
|
|
10563
|
+
return "";
|
|
10564
|
+
}
|
|
10565
|
+
function safeParseJson(raw) {
|
|
10566
|
+
try {
|
|
10567
|
+
return JSON.parse(raw);
|
|
10568
|
+
} catch {
|
|
10569
|
+
return null;
|
|
10570
|
+
}
|
|
10571
|
+
}
|
|
10572
|
+
function isRemoteAuthEndpoint(endpoint) {
|
|
10573
|
+
let host;
|
|
10574
|
+
try {
|
|
10575
|
+
host = new URL(endpoint).hostname.toLowerCase();
|
|
10576
|
+
} catch {
|
|
10577
|
+
return false;
|
|
10578
|
+
}
|
|
10579
|
+
if (!host) return false;
|
|
10580
|
+
if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host.endsWith(".local") || host.startsWith("192.168.") || host.startsWith("10.") || /^172\.(1[6-9]|2\d|3[01])\./.test(host)) {
|
|
10581
|
+
return false;
|
|
10582
|
+
}
|
|
10583
|
+
if (host === "api.openai.com" || host.endsWith(".openai.com") || host.endsWith(".openai.azure.com") || host === "api.deepseek.com" || host === "api.anthropic.com" || host === "generativelanguage.googleapis.com" || host === "api.together.xyz" || host === "api.groq.com" || host === "openrouter.ai" || host === "api.mistral.ai") {
|
|
10584
|
+
return true;
|
|
10585
|
+
}
|
|
10586
|
+
return false;
|
|
10587
|
+
}
|
|
10588
|
+
|
|
10589
|
+
// packages/cli/client/localRuntimeDialog.ts
|
|
10590
|
+
var import_date_fns = __toESM(require_date_fns(), 1);
|
|
10591
|
+
async function resolveStore(deps) {
|
|
10592
|
+
if (deps.store) return deps.store;
|
|
10593
|
+
return createCliHybridRecordStore({
|
|
10594
|
+
db: deps.db ?? await defaultLocalRuntimeDb(),
|
|
10595
|
+
env: deps.env,
|
|
10596
|
+
fetchImpl: deps.fetchImpl
|
|
10597
|
+
});
|
|
10598
|
+
}
|
|
10599
|
+
async function getOrCreateSharedStore(deps) {
|
|
10600
|
+
if (deps.store) return deps.store;
|
|
10601
|
+
const cacheKey = normalizeRuntimeCacheCwd(deps.cwd);
|
|
10602
|
+
let storePromise = hybridStoreCache.get(cacheKey);
|
|
10603
|
+
if (!storePromise) {
|
|
10604
|
+
storePromise = resolveStore(deps);
|
|
10605
|
+
hybridStoreCache.set(cacheKey, storePromise);
|
|
10606
|
+
}
|
|
10607
|
+
return storePromise;
|
|
10608
|
+
}
|
|
10609
|
+
function createLocalDialogTitleGenerator(deps, ctx) {
|
|
10610
|
+
if (!canUsePlatformChatProvider(deps.env) && !hasDirectOpenAiCompatibleProvider(deps.env)) {
|
|
10611
|
+
return null;
|
|
10612
|
+
}
|
|
10613
|
+
return async (input) => {
|
|
10614
|
+
const result = await generateLocalDialogTitle({
|
|
10615
|
+
messages: input.messages,
|
|
10616
|
+
env: deps.env,
|
|
10617
|
+
fetchImpl: async (url, init) => fetchWithTransientRetry(
|
|
10618
|
+
deps.fetchImpl ?? fetch,
|
|
10619
|
+
url,
|
|
10620
|
+
init,
|
|
10621
|
+
{
|
|
10622
|
+
sleep: deps.sleep,
|
|
10623
|
+
loopbackRequest: ctx.loopbackRequest,
|
|
10624
|
+
maxAttempts: 1
|
|
10625
|
+
}
|
|
10626
|
+
),
|
|
10627
|
+
resolveProviderConfig: async (args) => resolvePlatformChatProviderConfig({
|
|
10628
|
+
agentConfig: args.agentConfig,
|
|
10629
|
+
env: args.env,
|
|
10630
|
+
apiKeyRefResolver: ctx.apiKeyRefResolver,
|
|
10631
|
+
credentialBroker: ctx.credentialBroker
|
|
10632
|
+
}),
|
|
10633
|
+
resolveDirectProviderConfig: async (args) => resolveOpenAiCompatibleProviderConfig({
|
|
10634
|
+
agentConfig: args.agentConfig,
|
|
10635
|
+
env: args.env,
|
|
10636
|
+
apiKeyRefResolver: ctx.apiKeyRefResolver,
|
|
10637
|
+
credentialBroker: ctx.credentialBroker
|
|
10638
|
+
}),
|
|
10639
|
+
buildRequest: (args) => buildPlatformChatCompletionRequest({
|
|
10640
|
+
providerConfig: args.providerConfig,
|
|
10641
|
+
messages: args.messages,
|
|
10642
|
+
stream: false
|
|
10643
|
+
}),
|
|
10644
|
+
parseResponse: (args) => parsePlatformChatCompletionResponse({
|
|
10645
|
+
providerConfig: args.providerConfig,
|
|
10646
|
+
data: args.data,
|
|
10647
|
+
trace: []
|
|
10648
|
+
}),
|
|
10649
|
+
fallbackTitle: input.fallbackTitle,
|
|
10650
|
+
timeoutMs: 4e3
|
|
10967
10651
|
});
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10652
|
+
return result.source === "llm" ? result.title : null;
|
|
10653
|
+
};
|
|
10654
|
+
}
|
|
10655
|
+
async function writeLocalTokenRecord(args) {
|
|
10656
|
+
const usageRecords = args.input.usageRecords?.length ? args.input.usageRecords : args.input.result.usage ? [{
|
|
10657
|
+
callId: typeof args.input.result.usage?.provider_call_id === "string" && args.input.result.usage.provider_call_id.trim() ? args.input.result.usage.provider_call_id.trim() : args.createId(),
|
|
10658
|
+
usage: args.input.result.usage,
|
|
10659
|
+
model: args.input.result.model,
|
|
10660
|
+
...args.input.result.provider ? { provider: args.input.result.provider } : {}
|
|
10661
|
+
}] : [];
|
|
10662
|
+
if (usageRecords.length === 0) {
|
|
10663
|
+
return [];
|
|
10664
|
+
}
|
|
10665
|
+
const ops = [];
|
|
10666
|
+
for (const item of usageRecords) {
|
|
10667
|
+
if (!item.usage || Object.keys(item.usage).length === 0) continue;
|
|
10668
|
+
const timestamp = args.now();
|
|
10669
|
+
const callId = item.callId || typeof item.usage.provider_call_id === "string" && item.usage.provider_call_id.trim() || args.createId();
|
|
10670
|
+
const prepared = prepareTokenUsageData({
|
|
10671
|
+
rawUsage: item.usage,
|
|
10672
|
+
agentConfig: {
|
|
10673
|
+
model: item.model || args.input.billingConfig?.model || "unknown",
|
|
10674
|
+
provider: item.provider || args.input.billingConfig?.provider,
|
|
10675
|
+
apiSource: args.input.billingConfig?.apiSource,
|
|
10676
|
+
apiKeyRef: args.input.billingConfig?.apiKeyRef,
|
|
10677
|
+
inputPrice: args.input.billingConfig?.inputPrice,
|
|
10678
|
+
outputPrice: args.input.billingConfig?.outputPrice,
|
|
10679
|
+
sharingLevel: args.input.billingConfig?.sharingLevel,
|
|
10680
|
+
id: args.input.billingConfig?.id,
|
|
10681
|
+
userId: args.input.billingConfig?.userId
|
|
10682
|
+
},
|
|
10683
|
+
userId: args.userId,
|
|
10684
|
+
agentId: args.input.agentKey,
|
|
10685
|
+
dialogId: args.dialogId,
|
|
10686
|
+
timestamp,
|
|
10687
|
+
entry_path: "cli-local"
|
|
10972
10688
|
});
|
|
10973
|
-
const
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
parentDialogId
|
|
10689
|
+
const recordKey = createTokenKey.recordForStableCall(args.userId, callId);
|
|
10690
|
+
const existingToken = await args.store.read(recordKey, { remote: false }).catch(() => null);
|
|
10691
|
+
if (existingToken) continue;
|
|
10692
|
+
const tokenRecord = {
|
|
10693
|
+
id: args.createId(),
|
|
10694
|
+
type: "token",
|
|
10695
|
+
...prepared.tokenData
|
|
10981
10696
|
};
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
}
|
|
10697
|
+
await args.store.write(recordKey, tokenRecord);
|
|
10698
|
+
ops.push({ type: "put", key: recordKey, value: tokenRecord });
|
|
10699
|
+
const dateKey = (0, import_date_fns.format)(timestamp, "yyyy-MM-dd");
|
|
10700
|
+
const statsKey = createTokenStatsKey(args.userId, dateKey);
|
|
10701
|
+
await runKeyed(statsKey, async () => {
|
|
10702
|
+
let existingStats = null;
|
|
10703
|
+
try {
|
|
10704
|
+
existingStats = await args.store.read(statsKey, { remote: false });
|
|
10705
|
+
} catch {
|
|
10706
|
+
}
|
|
10707
|
+
const newStats = applyTokenUsageToDayStats(existingStats, {
|
|
10708
|
+
userId: args.userId,
|
|
10709
|
+
timeKey: dateKey,
|
|
10710
|
+
model: prepared.billedModel,
|
|
10711
|
+
provider: prepared.recordProvider,
|
|
10712
|
+
input_tokens: prepared.usage.input_tokens,
|
|
10713
|
+
output_tokens: prepared.usage.output_tokens,
|
|
10714
|
+
cost: prepared.tokenData.cost
|
|
11001
10715
|
});
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
10716
|
+
const statsRecord = { ...newStats, id: statsKey, type: "token" };
|
|
10717
|
+
await args.store.write(statsKey, statsRecord);
|
|
10718
|
+
});
|
|
10719
|
+
}
|
|
10720
|
+
return ops;
|
|
10721
|
+
}
|
|
10722
|
+
async function writeDialog(args) {
|
|
10723
|
+
let existingDialog = null;
|
|
10724
|
+
if (args.input.continueDialogId) {
|
|
10725
|
+
const dialogKey = `dialog-${args.userId}-${args.input.continueDialogId}`;
|
|
10726
|
+
existingDialog = await args.store.read(dialogKey);
|
|
10727
|
+
}
|
|
10728
|
+
const nowMs = args.now();
|
|
10729
|
+
const existingTitle = typeof existingDialog?.title === "string" ? existingDialog.title.trim() : "";
|
|
10730
|
+
const existingTitleSource = existingDialog?.titleSource;
|
|
10731
|
+
const titleTimeoutMs = args.titleTimeoutMs ?? 2500;
|
|
10732
|
+
let needsTitleUpdate = false;
|
|
10733
|
+
if (existingTitleSource === "manual") {
|
|
10734
|
+
needsTitleUpdate = false;
|
|
10735
|
+
} else if (!existingTitle) {
|
|
10736
|
+
needsTitleUpdate = true;
|
|
10737
|
+
} else {
|
|
10738
|
+
const titleUpdatedAtMs = parseTitleUpdatedAtMs(existingDialog);
|
|
10739
|
+
if (titleUpdatedAtMs > 0) {
|
|
10740
|
+
if (nowMs - titleUpdatedAtMs >= 30 * 60 * 1e3) {
|
|
10741
|
+
needsTitleUpdate = true;
|
|
10742
|
+
}
|
|
10743
|
+
} else {
|
|
10744
|
+
needsTitleUpdate = false;
|
|
11012
10745
|
}
|
|
10746
|
+
}
|
|
10747
|
+
let titlePromise;
|
|
10748
|
+
if (needsTitleUpdate && args.titleGenerator) {
|
|
10749
|
+
const rawLastUserText = extractLastUserText(args.input.messages);
|
|
10750
|
+
const fallbackTitle = buildDialogFallbackTitleFromUserInput(rawLastUserText) || "Local agent run";
|
|
10751
|
+
titlePromise = args.titleGenerator({ messages: args.input.messages, fallbackTitle }).catch(() => null);
|
|
10752
|
+
}
|
|
10753
|
+
let resolvedTitle = null;
|
|
10754
|
+
if (titlePromise) {
|
|
10755
|
+
let timeoutId;
|
|
10756
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
10757
|
+
timeoutId = setTimeout(() => resolve(null), titleTimeoutMs);
|
|
10758
|
+
});
|
|
11013
10759
|
try {
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
10760
|
+
resolvedTitle = await Promise.race([titlePromise, timeoutPromise]);
|
|
10761
|
+
} catch {
|
|
10762
|
+
resolvedTitle = null;
|
|
10763
|
+
} finally {
|
|
10764
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
10765
|
+
}
|
|
10766
|
+
}
|
|
10767
|
+
const plan = buildLocalDialogWritePlan({
|
|
10768
|
+
input: args.input,
|
|
10769
|
+
userId: args.userId,
|
|
10770
|
+
now: nowMs,
|
|
10771
|
+
createId: args.createId,
|
|
10772
|
+
existingDialog,
|
|
10773
|
+
cwd: args.cwd,
|
|
10774
|
+
...resolvedTitle ? { titleOverride: resolvedTitle } : {}
|
|
10775
|
+
});
|
|
10776
|
+
await args.store.batch(plan.ops);
|
|
10777
|
+
let tokenOps = [];
|
|
10778
|
+
try {
|
|
10779
|
+
tokenOps = await writeLocalTokenRecord({
|
|
10780
|
+
store: args.store,
|
|
10781
|
+
input: args.input,
|
|
10782
|
+
userId: args.userId,
|
|
10783
|
+
dialogId: plan.dialogId,
|
|
10784
|
+
now: args.now,
|
|
10785
|
+
createId: args.createId,
|
|
10786
|
+
output: args.output
|
|
10787
|
+
});
|
|
10788
|
+
} catch (error) {
|
|
10789
|
+
args.output?.write(
|
|
10790
|
+
`[nolo] Token usage record write failed (non-fatal): ${toErrorMessage(error)}
|
|
11042
10791
|
`
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
|
|
11056
|
-
|
|
10792
|
+
);
|
|
10793
|
+
}
|
|
10794
|
+
const hasSubjectRefs = localTurnHasSubjectRefs(args.input);
|
|
10795
|
+
const isLocalUser = args.userId === "local";
|
|
10796
|
+
if (!isLocalUser) {
|
|
10797
|
+
try {
|
|
10798
|
+
const syncResult = await syncLocalDialogEvidenceToRemote({
|
|
10799
|
+
env: args.env,
|
|
10800
|
+
fetchImpl: args.fetchImpl,
|
|
10801
|
+
input: args.input,
|
|
10802
|
+
ops: [...plan.ops, ...tokenOps],
|
|
10803
|
+
output: args.output,
|
|
10804
|
+
userId: args.userId
|
|
10805
|
+
});
|
|
10806
|
+
if (!syncResult.attempted) {
|
|
10807
|
+
if (hasSubjectRefs) {
|
|
10808
|
+
args.output?.write(
|
|
10809
|
+
"[nolo] Local dialog evidence is local-only; set NOLO_SERVER and AUTH_TOKEN to make subjectRefs remotely queryable.\n"
|
|
10810
|
+
);
|
|
11057
10811
|
}
|
|
11058
|
-
}
|
|
10812
|
+
}
|
|
10813
|
+
} catch (error) {
|
|
10814
|
+
if (hasSubjectRefs) {
|
|
10815
|
+
throw error;
|
|
10816
|
+
}
|
|
10817
|
+
args.output?.write(
|
|
10818
|
+
`[nolo] Remote dialog evidence sync failed; local dialog only: ${toErrorMessage(
|
|
10819
|
+
error
|
|
10820
|
+
)}
|
|
10821
|
+
`
|
|
10822
|
+
);
|
|
11059
10823
|
}
|
|
10824
|
+
}
|
|
10825
|
+
return { dialogId: plan.dialogId, title: plan.title };
|
|
10826
|
+
}
|
|
10827
|
+
function resolveCliDialogRecordKey(userId, dialogId) {
|
|
10828
|
+
if (dialogId.startsWith("dialog-") && !dialogId.includes("-msg-")) {
|
|
10829
|
+
return dialogId;
|
|
10830
|
+
}
|
|
10831
|
+
return `dialog-${userId}-${dialogId}`;
|
|
10832
|
+
}
|
|
10833
|
+
async function loadCliDialogSummary(args) {
|
|
10834
|
+
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10835
|
+
const record = await args.store.read(dialogKey);
|
|
10836
|
+
if (!record || typeof record !== "object") return null;
|
|
10837
|
+
const summary = typeof record.summary === "string" ? record.summary.trim() : "";
|
|
10838
|
+
if (!summary) return null;
|
|
10839
|
+
const summarizedBeforeId = record.summarizedBeforeId;
|
|
10840
|
+
return {
|
|
10841
|
+
summary,
|
|
10842
|
+
...typeof summarizedBeforeId === "string" && summarizedBeforeId ? { summarizedBeforeId } : {}
|
|
11060
10843
|
};
|
|
11061
10844
|
}
|
|
10845
|
+
async function saveCliDialogSummary(args) {
|
|
10846
|
+
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10847
|
+
const existing = await args.store.read(dialogKey) ?? {};
|
|
10848
|
+
const bareId = typeof existing.id === "string" && existing.id ? existing.id : args.dialogId.startsWith("dialog-") ? args.dialogId.slice(args.dialogId.lastIndexOf("-") + 1) : args.dialogId;
|
|
10849
|
+
const compressionCount = typeof existing.compressionCount === "number" ? existing.compressionCount + 1 : 1;
|
|
10850
|
+
await args.store.write(dialogKey, {
|
|
10851
|
+
...existing,
|
|
10852
|
+
id: bareId,
|
|
10853
|
+
dbKey: dialogKey,
|
|
10854
|
+
type: "dialog",
|
|
10855
|
+
userId: args.userId,
|
|
10856
|
+
summary: args.summary,
|
|
10857
|
+
...args.summarizedBeforeId !== void 0 ? { summarizedBeforeId: args.summarizedBeforeId } : {},
|
|
10858
|
+
compressionCount,
|
|
10859
|
+
summaryPending: false,
|
|
10860
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10861
|
+
});
|
|
10862
|
+
}
|
|
10863
|
+
function parseTitleUpdatedAtMs(existingDialog) {
|
|
10864
|
+
const raw = existingDialog?.titleUpdatedAt;
|
|
10865
|
+
if (typeof raw === "number" && !Number.isNaN(raw)) return raw;
|
|
10866
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
10867
|
+
const parsed = Date.parse(raw);
|
|
10868
|
+
if (!Number.isNaN(parsed)) return parsed;
|
|
10869
|
+
}
|
|
10870
|
+
return 0;
|
|
10871
|
+
}
|
|
11062
10872
|
|
|
11063
10873
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
11064
10874
|
var currentMetaFile = fileURLToPath(import.meta.url);
|
|
@@ -11210,6 +11020,21 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11210
11020
|
})
|
|
11211
11021
|
}),
|
|
11212
11022
|
resolveProvider: async (agentConfig) => {
|
|
11023
|
+
if (isAgentCoolingDown(agentConfig, now())) {
|
|
11024
|
+
throw new Error(
|
|
11025
|
+
`agent temporarily unavailable until ${new Date(Number(agentConfig.nextAvailableAt)).toISOString()}`
|
|
11026
|
+
);
|
|
11027
|
+
}
|
|
11028
|
+
const recordLocalAvailability = async (status, body) => {
|
|
11029
|
+
const key = typeof agentConfig.key === "string" ? agentConfig.key : "";
|
|
11030
|
+
if (!key || status !== 200 && status !== 429) return;
|
|
11031
|
+
const current = await getOrCreateSharedStore(deps).then((store) => store.read(key, { remote: false })).catch(() => null);
|
|
11032
|
+
if (!current || typeof current !== "object") return;
|
|
11033
|
+
const next = { ...current };
|
|
11034
|
+
if (status === 429) next.nextAvailableAt = resolveAgentNextAvailableAt(body, now());
|
|
11035
|
+
else delete next.nextAvailableAt;
|
|
11036
|
+
await getOrCreateSharedStore(deps).then((store) => store.write(key, next)).catch(() => void 0);
|
|
11037
|
+
};
|
|
11213
11038
|
if (isCliProviderAgent(agentConfig)) {
|
|
11214
11039
|
const provider = resolveCliProviderName(agentConfig);
|
|
11215
11040
|
logLocalRuntimeDiagnostic("provider.selected", {
|
|
@@ -11260,7 +11085,20 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11260
11085
|
const credentialBroker = createFileCredentialBroker();
|
|
11261
11086
|
const serverUrl = asOptionalTrimmedString(deps.env.NOLO_SERVER) ?? "https://us.nolo.chat";
|
|
11262
11087
|
const authToken = asOptionalTrimmedString(deps.env.AUTH_TOKEN);
|
|
11263
|
-
const syncFetcher = authToken ? (ref) =>
|
|
11088
|
+
const syncFetcher = authToken ? async (ref) => {
|
|
11089
|
+
try {
|
|
11090
|
+
return await fetchServerSyncedCredential(
|
|
11091
|
+
{ currentServer: serverUrl, authToken },
|
|
11092
|
+
ref
|
|
11093
|
+
);
|
|
11094
|
+
} catch (error) {
|
|
11095
|
+
logLocalRuntimeDiagnostic("credential.sync.unavailable", {
|
|
11096
|
+
ref,
|
|
11097
|
+
error: toErrorMessage(error)
|
|
11098
|
+
});
|
|
11099
|
+
return null;
|
|
11100
|
+
}
|
|
11101
|
+
} : void 0;
|
|
11264
11102
|
if (isAntigravityOAuthAgent(agentConfig)) {
|
|
11265
11103
|
const accessToken = await apiKeyRefResolver("antigravity");
|
|
11266
11104
|
if (!accessToken) {
|
|
@@ -11314,6 +11152,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11314
11152
|
loopbackRequest
|
|
11315
11153
|
})
|
|
11316
11154
|
});
|
|
11155
|
+
await recordLocalAvailability(result.status, result.body);
|
|
11317
11156
|
if (result.status < 200 || result.status >= 300) {
|
|
11318
11157
|
const errMsg = result.body && typeof result.body === "object" && result.body.error && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
|
|
11319
11158
|
throw new Error(
|
|
@@ -11382,6 +11221,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11382
11221
|
loopbackRequest
|
|
11383
11222
|
})
|
|
11384
11223
|
});
|
|
11224
|
+
await recordLocalAvailability(result.status, result.body);
|
|
11385
11225
|
if (result.status < 200 || result.status >= 300) {
|
|
11386
11226
|
const errMsg = result.body?.error && typeof result.body.error === "object" && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
|
|
11387
11227
|
throw new Error(
|
|
@@ -11452,6 +11292,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11452
11292
|
loopbackRequest
|
|
11453
11293
|
})
|
|
11454
11294
|
});
|
|
11295
|
+
await recordLocalAvailability(result.status, result.body);
|
|
11455
11296
|
if (result.status < 200 || result.status >= 300) {
|
|
11456
11297
|
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
11298
|
throw new Error(
|
|
@@ -11474,6 +11315,14 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11474
11315
|
return {
|
|
11475
11316
|
content,
|
|
11476
11317
|
...tool_calls ? { tool_calls } : {},
|
|
11318
|
+
// fetchCodexResponsesCompletion 已把 codex responses 流聚合完毕并归一化成
|
|
11319
|
+
// OpenAI chat.completions 形状:choices[0].finish_reason("stop"/"tool_calls")
|
|
11320
|
+
// + usage(prompt/completion/total_tokens)。必须透传,否则 localLoop 把正常走完
|
|
11321
|
+
// 的空轮误判成 stream_truncated、TUI context chip 也拿不到 token 数更新。
|
|
11322
|
+
finish_reason: typeof choice?.finish_reason === "string" ? choice.finish_reason : void 0,
|
|
11323
|
+
stream_complete: true,
|
|
11324
|
+
// body 类型是 Record<string, unknown>,透传 usage 需 cast 到 AgentRuntimeResult.usage。
|
|
11325
|
+
usage: result.body?.usage,
|
|
11477
11326
|
trace: messages
|
|
11478
11327
|
};
|
|
11479
11328
|
}
|
|
@@ -11923,9 +11772,7 @@ export {
|
|
|
11923
11772
|
t,
|
|
11924
11773
|
toolLabel,
|
|
11925
11774
|
agentRunCardLabels,
|
|
11926
|
-
QUOTA_ERROR_PATTERNS,
|
|
11927
|
-
isQuotaExhaustedError,
|
|
11928
11775
|
clearCliLocalRuntimePreparedAgentCache,
|
|
11929
|
-
|
|
11776
|
+
isSubtaskRun,
|
|
11930
11777
|
createCliLocalRuntimeAdapter
|
|
11931
11778
|
};
|