nolo-cli 0.19.0 → 0.24.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{_executeModel-X5PCIZN6.js → _executeModel-ARCMGGMY.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-C5PIEBMZ.js} +27 -26
- package/{agentEmailCommands-2QJDGRMB.js → agentEmailCommands-QTGQ3ZAD.js} +57 -55
- package/{agentListCommands-6VEPTKBI.js → agentListCommands-LRHBS3A5.js} +30 -26
- package/{agentMachineCommands-NVVHNWYI.js → agentMachineCommands-4PXIT4BP.js} +25 -24
- package/{agentRecordCommands-4GGRDMD4.js → agentRecordCommands-ZZPTYTYR.js} +52 -50
- package/{agentRunCommand-XOLQNKBZ.js → agentRunCommand-7ZTPZNUX.js} +55 -54
- package/{agentRunControl-Y5AFH5PQ.js → agentRunControl-SNUKXN6J.js} +6 -2
- package/{agentRuntimeLocal-7WYWCGL4.js → agentRuntimeLocal-QOYY5UV2.js} +19 -18
- package/{agentSlice-EAXPGEYV.js → agentSlice-J3W3RX2I.js} +5 -5
- package/{appDeleteCommands-77KR2RJ4.js → appDeleteCommands-7NS46XDH.js} +23 -22
- package/{appDeployCommands-K7CAHGBI.js → appDeployCommands-RSRNQ67U.js} +23 -22
- package/{appDeployStatusCommands-4OEKLTBT.js → appDeployStatusCommands-EF4RSGC6.js} +23 -22
- package/{appGetCommands-VM2WDLAZ.js → appGetCommands-YA7JWYUX.js} +23 -22
- package/{appListCommands-GX6BBA6U.js → appListCommands-WM2ON6JW.js} +23 -22
- package/{authCommand-DY6UUL6O.js → authCommand-HJP7FURK.js} +12 -13
- package/{authCommands-XTBV7OFZ.js → authCommands-NYZM2B2I.js} +4 -5
- package/{chunk-MKA6QE5E.js → chunk-2IPEVBUO.js} +126 -68
- package/{chunk-OWOHNGCN.js → chunk-2MBTWINN.js} +42 -3
- package/{chunk-K6EUAOW3.js → chunk-35RYGII3.js} +1 -1
- package/{chunk-TRT4I4UD.js → chunk-4POUK2BV.js} +2 -2
- package/{chunk-LLWKHDG4.js → chunk-4ULSC37S.js} +1 -3
- package/{chunk-EDV7EBOI.js → chunk-4ZH6GUJF.js} +2151 -1500
- package/{chunk-MVQ4TBSD.js → chunk-54VHTARN.js} +1 -1
- package/{chunk-L4F3I4SR.js → chunk-5HQQ4LUU.js} +4 -6
- package/{chunk-Z4NR32XR.js → chunk-5RGU3J7P.js} +13 -0
- package/{chunk-7BUYEZ6U.js → chunk-7H3UTGPM.js} +12 -72
- package/{chunk-RQN4SEKL.js → chunk-7W6GFNJL.js} +1 -1
- package/{chunk-HEGV7BH3.js → chunk-AQZCWJOG.js} +1 -1
- package/{chunk-3ND52WIL.js → chunk-ATWUOTJP.js} +180 -24
- package/chunk-CF7S2RYZ.js +376 -0
- package/{chunk-I2ZJKTG5.js → chunk-CGVRC2TB.js} +7 -7
- package/{chunk-UAIVG4J6.js → chunk-CHSCAUZN.js} +1 -8
- package/{chunk-KFEVY3ST.js → chunk-D34RI6NI.js} +18 -8
- package/{chunk-ROWQEJRP.js → chunk-DXJS7VSG.js} +3 -2
- package/{chunk-MHSGJW4Z.js → chunk-EHOYZRTI.js} +44 -14
- package/{chunk-XRZJGPFI.js → chunk-FON47ACC.js} +4 -4
- package/{chunk-SCTYAHYK.js → chunk-H2NAWOLH.js} +217 -141
- package/{chunk-MPVYDS7I.js → chunk-H6ODMJR3.js} +3 -3
- package/{chunk-R35XMF6F.js → chunk-H73ZV2GL.js} +352 -30
- package/{chunk-4T5F7YZQ.js → chunk-I6RJGORZ.js} +1 -1
- package/{chunk-OK6YSWLH.js → chunk-IICW77GI.js} +1 -1
- package/{chunk-VDXCXCXH.js → chunk-IUDMBCXC.js} +1 -1
- package/{chunk-AHCY2S2I.js → chunk-JADNODCQ.js} +1 -1
- package/{chunk-DFCFMCY6.js → chunk-JBLY6HQP.js} +2 -2
- package/{chunk-UGUW3FHG.js → chunk-JMSCXQUG.js} +2 -2
- package/{chunk-N54HIJVJ.js → chunk-KFUCLS7Z.js} +101 -9
- package/{chunk-FQZZLA3C.js → chunk-KXKQO4Q6.js} +17 -0
- package/{chunk-3Q7WHGCB.js → chunk-L65QKSVJ.js} +1 -1
- package/{chunk-3ZX7PERL.js → chunk-LALVWNE4.js} +20 -7
- package/{chunk-PJSV3IZ5.js → chunk-M3TMVJKG.js} +1 -1
- package/{chunk-REA4JLBH.js → chunk-M5OZCOBV.js} +7 -6
- package/{chunk-JLA4FXYC.js → chunk-MALVZUYL.js} +1 -1
- 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-G5U6LDLG.js → chunk-NVHPMDSZ.js} +6 -6
- package/{chunk-23FZYPLC.js → chunk-OJFYT3ZQ.js} +842 -1060
- package/{chunk-ELT65PZW.js → chunk-OXLLFZNF.js} +1 -1
- package/{chunk-CZ6NYQTV.js → chunk-P4QWLZGU.js} +2 -2
- package/{chunk-5MIDPSSK.js → chunk-PB7G5MAM.js} +3 -3
- package/{chunk-HWW2M4SN.js → chunk-QLVWFXZQ.js} +5 -4
- package/{chunk-VYHDJEQD.js → chunk-QNLLGS37.js} +136 -78
- package/{chunk-XHG22OEX.js → chunk-ROJI6DRT.js} +2 -2
- package/{chunk-BV4VEE3W.js → chunk-ROYOKSX4.js} +243 -354
- package/{chunk-VNAEBGDK.js → chunk-RZNYL4LW.js} +123 -26
- package/{chunk-RVOUXDFU.js → chunk-S6KVFOUG.js} +6 -34
- package/{chunk-V3ED5AWK.js → chunk-S77SCVBU.js} +27 -16
- package/{chunk-UBHAWFQ6.js → chunk-S7RWIPDI.js} +42 -19
- package/{chunk-B5TOXZAK.js → chunk-SIZQB7BD.js} +1 -1
- package/{chunk-DFFIZ25G.js → chunk-SLOGKB7M.js} +4 -1
- package/{chunk-FXUSIQC2.js → chunk-SROR5TSM.js} +1 -1
- package/{chunk-PIZYJVHQ.js → chunk-TN4YHAI3.js} +4 -4
- package/{chunk-IYEXFJPC.js → chunk-TW35GDNW.js} +64 -57
- package/chunk-UZ6XXCVR.js +50 -0
- package/{chunk-DKZFOK24.js → chunk-UZH44DWK.js} +7 -288
- package/{chunk-YGW4G5W5.js → chunk-X546QUDT.js} +61 -12
- package/chunk-YYLHWIW6.js +48 -0
- package/{chunk-SWDPIPOY.js → chunk-ZGVW7MSZ.js} +1 -1
- 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-MKQWN4VQ.js} +19 -18
- package/{createDialogAction-RB55KCLO.js → createDialogAction-YWIZPLFS.js} +22 -20
- package/{createPageAction-Y7343GLU.js → createPageAction-74TTEIPC.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-MJIP32FL.js} +24 -23
- package/{dialogSlice-UQAXF23P.js → dialogSlice-KLLVH4WI.js} +24 -18
- package/{docCreateCommands-I2EWZGCI.js → docCreateCommands-5DN472U6.js} +24 -27
- package/{docDeleteCommands-IZ45UZKG.js → docDeleteCommands-HE76LBN4.js} +25 -24
- package/{docReadCommands-R6Z4QJYU.js → docReadCommands-XVGZSCBS.js} +24 -23
- package/{docStore-5HOJ4D7D.js → docStore-SPH3D6BT.js} +20 -19
- package/{docUpdateCommands-2LRBKQPY.js → docUpdateCommands-P7IAWUAD.js} +24 -27
- package/{fetchMessages-BMGVZVSE.js → fetchMessages-W4IKHPCS.js} +2 -3
- package/{getPricing-G7DLAST6.js → getPricing-WENPBVWH.js} +3 -3
- package/{handleSendMessageAction-Q4HY35WX.js → handleSendMessageAction-ZU6WJVL7.js} +23 -20
- package/index.js +74 -74
- package/{localDialogRead-4H3QJFLW.js → localDialogRead-JXTAHW2E.js} +2 -2
- package/{machineCommands-PKBPQKTY.js → machineCommands-NI76PVHK.js} +59 -57
- package/{machineWsRunDispatch-UZAW4OXJ.js → machineWsRunDispatch-W3G6NJVQ.js} +51 -49
- package/{models-DJFSJ7SW.js → models-DB27UAE3.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-BDH4G477.js} +880 -425
- package/{removeDialogAgentAction-OAGA2G3U.js → removeDialogAgentAction-QCFGIUIH.js} +8 -7
- package/{runAgentClientLoop-NBPIKJ6J.js → runAgentClientLoop-ZPKMXCM5.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-3GGBJRQR.js} +25 -24
- package/{spaceSlice-ZXLLG3CR.js → spaceSlice-47Z6XLFQ.js} +21 -18
- package/{streamAgentChatTurn-L3YW6LSB.js → streamAgentChatTurn-VT5K5JSD.js} +140 -98
- package/switchDialogAgentAction-4OAC6QRN.js +61 -0
- package/{tableCommands-BEQAGE4I.js → tableCommands-HEQYT2KP.js} +1 -1
- package/{toolApiClient-QI3YBNWB.js → toolApiClient-ISM4ZQX4.js} +2 -2
- package/{tools-ECGXR5QF.js → tools-L7RCHAPT.js} +36 -33
- package/{tuiSummaryLlmCaller-OMSCNHXA.js → tuiSummaryLlmCaller-3DYOLTVN.js} +6 -6
- package/{updateCommands-XTW55TOT.js → updateCommands-HTCOBXCA.js} +2 -2
- package/{updateDialogTitleAction-HQ2EUDFT.js → updateDialogTitleAction-KMPVPQ4A.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,11 @@ import {
|
|
|
3
3
|
refreshAntigravityOAuthToken,
|
|
4
4
|
refreshOpenAiCodexToken,
|
|
5
5
|
refreshXaiOAuthToken
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IICW77GI.js";
|
|
7
7
|
import {
|
|
8
8
|
buildLocalAgentLookupKeys,
|
|
9
9
|
shouldReadAgentKeyRemotely
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZGVW7MSZ.js";
|
|
11
11
|
import {
|
|
12
12
|
LOCAL_CODEX_AGENT_ID,
|
|
13
13
|
LOCAL_CODEX_AGENT_KEY,
|
|
@@ -16,57 +16,61 @@ import {
|
|
|
16
16
|
} from "./chunk-VHBWHNVT.js";
|
|
17
17
|
import {
|
|
18
18
|
inferCaptureIntent
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-54VHTARN.js";
|
|
20
20
|
import {
|
|
21
21
|
inlineImageUrlsForCustomProvider,
|
|
22
22
|
prepareTools
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-P4QWLZGU.js";
|
|
24
24
|
import {
|
|
25
25
|
getAntigravityUserAgent,
|
|
26
26
|
isAntigravityOAuthAgent,
|
|
27
27
|
readAntigravityProjectId,
|
|
28
28
|
resolveAntigravityCloudCodeBaseUrl
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-SROR5TSM.js";
|
|
30
30
|
import {
|
|
31
|
-
FORCED_TOOLS,
|
|
32
|
-
addDefaultLightWebToolsForConfiguredAgents,
|
|
33
|
-
addDefaultSystemCapabilityTools,
|
|
34
|
-
appendEnabledPackPromptPatches,
|
|
35
|
-
applyDisabledTools,
|
|
36
|
-
applySystemBuiltinSkillFilter,
|
|
37
|
-
expandEnabledPacks,
|
|
38
31
|
readXPostFunc,
|
|
39
32
|
readXPostFunctionSchema,
|
|
40
33
|
readXhsProfileFunc,
|
|
41
34
|
readXhsProfileFunctionSchema,
|
|
42
35
|
rememberMemoryFunctionSchema,
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
resolveAgentRequiredPackIds,
|
|
37
|
+
setTodoListFunc
|
|
38
|
+
} from "./chunk-4ZH6GUJF.js";
|
|
45
39
|
import {
|
|
46
40
|
createDrainExhaustedResponse,
|
|
47
41
|
isCoreDrainingBody,
|
|
48
42
|
normalizeNonNegativeMs,
|
|
49
43
|
parseRetryAfterHeaderMs
|
|
50
44
|
} from "./chunk-RQSOAMPJ.js";
|
|
51
|
-
import {
|
|
52
|
-
normalizeDialogTitle
|
|
53
|
-
} from "./chunk-OWOHNGCN.js";
|
|
54
45
|
import {
|
|
55
46
|
getDefaultCliLocalRuntimeDb
|
|
56
47
|
} from "./chunk-WJRJDX2W.js";
|
|
57
48
|
import {
|
|
58
|
-
prepareTokenUsageData
|
|
59
|
-
|
|
49
|
+
prepareTokenUsageData,
|
|
50
|
+
resolveBuiltinPlatformAgentConfig
|
|
51
|
+
} from "./chunk-H2NAWOLH.js";
|
|
60
52
|
import {
|
|
61
53
|
BUILTIN_TITLE_LLM_CONFIG
|
|
62
54
|
} from "./chunk-XOIF2TNF.js";
|
|
63
55
|
import {
|
|
64
56
|
fetchServerSyncedCredential
|
|
65
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-M5OZCOBV.js";
|
|
58
|
+
import {
|
|
59
|
+
FORCED_TOOLS,
|
|
60
|
+
addDefaultLightWebToolsForConfiguredAgents,
|
|
61
|
+
addDefaultSystemCapabilityTools,
|
|
62
|
+
appendEnabledPackPromptPatches,
|
|
63
|
+
applyDisabledTools,
|
|
64
|
+
applySystemBuiltinSkillFilter,
|
|
65
|
+
expandEnabledPacks,
|
|
66
|
+
resolveEffectiveEnabledPacks
|
|
67
|
+
} from "./chunk-CF7S2RYZ.js";
|
|
66
68
|
import {
|
|
67
69
|
buildAgentRuntimeDialogWritePlan,
|
|
70
|
+
buildLoadSkillExecutor,
|
|
68
71
|
buildLocalWorkspaceOpenAiTools,
|
|
69
72
|
buildLocalWorkspaceToolset,
|
|
73
|
+
buildNoloWorkspaceCliToolExecutors,
|
|
70
74
|
createHybridRecordStore,
|
|
71
75
|
createLocalWorkspaceToolExecutors,
|
|
72
76
|
dialogMessageRecordToAgentRuntimeMessage,
|
|
@@ -76,36 +80,39 @@ import {
|
|
|
76
80
|
parseSseDataLineObject,
|
|
77
81
|
readOpenAiCompatibleSseCompletion,
|
|
78
82
|
resolveOpenAiCompatibleProviderConfig
|
|
79
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-H73ZV2GL.js";
|
|
80
84
|
import {
|
|
81
85
|
buildPlatformChatCompletionRequest,
|
|
82
86
|
canUsePlatformChatProvider,
|
|
87
|
+
hasDirectOpenAiCompatibleProvider,
|
|
83
88
|
parsePlatformChatCompletionData,
|
|
84
89
|
parsePlatformChatCompletionResponse,
|
|
85
90
|
readSseDataValues,
|
|
86
91
|
resolvePlatformChatProviderConfig,
|
|
87
92
|
shouldUsePlatformChatProvider
|
|
88
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-KFUCLS7Z.js";
|
|
89
94
|
import {
|
|
90
95
|
resolveAgentRuntimeConfigFromRecord
|
|
91
96
|
} from "./chunk-OIQPORYI.js";
|
|
92
97
|
import {
|
|
93
98
|
summarizeToolArguments
|
|
94
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-X546QUDT.js";
|
|
95
100
|
import {
|
|
96
101
|
convertMessagesToResponsesInput,
|
|
97
102
|
toResponsesTools
|
|
98
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-D34RI6NI.js";
|
|
99
104
|
import {
|
|
100
105
|
resolvePlatformAuthToken
|
|
101
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-EHOYZRTI.js";
|
|
102
107
|
import {
|
|
103
|
-
buildLoadSkillExecutor,
|
|
104
|
-
buildNoloWorkspaceCliToolExecutors,
|
|
105
108
|
buildNoloWorkspaceOpenAiTools,
|
|
106
109
|
parseNoloWorkspaceToolArguments,
|
|
107
110
|
resolveRuntimeToolSurfaceForAgent
|
|
108
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-UZH44DWK.js";
|
|
112
|
+
import {
|
|
113
|
+
buildDialogFallbackTitleFromUserInput,
|
|
114
|
+
normalizeDialogTitle
|
|
115
|
+
} from "./chunk-2MBTWINN.js";
|
|
109
116
|
import {
|
|
110
117
|
clipCompactText
|
|
111
118
|
} from "./chunk-5MMAK75Q.js";
|
|
@@ -123,10 +130,7 @@ import {
|
|
|
123
130
|
} from "./chunk-JZPBVBIY.js";
|
|
124
131
|
import {
|
|
125
132
|
isAdaptiveThinkingModelId
|
|
126
|
-
} from "./chunk-
|
|
127
|
-
import {
|
|
128
|
-
toErrorMessage
|
|
129
|
-
} from "./chunk-HNMXYYJR.js";
|
|
133
|
+
} from "./chunk-CHSCAUZN.js";
|
|
130
134
|
import {
|
|
131
135
|
canonicalizeToolNames
|
|
132
136
|
} from "./chunk-ZZ2MH7LE.js";
|
|
@@ -134,13 +138,14 @@ import {
|
|
|
134
138
|
compactWhitespace
|
|
135
139
|
} from "./chunk-DWLEOOGR.js";
|
|
136
140
|
import {
|
|
141
|
+
ackRunRecord,
|
|
137
142
|
checkStaleRun,
|
|
138
143
|
finalizeRunRecord,
|
|
139
144
|
findRunRecord,
|
|
140
145
|
gcRunRecords,
|
|
141
146
|
queryRunRecords,
|
|
142
147
|
spawnLocalBackgroundRun
|
|
143
|
-
} from "./chunk-
|
|
148
|
+
} from "./chunk-RZNYL4LW.js";
|
|
144
149
|
import {
|
|
145
150
|
TASK_PREVIEW_MAX,
|
|
146
151
|
formatListRunsCard,
|
|
@@ -152,14 +157,17 @@ import {
|
|
|
152
157
|
isAgentRunTerminalStatus,
|
|
153
158
|
resolveRunLabel,
|
|
154
159
|
shortRunId
|
|
155
|
-
} from "./chunk-
|
|
160
|
+
} from "./chunk-KXKQO4Q6.js";
|
|
156
161
|
import {
|
|
157
162
|
CliProviderQuotaError,
|
|
158
163
|
executeCli
|
|
159
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-CMKUBIGW.js";
|
|
160
165
|
import {
|
|
161
166
|
buildCliPrompt
|
|
162
167
|
} from "./chunk-ATNTHIZI.js";
|
|
168
|
+
import {
|
|
169
|
+
toErrorMessage
|
|
170
|
+
} from "./chunk-HNMXYYJR.js";
|
|
163
171
|
import {
|
|
164
172
|
isCompiledBinary,
|
|
165
173
|
parseUserIdFromAuthToken
|
|
@@ -171,7 +179,7 @@ import {
|
|
|
171
179
|
createTokenKey,
|
|
172
180
|
createUserKey,
|
|
173
181
|
dialogMessageRange
|
|
174
|
-
} from "./chunk-
|
|
182
|
+
} from "./chunk-NRY4GCKJ.js";
|
|
175
183
|
import {
|
|
176
184
|
asOptionalFiniteNumber
|
|
177
185
|
} from "./chunk-WWC7I6TA.js";
|
|
@@ -182,15 +190,8 @@ import {
|
|
|
182
190
|
asTrimmedLowercaseString
|
|
183
191
|
} from "./chunk-QSJ3HFEF.js";
|
|
184
192
|
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";
|
|
193
|
+
isSystemBuiltinTrustedAgentKey
|
|
194
|
+
} from "./chunk-ATWUOTJP.js";
|
|
194
195
|
import {
|
|
195
196
|
isRecord
|
|
196
197
|
} from "./chunk-KUG52IAP.js";
|
|
@@ -782,6 +783,18 @@ var STRINGS = {
|
|
|
782
783
|
en: "Forked dialog {0} \u2192 {1} (no summary needed).",
|
|
783
784
|
zh: "\u5DF2\u5206\u53C9\u5BF9\u8BDD {0} \u2192 {1}\uFF08\u65E0\u9700\u538B\u7F29\uFF09\u3002"
|
|
784
785
|
},
|
|
786
|
+
compactSuccess: {
|
|
787
|
+
en: "\u2713 Compacted dialog {0} \u2192 {1} in {2}.",
|
|
788
|
+
zh: "\u2713 \u5DF2\u538B\u7F29\u5BF9\u8BDD {0} \u2192 {1}\uFF0C\u8017\u65F6 {2}\u3002"
|
|
789
|
+
},
|
|
790
|
+
compactSuccessWithCount: {
|
|
791
|
+
en: "\u2713 Compacted dialog {0} \u2192 {1} in {2} ({3} messages compressed).",
|
|
792
|
+
zh: "\u2713 \u5DF2\u538B\u7F29\u5BF9\u8BDD {0} \u2192 {1}\uFF0C\u8017\u65F6 {2}\uFF08\u538B\u7F29 {3} \u6761\u6D88\u606F\uFF09\u3002"
|
|
793
|
+
},
|
|
794
|
+
compactForked: {
|
|
795
|
+
en: "\u2713 Forked dialog {0} \u2192 {1} in {2} (no summary needed).",
|
|
796
|
+
zh: "\u2713 \u5DF2\u5206\u53C9\u5BF9\u8BDD {0} \u2192 {1}\uFF0C\u8017\u65F6 {2}\uFF08\u65E0\u9700\u538B\u7F29\uFF09\u3002"
|
|
797
|
+
},
|
|
785
798
|
agentCurrent: { en: "Current agent: {0} ({1})", zh: "\u5F53\u524D agent\uFF1A{0}\uFF08{1}\uFF09" },
|
|
786
799
|
agentUnknown: {
|
|
787
800
|
en: `I don't know agent "{0}" yet.
|
|
@@ -915,6 +928,11 @@ var TOOL_LABELS = {
|
|
|
915
928
|
captureVisualState: { en: "Capture", zh: "\u622A\u5C4F" },
|
|
916
929
|
// Workspace / diagnostics
|
|
917
930
|
searchWorkspace: { en: "Search workspace", zh: "\u641C\u7D22\u5DE5\u4F5C\u533A" },
|
|
931
|
+
// 同一工具在 web/server 工具面用 snake_case 命名(packages/ai/tools/index.ts)。
|
|
932
|
+
search_workspace: { en: "Search workspace", zh: "\u641C\u7D22\u5DE5\u4F5C\u533A" },
|
|
933
|
+
// 全空间搜索:内置 skill search-all-spaces 声明的工作区工具,loadSkill 后进入
|
|
934
|
+
// 工具面;同样需要中英文标签,避免回退成裸工具名。
|
|
935
|
+
search_all_spaces: { en: "Search all spaces", zh: "\u641C\u7D22\u5168\u90E8\u7A7A\u95F4" },
|
|
918
936
|
cliDoctor: { en: "Doctor", zh: "\u81EA\u68C0" },
|
|
919
937
|
cliWhoami: { en: "Whoami", zh: "\u67E5\u770B\u8EAB\u4EFD" },
|
|
920
938
|
checkEnv: { en: "Check env", zh: "\u68C0\u67E5\u73AF\u5883" },
|
|
@@ -960,185 +978,6 @@ function agentRunCardLabels() {
|
|
|
960
978
|
};
|
|
961
979
|
}
|
|
962
980
|
|
|
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
981
|
// packages/cli/client/localRuntimeDiagnostics.ts
|
|
1143
982
|
import { ulid } from "ulid";
|
|
1144
983
|
var preparedAgentRuntimeCache = /* @__PURE__ */ new Map();
|
|
@@ -1177,6 +1016,36 @@ function summarizeOpenAiToolNames(tools) {
|
|
|
1177
1016
|
}, []);
|
|
1178
1017
|
}
|
|
1179
1018
|
|
|
1019
|
+
// packages/agent-runtime/agentRunIsolation.ts
|
|
1020
|
+
var ORCHESTRATION_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1021
|
+
"startAgentRun",
|
|
1022
|
+
"controlAgentRun",
|
|
1023
|
+
"listAgents",
|
|
1024
|
+
"readAgent",
|
|
1025
|
+
"startAgentDialog",
|
|
1026
|
+
"runStreamingAgent",
|
|
1027
|
+
"streamParallelAgents"
|
|
1028
|
+
]);
|
|
1029
|
+
var SUBTASK_REMOVED_GIT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1030
|
+
"gitAdd",
|
|
1031
|
+
"gitCommit",
|
|
1032
|
+
"gitCreateBranch",
|
|
1033
|
+
"commitWorkspace"
|
|
1034
|
+
]);
|
|
1035
|
+
var SUBTASK_REMOVED_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1036
|
+
...ORCHESTRATION_TOOL_NAMES,
|
|
1037
|
+
...SUBTASK_REMOVED_GIT_TOOL_NAMES
|
|
1038
|
+
]);
|
|
1039
|
+
function isSubtaskRun(env) {
|
|
1040
|
+
if (!env) return false;
|
|
1041
|
+
const value = env.NOLO_AGENT_RUN_CHILD;
|
|
1042
|
+
return typeof value === "string" && value.length > 0 && value !== "0";
|
|
1043
|
+
}
|
|
1044
|
+
function filterToolNamesForRunKind(toolNames, isSubtask) {
|
|
1045
|
+
if (!isSubtask) return [...toolNames];
|
|
1046
|
+
return toolNames.filter((name) => !SUBTASK_REMOVED_TOOL_NAMES.has(name));
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1180
1049
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
1181
1050
|
import { dirname as dirname2, extname, join as join2 } from "node:path";
|
|
1182
1051
|
import { fileURLToPath } from "node:url";
|
|
@@ -1662,93 +1531,6 @@ function assertWithinLocalToolBudget(args) {
|
|
|
1662
1531
|
);
|
|
1663
1532
|
}
|
|
1664
1533
|
|
|
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
1534
|
// packages/cli/client/localDialogRecords.ts
|
|
1753
1535
|
var localDialogMessageRecordToRuntimeMessage = dialogMessageRecordToAgentRuntimeMessage;
|
|
1754
1536
|
function buildLocalDialogWritePlan(args) {
|
|
@@ -1814,22 +1596,6 @@ async function readDialogMessages(args) {
|
|
|
1814
1596
|
}
|
|
1815
1597
|
|
|
1816
1598
|
// 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
1599
|
function isCliProviderAgent(agentConfig) {
|
|
1834
1600
|
return Boolean(
|
|
1835
1601
|
agentConfig.apiSource === "cli" || agentConfig.provider === "cli" || agentConfig.cliProvider
|
|
@@ -1890,7 +1656,7 @@ function collectCliProviderImageInputs(messages) {
|
|
|
1890
1656
|
}
|
|
1891
1657
|
|
|
1892
1658
|
// packages/cli/client/cliAgentConfigHelpers.ts
|
|
1893
|
-
var
|
|
1659
|
+
var BUILTIN_NOLO_AGENT_KEY = NOLO_DEFAULT_AGENT_KEY;
|
|
1894
1660
|
var BUILTIN_NOLO_AGENT_ID = NOLO_DEFAULT_AGENT_ID;
|
|
1895
1661
|
function resolveLocalUserId(env) {
|
|
1896
1662
|
const explicitUserId = env.NOLO_LOCAL_USER_ID || env.NOLO_USER_ID;
|
|
@@ -1901,7 +1667,7 @@ function resolveLocalUserId(env) {
|
|
|
1901
1667
|
function isBuiltinNoloAgentRef(ref) {
|
|
1902
1668
|
if (typeof ref !== "string") return false;
|
|
1903
1669
|
const normalized = ref.trim();
|
|
1904
|
-
return normalized ===
|
|
1670
|
+
return normalized === BUILTIN_NOLO_AGENT_KEY || normalized === BUILTIN_NOLO_AGENT_ID || normalized.endsWith(`-${BUILTIN_NOLO_AGENT_ID}`);
|
|
1905
1671
|
}
|
|
1906
1672
|
function isBuiltinNoloAgentConfig(agentConfig) {
|
|
1907
1673
|
const key = agentConfig?.key || agentConfig?.rawRecord?.dbKey || agentConfig?.rawRecord?.agentKey;
|
|
@@ -1913,14 +1679,15 @@ function withResolvedRuntimeToolSurface(agentConfig, env) {
|
|
|
1913
1679
|
const currentUserId = resolveLocalUserId(env);
|
|
1914
1680
|
const rawRecord = agentConfig.rawRecord ?? {};
|
|
1915
1681
|
const ownerId = asOptionalTrimmedString(rawRecord.userId) ?? null;
|
|
1682
|
+
const agentKey = rawRecord.dbKey ?? agentConfig.key;
|
|
1916
1683
|
const toolSurface = resolveRuntimeToolSurfaceForAgent({
|
|
1917
1684
|
explicitToolNames: agentConfig.toolNames,
|
|
1918
1685
|
currentUserId,
|
|
1919
1686
|
agentOwnerId: ownerId,
|
|
1920
|
-
agentKey
|
|
1687
|
+
agentKey,
|
|
1921
1688
|
isPublic: !isBuiltinNoloAgentConfig(agentConfig) && rawRecord.isPublic === true,
|
|
1922
1689
|
sharingLevel: typeof rawRecord.sharingLevel === "string" ? rawRecord.sharingLevel : null,
|
|
1923
|
-
trustedPrivateInvocation: isBuiltinNoloAgentConfig(agentConfig),
|
|
1690
|
+
trustedPrivateInvocation: isBuiltinNoloAgentConfig(agentConfig) || isSystemBuiltinTrustedAgentKey(agentKey),
|
|
1924
1691
|
runtimeHost: "cli"
|
|
1925
1692
|
});
|
|
1926
1693
|
return {
|
|
@@ -2439,54 +2206,29 @@ function aggregateBatch(input) {
|
|
|
2439
2206
|
};
|
|
2440
2207
|
}
|
|
2441
2208
|
|
|
2442
|
-
// packages/ai/tools/agent/
|
|
2443
|
-
var
|
|
2444
|
-
|
|
2209
|
+
// packages/ai/tools/agent/agentRunTodo.ts
|
|
2210
|
+
var SUCCESS_STATUSES = /* @__PURE__ */ new Set(["completed", "done", "success", "passed", "finished"]);
|
|
2211
|
+
var FAILED_STATUSES = /* @__PURE__ */ new Set(["failed", "error", "stopped", "cancelled", "orphaned", "blocked"]);
|
|
2212
|
+
function deriveAgentRunTodoStatus(input) {
|
|
2445
2213
|
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) };
|
|
2214
|
+
if (!runs || runs.length === 0) {
|
|
2215
|
+
return { status: todo.status ?? "pending" };
|
|
2454
2216
|
}
|
|
2455
|
-
const
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
};
|
|
2217
|
+
const latestRun = runs[runs.length - 1];
|
|
2218
|
+
const hasRunning = runs.some(
|
|
2219
|
+
(r) => r.status === "running" || r.status === "in_progress" || r.status === "executing"
|
|
2220
|
+
);
|
|
2221
|
+
if (hasRunning) {
|
|
2222
|
+
return { status: "running", latestRun };
|
|
2462
2223
|
}
|
|
2463
|
-
|
|
2464
|
-
|
|
2224
|
+
const runStatus = (latestRun.status || "").toLowerCase();
|
|
2225
|
+
if (SUCCESS_STATUSES.has(runStatus)) {
|
|
2226
|
+
return { status: "done", latestRun };
|
|
2465
2227
|
}
|
|
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
|
-
}
|
|
2228
|
+
if (FAILED_STATUSES.has(runStatus)) {
|
|
2229
|
+
return { status: "failed", latestRun };
|
|
2482
2230
|
}
|
|
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;
|
|
2231
|
+
return { status: todo.status ?? "pending", latestRun };
|
|
2490
2232
|
}
|
|
2491
2233
|
|
|
2492
2234
|
// packages/cli/client/fileSystemStores.ts
|
|
@@ -2519,50 +2261,41 @@ function readJson(path, fs) {
|
|
|
2519
2261
|
function writeJson(path, data, fs) {
|
|
2520
2262
|
fs.writeFileSync(path, JSON.stringify(data, null, 2));
|
|
2521
2263
|
}
|
|
2522
|
-
function
|
|
2264
|
+
function createFileSystemTodoStore(opts = {}) {
|
|
2523
2265
|
const env = opts.env ?? process.env;
|
|
2524
2266
|
const homedir = opts.homedir ?? nodeHomedir;
|
|
2525
2267
|
const fs = opts.fs ?? nodeFs;
|
|
2526
|
-
const
|
|
2268
|
+
const noloHome = resolveNoloHome(env, homedir);
|
|
2269
|
+
const filePath = opts.filePath ?? join(noloHome, "agent_run_todos.json");
|
|
2270
|
+
const oldFilePath = join(noloHome, "todos.json");
|
|
2527
2271
|
const loadMap = () => {
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2272
|
+
if (!opts.filePath && !fs.existsSync(filePath) && fs.existsSync(oldFilePath)) {
|
|
2273
|
+
const oldData = readJson(oldFilePath, fs);
|
|
2274
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
2275
|
+
if (oldData?.todos) {
|
|
2276
|
+
for (const item of oldData.todos) {
|
|
2277
|
+
if (item && typeof item.id === "string") {
|
|
2278
|
+
let status = "pending";
|
|
2279
|
+
if (item.status === "running") status = "running";
|
|
2280
|
+
else if (item.status === "done") status = "done";
|
|
2281
|
+
else if (item.status === "blocked" || item.status === "abandoned" || item.status === "failed") status = "failed";
|
|
2282
|
+
const rec = {
|
|
2283
|
+
...item,
|
|
2284
|
+
id: item.id,
|
|
2285
|
+
title: item.title || "Untitled Task",
|
|
2286
|
+
status,
|
|
2287
|
+
runIds: Array.isArray(item.runIds) ? item.runIds : [],
|
|
2288
|
+
createdAt: item.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
2289
|
+
updatedAt: item.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
2290
|
+
};
|
|
2291
|
+
map2.set(rec.id, rec);
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2533
2294
|
}
|
|
2295
|
+
ensureDir(dirname(filePath), fs);
|
|
2296
|
+
writeJson(filePath, { todos: [...map2.values()] }, fs);
|
|
2297
|
+
return map2;
|
|
2534
2298
|
}
|
|
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
2299
|
const data = readJson(filePath, fs);
|
|
2567
2300
|
const map = /* @__PURE__ */ new Map();
|
|
2568
2301
|
if (data?.todos) {
|
|
@@ -2578,13 +2311,15 @@ function createFileSystemTodoStore(opts = {}) {
|
|
|
2578
2311
|
};
|
|
2579
2312
|
return {
|
|
2580
2313
|
async getTodo(id) {
|
|
2581
|
-
return loadMap().get(id);
|
|
2314
|
+
return loadMap().get(id) ?? null;
|
|
2582
2315
|
},
|
|
2583
|
-
async listTodos(
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2316
|
+
async listTodos() {
|
|
2317
|
+
return [...loadMap().values()];
|
|
2318
|
+
},
|
|
2319
|
+
async saveTodo(todo) {
|
|
2320
|
+
const map = loadMap();
|
|
2321
|
+
map.set(todo.id, todo);
|
|
2322
|
+
persist(map);
|
|
2588
2323
|
},
|
|
2589
2324
|
async putTodo(todo) {
|
|
2590
2325
|
const map = loadMap();
|
|
@@ -2593,8 +2328,10 @@ function createFileSystemTodoStore(opts = {}) {
|
|
|
2593
2328
|
},
|
|
2594
2329
|
async deleteTodo(id) {
|
|
2595
2330
|
const map = loadMap();
|
|
2331
|
+
const existed = map.has(id);
|
|
2596
2332
|
map.delete(id);
|
|
2597
2333
|
persist(map);
|
|
2334
|
+
return existed;
|
|
2598
2335
|
}
|
|
2599
2336
|
};
|
|
2600
2337
|
}
|
|
@@ -2621,10 +2358,8 @@ var tailFile = (logPath, tailLines, fs) => {
|
|
|
2621
2358
|
return void 0;
|
|
2622
2359
|
}
|
|
2623
2360
|
};
|
|
2624
|
-
var resolveBreakerStore = (deps) => deps.breakerStore ?? createFileSystemCircuitBreakerStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2625
2361
|
var resolveTodoStore = (deps) => deps.todoStore ?? createFileSystemTodoStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2626
2362
|
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
2363
|
function buildProgressField(record, nowMs) {
|
|
2629
2364
|
const activity = record.activity;
|
|
2630
2365
|
if (!activity || isAgentRunTerminalStatus(record.status)) return {};
|
|
@@ -2642,6 +2377,55 @@ function buildProgressField(record, nowMs) {
|
|
|
2642
2377
|
}
|
|
2643
2378
|
return { progress };
|
|
2644
2379
|
}
|
|
2380
|
+
var WAIT_POLL_INTERVAL_MS = 500;
|
|
2381
|
+
var DEFAULT_WAIT_TIMEOUT_MS = 1e5;
|
|
2382
|
+
function buildRunStatusPayload(reconciled, deps, opts = {}) {
|
|
2383
|
+
const logLines = opts.logTail ? opts.logTail.split("\n") : void 0;
|
|
2384
|
+
const name = resolveRunLabel(reconciled);
|
|
2385
|
+
const labels = agentRunCardLabels();
|
|
2386
|
+
return {
|
|
2387
|
+
content: JSON.stringify({
|
|
2388
|
+
runId: reconciled.runId,
|
|
2389
|
+
found: true,
|
|
2390
|
+
status: reconciled.status,
|
|
2391
|
+
pid: reconciled.pid ?? null,
|
|
2392
|
+
agentKey: reconciled.agentKey,
|
|
2393
|
+
...reconciled.agentName ? { agentName: reconciled.agentName } : {},
|
|
2394
|
+
startedAt: reconciled.startedAt,
|
|
2395
|
+
endedAt: reconciled.endedAt ?? null,
|
|
2396
|
+
exitCode: reconciled.exitCode ?? null,
|
|
2397
|
+
// Expose dialogId so the caller can read the agent's actual output
|
|
2398
|
+
// via `nolo dialog read <dialogId>`. The dialog is the authoritative
|
|
2399
|
+
// result store; the run log is the child process stdout/stderr,
|
|
2400
|
+
// whose contents vary by provider (some stream tokens to stdout,
|
|
2401
|
+
// some only emit startup + stderr). Because status does not carry
|
|
2402
|
+
// logTail by default, a "done" run with an empty logTail is
|
|
2403
|
+
// indistinguishable from a hung run without this field. Surfacing
|
|
2404
|
+
// dialogId gives the caller a reliable way to fetch the result.
|
|
2405
|
+
...reconciled.dialogId ? { dialogId: reconciled.dialogId } : {},
|
|
2406
|
+
// Progress is what makes tailLines:0 an actual answer to "is it
|
|
2407
|
+
// stuck?". Without it a poll returns `running` and a pid, so the only
|
|
2408
|
+
// way to tell a working run from a wedged one was to pull 30 lines of
|
|
2409
|
+
// log — the exact thing the orchestration prompt tells the model not
|
|
2410
|
+
// to do. The registry has been recording this all along and `nolo
|
|
2411
|
+
// agent status` has been printing it; only the tool was blind.
|
|
2412
|
+
...buildProgressField(reconciled, resolveNowMs(deps)),
|
|
2413
|
+
...opts.logTail !== void 0 ? { logTail: opts.logTail } : {},
|
|
2414
|
+
...logLines ? { logLines } : {}
|
|
2415
|
+
}),
|
|
2416
|
+
metadata: {
|
|
2417
|
+
displayData: formatStatusRunCard(name, reconciled.status, {
|
|
2418
|
+
runId: reconciled.runId,
|
|
2419
|
+
timing: {
|
|
2420
|
+
startedAt: readTimestamp(reconciled.startedAt),
|
|
2421
|
+
finishedAt: readTimestamp(reconciled.endedAt)
|
|
2422
|
+
},
|
|
2423
|
+
logLines,
|
|
2424
|
+
labels
|
|
2425
|
+
})
|
|
2426
|
+
}
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2645
2429
|
function createCliStartAgentRunExecutor(deps = {}) {
|
|
2646
2430
|
return async (call) => {
|
|
2647
2431
|
const args = parseCallArgs(call);
|
|
@@ -2649,29 +2433,7 @@ function createCliStartAgentRunExecutor(deps = {}) {
|
|
|
2649
2433
|
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
2650
2434
|
if (!agentKey) throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
|
|
2651
2435
|
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
2436
|
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
2437
|
const message = typeof args.input === "undefined" ? task : `${task}
|
|
2676
2438
|
|
|
2677
2439
|
--- \u9644\u52A0\u8F93\u5165 ---
|
|
@@ -2719,16 +2481,15 @@ ${JSON.stringify(args.input)}`;
|
|
|
2719
2481
|
id: todoId,
|
|
2720
2482
|
title: taskPreview || task.slice(0, 100),
|
|
2721
2483
|
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
2484
|
runIds,
|
|
2727
|
-
deps: existing?.deps ?? [],
|
|
2728
2485
|
createdAt: existing?.createdAt ?? nowIso,
|
|
2729
2486
|
updatedAt: nowIso
|
|
2730
2487
|
};
|
|
2731
|
-
|
|
2488
|
+
if (typeof todoStore.saveTodo === "function") {
|
|
2489
|
+
await todoStore.saveTodo(todo);
|
|
2490
|
+
} else {
|
|
2491
|
+
await todoStore.putTodo(todo);
|
|
2492
|
+
}
|
|
2732
2493
|
} catch {
|
|
2733
2494
|
}
|
|
2734
2495
|
}
|
|
@@ -2808,12 +2569,11 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2808
2569
|
}
|
|
2809
2570
|
};
|
|
2810
2571
|
}
|
|
2811
|
-
if (action === "todo") {
|
|
2572
|
+
if (action === "todo" || action === "agentRunTodo" || action === "agent_run_todo") {
|
|
2812
2573
|
const todoStore = resolveTodoStore(deps);
|
|
2813
|
-
const
|
|
2814
|
-
const
|
|
2815
|
-
|
|
2816
|
-
const enriched = await Promise.all(
|
|
2574
|
+
const todos = await todoStore.listTodos();
|
|
2575
|
+
const statusFilter = typeof args.status === "string" ? args.status.trim().toLowerCase() : void 0;
|
|
2576
|
+
let enriched = await Promise.all(
|
|
2817
2577
|
todos.map(async (todo) => {
|
|
2818
2578
|
const runSummaries = [];
|
|
2819
2579
|
for (const rid of todo.runIds) {
|
|
@@ -2822,26 +2582,29 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2822
2582
|
runSummaries.push({
|
|
2823
2583
|
runId: rec.runId,
|
|
2824
2584
|
status: rec.status,
|
|
2825
|
-
startedAt: rec.startedAt,
|
|
2585
|
+
startedAt: readTimestamp(rec.startedAt)?.toString(),
|
|
2586
|
+
finishedAt: readTimestamp(rec.endedAt)?.toString(),
|
|
2826
2587
|
...rec.agentName ? { agentName: rec.agentName } : {}
|
|
2827
2588
|
});
|
|
2828
2589
|
}
|
|
2829
|
-
const derived =
|
|
2590
|
+
const derived = deriveAgentRunTodoStatus({
|
|
2830
2591
|
todo: { id: todo.id, status: todo.status },
|
|
2831
|
-
runs: runSummaries
|
|
2832
|
-
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2592
|
+
runs: runSummaries
|
|
2833
2593
|
});
|
|
2834
2594
|
return {
|
|
2835
2595
|
id: todo.id,
|
|
2836
2596
|
title: todo.title,
|
|
2837
2597
|
status: derived.status,
|
|
2838
2598
|
runIds: todo.runIds,
|
|
2839
|
-
...derived.blockedReason ? { blockedReason: derived.blockedReason } : {},
|
|
2840
2599
|
...derived.latestRun ? { latestRunId: derived.latestRun.runId, latestRunStatus: derived.latestRun.status } : {},
|
|
2841
2600
|
updatedAt: todo.updatedAt
|
|
2842
2601
|
};
|
|
2843
2602
|
})
|
|
2844
2603
|
);
|
|
2604
|
+
if (statusFilter && statusFilter !== "all") {
|
|
2605
|
+
const wanted = new Set(statusFilter.split(",").map((s) => s.trim()).filter(Boolean));
|
|
2606
|
+
enriched = enriched.filter((t2) => wanted.has(t2.status.toLowerCase()));
|
|
2607
|
+
}
|
|
2845
2608
|
return {
|
|
2846
2609
|
content: JSON.stringify({ todos: enriched, count: enriched.length }),
|
|
2847
2610
|
metadata: {
|
|
@@ -2855,7 +2618,7 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2855
2618
|
}
|
|
2856
2619
|
};
|
|
2857
2620
|
}
|
|
2858
|
-
if (action !== "status" && action !== "stop") {
|
|
2621
|
+
if (action !== "status" && action !== "stop" && action !== "wait") {
|
|
2859
2622
|
throw new Error(`controlAgentRun: \u672A\u77E5 action "${action}"\u3002`);
|
|
2860
2623
|
}
|
|
2861
2624
|
if (!args.runId) throw new Error(`controlAgentRun(action:"${action}"): \u7F3A\u5C11 runId\u3002`);
|
|
@@ -2870,70 +2633,43 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2870
2633
|
if (action === "status") {
|
|
2871
2634
|
const reconciled = checkStaleRun(record.runId, deps) ?? record;
|
|
2872
2635
|
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
|
-
|
|
2636
|
+
return buildRunStatusPayload(reconciled, deps, { logTail });
|
|
2637
|
+
}
|
|
2638
|
+
if (action === "wait") {
|
|
2639
|
+
const timeoutMs = typeof args.timeoutMs === "number" && args.timeoutMs > 0 ? args.timeoutMs : DEFAULT_WAIT_TIMEOUT_MS;
|
|
2640
|
+
const startMs = resolveNowMs(deps);
|
|
2641
|
+
const deadline = startMs + timeoutMs;
|
|
2642
|
+
const sleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2643
|
+
let reconciled = record;
|
|
2644
|
+
for (; ; ) {
|
|
2645
|
+
reconciled = checkStaleRun(record.runId, deps) ?? record;
|
|
2646
|
+
if (isAgentRunTerminalStatus(reconciled.status)) break;
|
|
2647
|
+
const nowMs = resolveNowMs(deps);
|
|
2648
|
+
const waitedMs = nowMs - startMs;
|
|
2649
|
+
if (nowMs >= deadline) {
|
|
2650
|
+
return {
|
|
2651
|
+
content: JSON.stringify({
|
|
2652
|
+
runId: reconciled.runId,
|
|
2653
|
+
found: true,
|
|
2654
|
+
status: "timeout",
|
|
2655
|
+
runStatus: reconciled.status,
|
|
2656
|
+
pid: reconciled.pid ?? null,
|
|
2657
|
+
agentKey: reconciled.agentKey,
|
|
2658
|
+
...reconciled.agentName ? { agentName: reconciled.agentName } : {},
|
|
2659
|
+
startedAt: reconciled.startedAt,
|
|
2660
|
+
waitedMs,
|
|
2661
|
+
timeoutMs,
|
|
2662
|
+
...buildProgressField(reconciled, nowMs)
|
|
2663
|
+
}),
|
|
2664
|
+
metadata: {
|
|
2665
|
+
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`
|
|
2666
|
+
}
|
|
2667
|
+
};
|
|
2893
2668
|
}
|
|
2669
|
+
await sleep(WAIT_POLL_INTERVAL_MS);
|
|
2894
2670
|
}
|
|
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
|
-
};
|
|
2671
|
+
ackRunRecord(reconciled.runId, deps);
|
|
2672
|
+
return buildRunStatusPayload(reconciled, deps);
|
|
2937
2673
|
}
|
|
2938
2674
|
if (typeof record.pid === "number") {
|
|
2939
2675
|
try {
|
|
@@ -3168,6 +2904,20 @@ function buildLocalToolExecutors(args) {
|
|
|
3168
2904
|
controlAgentRun: createCliControlAgentRunExecutor({
|
|
3169
2905
|
env: args.env
|
|
3170
2906
|
}),
|
|
2907
|
+
setTodoList: async (call) => {
|
|
2908
|
+
const parsedArgs = typeof call?.arguments === "string" ? (() => {
|
|
2909
|
+
try {
|
|
2910
|
+
return JSON.parse(call.arguments);
|
|
2911
|
+
} catch {
|
|
2912
|
+
return {};
|
|
2913
|
+
}
|
|
2914
|
+
})() : call?.arguments || {};
|
|
2915
|
+
const res = await setTodoListFunc(parsedArgs);
|
|
2916
|
+
return {
|
|
2917
|
+
content: JSON.stringify(res.rawData),
|
|
2918
|
+
metadata: { displayData: res.displayData }
|
|
2919
|
+
};
|
|
2920
|
+
},
|
|
3171
2921
|
...args.pastedTextStore ? { readPastedText: createReadPastedTextExecutor(args.pastedTextStore) } : {},
|
|
3172
2922
|
...args.localToolExecutors ?? {}
|
|
3173
2923
|
};
|
|
@@ -3297,12 +3047,15 @@ function convertOpenAiMessagesToGemini(messages, options) {
|
|
|
3297
3047
|
}
|
|
3298
3048
|
if (role === "assistant") {
|
|
3299
3049
|
flushPendingFunctionCalls();
|
|
3300
|
-
const parts = [];
|
|
3301
3050
|
const text = messageText(
|
|
3302
3051
|
content
|
|
3303
3052
|
);
|
|
3304
|
-
if (text) parts.push({ text });
|
|
3305
3053
|
const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
|
|
3054
|
+
if (text) pushOrMergeContent("model", [{ text }]);
|
|
3055
|
+
if (toolCalls.length > 0 && contents.length > 0 && contents[contents.length - 1]?.role !== "user") {
|
|
3056
|
+
contents.push({ role: "user", parts: [{ text: "" }] });
|
|
3057
|
+
}
|
|
3058
|
+
const parts = [];
|
|
3306
3059
|
for (const call of toolCalls) {
|
|
3307
3060
|
const name = call?.function?.name?.trim();
|
|
3308
3061
|
if (!name) continue;
|
|
@@ -3330,15 +3083,11 @@ function convertOpenAiMessagesToGemini(messages, options) {
|
|
|
3330
3083
|
if (role === "tool") {
|
|
3331
3084
|
const toolCallId = "tool_call_id" in raw && typeof raw.tool_call_id === "string" ? raw.tool_call_id : "";
|
|
3332
3085
|
const rawName = "name" in raw && typeof raw.name === "string" ? raw.name.trim() : "";
|
|
3333
|
-
const name = toolNamesById.get(toolCallId) || rawName || pendingFunctionCalls[0]?.name || "tool";
|
|
3334
3086
|
const pendingIndex = pendingFunctionCalls.findIndex(
|
|
3335
|
-
(p) => toolCallId ? p.id === toolCallId : p.name ===
|
|
3087
|
+
(p) => toolCallId ? p.id === toolCallId : rawName ? p.name === rawName : true
|
|
3336
3088
|
);
|
|
3337
|
-
if (pendingIndex
|
|
3338
|
-
|
|
3339
|
-
} else if (pendingFunctionCalls.length > 0) {
|
|
3340
|
-
pendingFunctionCalls.shift();
|
|
3341
|
-
}
|
|
3089
|
+
if (pendingIndex === -1) continue;
|
|
3090
|
+
const [{ name, id }] = pendingFunctionCalls.splice(pendingIndex, 1);
|
|
3342
3091
|
const output = messageText(content) || "{}";
|
|
3343
3092
|
pushOrMergeContent("user", [
|
|
3344
3093
|
{
|
|
@@ -3349,7 +3098,7 @@ function convertOpenAiMessagesToGemini(messages, options) {
|
|
|
3349
3098
|
// Gemini contents 转成 Claude messages 时需要 functionResponse →
|
|
3350
3099
|
// tool_result 的 tool_use_id;缺 id 时网关报
|
|
3351
3100
|
// "tool_result.tool_use_id: Field required"(HTTP 400)。
|
|
3352
|
-
...
|
|
3101
|
+
...id ? { id } : {}
|
|
3353
3102
|
}
|
|
3354
3103
|
}
|
|
3355
3104
|
]);
|
|
@@ -10076,13 +9825,25 @@ function stablePromptCacheKey(parts) {
|
|
|
10076
9825
|
}
|
|
10077
9826
|
return `nolo-codex-${hash.toString(16).padStart(8, "0")}`;
|
|
10078
9827
|
}
|
|
9828
|
+
function convertMessagesToCodexInput(messages) {
|
|
9829
|
+
return convertMessagesToResponsesInput(messages).map((item) => {
|
|
9830
|
+
if (item.type !== "reasoning") return item;
|
|
9831
|
+
return {
|
|
9832
|
+
type: "reasoning",
|
|
9833
|
+
summary: item.content.map((part) => ({
|
|
9834
|
+
type: "summary_text",
|
|
9835
|
+
text: part.text
|
|
9836
|
+
}))
|
|
9837
|
+
};
|
|
9838
|
+
});
|
|
9839
|
+
}
|
|
10079
9840
|
function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
|
|
10080
9841
|
const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
|
|
10081
9842
|
const nonSystem = rawMessages.filter((m) => {
|
|
10082
9843
|
const role = m && typeof m === "object" ? String(m.role) : "";
|
|
10083
9844
|
return role !== "system" && role !== "developer";
|
|
10084
9845
|
});
|
|
10085
|
-
const input =
|
|
9846
|
+
const input = convertMessagesToCodexInput(nonSystem);
|
|
10086
9847
|
const instructions = collectInstructions(rawMessages, args.agentConfig.prompt);
|
|
10087
9848
|
const stableInstructions = collectStableInstructions(rawMessages, args.agentConfig.prompt);
|
|
10088
9849
|
const model = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gpt-5.5";
|
|
@@ -10107,12 +9868,47 @@ function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
|
|
|
10107
9868
|
}
|
|
10108
9869
|
return body;
|
|
10109
9870
|
}
|
|
9871
|
+
function codexStreamFailureStatus(failure) {
|
|
9872
|
+
const marker = `${failure.code ?? ""} ${failure.type ?? ""}`.toLowerCase();
|
|
9873
|
+
if (marker.includes("overload") || marker.includes("service_unavailable")) return 503;
|
|
9874
|
+
if (marker.includes("rate_limit") || marker.includes("usage_limit")) return 429;
|
|
9875
|
+
return 502;
|
|
9876
|
+
}
|
|
9877
|
+
var RETRYABLE_CODEX_STREAM_STATUSES = /* @__PURE__ */ new Set([503]);
|
|
9878
|
+
var CODEX_STREAM_MAX_ATTEMPTS = 3;
|
|
9879
|
+
var CODEX_STREAM_RETRY_BASE_DELAY_MS = 500;
|
|
9880
|
+
function toStreamFailure(raw) {
|
|
9881
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
9882
|
+
const err = raw;
|
|
9883
|
+
const reason = typeof err.reason === "string" ? err.reason : void 0;
|
|
9884
|
+
const message = typeof err.message === "string" && err.message ? err.message : reason ? `Codex upstream ended incomplete: ${reason}.` : "";
|
|
9885
|
+
if (!message) return void 0;
|
|
9886
|
+
const code = typeof err.code === "string" ? err.code : reason;
|
|
9887
|
+
return {
|
|
9888
|
+
...code ? { code } : {},
|
|
9889
|
+
...typeof err.type === "string" ? { type: err.type } : {},
|
|
9890
|
+
message
|
|
9891
|
+
};
|
|
9892
|
+
}
|
|
10110
9893
|
function aggregateResponsesStream(events) {
|
|
10111
9894
|
let text = "";
|
|
10112
9895
|
const toolCalls = [];
|
|
10113
9896
|
let usage;
|
|
9897
|
+
let failure;
|
|
10114
9898
|
for (const ev of events) {
|
|
10115
9899
|
const type = String(ev.type ?? "");
|
|
9900
|
+
if (type === "error") {
|
|
9901
|
+
failure = failure ?? toStreamFailure(ev.error);
|
|
9902
|
+
continue;
|
|
9903
|
+
}
|
|
9904
|
+
if (type === "response.failed" || type === "response.incomplete") {
|
|
9905
|
+
const response = ev.response;
|
|
9906
|
+
failure = failure ?? toStreamFailure(response?.error) ?? toStreamFailure(response?.incomplete_details) ?? {
|
|
9907
|
+
code: type === "response.incomplete" ? "response_incomplete" : "response_failed",
|
|
9908
|
+
message: `Codex upstream ended with ${type}.`
|
|
9909
|
+
};
|
|
9910
|
+
continue;
|
|
9911
|
+
}
|
|
10116
9912
|
if (type === "response.output_text.delta" && typeof ev.delta === "string") {
|
|
10117
9913
|
text += ev.delta;
|
|
10118
9914
|
continue;
|
|
@@ -10149,7 +9945,7 @@ function aggregateResponsesStream(events) {
|
|
|
10149
9945
|
}
|
|
10150
9946
|
}
|
|
10151
9947
|
}
|
|
10152
|
-
return { text, toolCalls, usage };
|
|
9948
|
+
return { text, toolCalls, usage, failure };
|
|
10153
9949
|
}
|
|
10154
9950
|
async function readSseEvents(response) {
|
|
10155
9951
|
return readSseDataValues(response, (line) => {
|
|
@@ -10157,19 +9953,9 @@ async function readSseEvents(response) {
|
|
|
10157
9953
|
return ev && !Array.isArray(ev) ? ev : null;
|
|
10158
9954
|
});
|
|
10159
9955
|
}
|
|
10160
|
-
|
|
9956
|
+
var defaultSleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
9957
|
+
async function callCodexResponsesOnce(args, accountId) {
|
|
10161
9958
|
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
9959
|
const identity = createCodexRequestIdentity();
|
|
10174
9960
|
const body = buildCodexRequestBody(args, identity);
|
|
10175
9961
|
const headers = buildCodexCompatibilityHeaders(identity, accountId);
|
|
@@ -10188,7 +9974,19 @@ async function fetchCodexResponsesCompletion(args) {
|
|
|
10188
9974
|
};
|
|
10189
9975
|
}
|
|
10190
9976
|
const events = await readSseEvents(response);
|
|
10191
|
-
const { text, toolCalls, usage } = aggregateResponsesStream(events);
|
|
9977
|
+
const { text, toolCalls, usage, failure } = aggregateResponsesStream(events);
|
|
9978
|
+
if (failure) {
|
|
9979
|
+
return {
|
|
9980
|
+
status: codexStreamFailureStatus(failure),
|
|
9981
|
+
body: {
|
|
9982
|
+
error: {
|
|
9983
|
+
message: failure.message,
|
|
9984
|
+
...failure.code ? { code: failure.code } : {},
|
|
9985
|
+
...failure.type ? { type: failure.type } : {}
|
|
9986
|
+
}
|
|
9987
|
+
}
|
|
9988
|
+
};
|
|
9989
|
+
}
|
|
10192
9990
|
const message = {
|
|
10193
9991
|
role: "assistant",
|
|
10194
9992
|
content: text || null
|
|
@@ -10208,6 +10006,30 @@ async function fetchCodexResponsesCompletion(args) {
|
|
|
10208
10006
|
}
|
|
10209
10007
|
};
|
|
10210
10008
|
}
|
|
10009
|
+
async function fetchCodexResponsesCompletion(args) {
|
|
10010
|
+
const accountId = args.accountId?.trim() || decodeCodexAccountId(args.accessToken);
|
|
10011
|
+
if (!accountId) {
|
|
10012
|
+
return {
|
|
10013
|
+
status: 401,
|
|
10014
|
+
body: {
|
|
10015
|
+
error: {
|
|
10016
|
+
message: "ChatGPT Codex credential is missing chatgpt_account_id. Re-run `nolo auth chatgpt`."
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
};
|
|
10020
|
+
}
|
|
10021
|
+
const sleep = args.sleep ?? defaultSleep2;
|
|
10022
|
+
const requestedMaxAttempts = Number(args.maxAttempts);
|
|
10023
|
+
const maxAttempts = Number.isFinite(requestedMaxAttempts) ? Math.min(10, Math.max(1, Math.floor(requestedMaxAttempts))) : CODEX_STREAM_MAX_ATTEMPTS;
|
|
10024
|
+
let result = await callCodexResponsesOnce(args, accountId);
|
|
10025
|
+
for (let attempt = 1; attempt < maxAttempts; attempt += 1) {
|
|
10026
|
+
if (!RETRYABLE_CODEX_STREAM_STATUSES.has(result.status)) break;
|
|
10027
|
+
if (args.signal?.aborted) break;
|
|
10028
|
+
await sleep(CODEX_STREAM_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
|
|
10029
|
+
result = await callCodexResponsesOnce(args, accountId);
|
|
10030
|
+
}
|
|
10031
|
+
return result;
|
|
10032
|
+
}
|
|
10211
10033
|
function isCodexOAuthAgent(agentConfig) {
|
|
10212
10034
|
if (!agentConfig) return false;
|
|
10213
10035
|
const apiKeyRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
|
|
@@ -10302,313 +10124,15 @@ function createOAuthApiKeyRefResolver(options = {}) {
|
|
|
10302
10124
|
};
|
|
10303
10125
|
}
|
|
10304
10126
|
|
|
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))];
|
|
10127
|
+
// packages/cli/client/cliWorkspaceToolVariants.ts
|
|
10128
|
+
function shouldUseDeclaredOnlyLocalWorkspaceTools(env) {
|
|
10129
|
+
const value = env.NOLO_LOCAL_WORKSPACE_TOOLSET || env.NOLO_LOCAL_TOOLSET_MODE || "";
|
|
10130
|
+
return value === "declared-only" || value === "declared";
|
|
10313
10131
|
}
|
|
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
|
-
);
|
|
10132
|
+
function resolveGlobFilesDescriptionVariant(env) {
|
|
10133
|
+
return resolveLocalWorkspaceDescriptionVariant(
|
|
10134
|
+
env.NOLO_GLOBFILES_DESCRIPTION_VARIANT
|
|
10135
|
+
);
|
|
10612
10136
|
}
|
|
10613
10137
|
function resolveListFilesDescriptionVariant(env) {
|
|
10614
10138
|
return resolveLocalWorkspaceDescriptionVariant(
|
|
@@ -10652,61 +10176,10 @@ function resolveLocalWorkspaceParameterVariant(value) {
|
|
|
10652
10176
|
return value === "minimal" || value === "scoped" || value === "rich" ? value : "rich";
|
|
10653
10177
|
}
|
|
10654
10178
|
|
|
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
10179
|
// packages/cli/client/localRuntimeTools.ts
|
|
10706
10180
|
function buildOpenAiTools(args) {
|
|
10707
10181
|
const toolset = buildLocalWorkspaceToolsetForEnv(args);
|
|
10708
10182
|
const toolNameSet = new Set(args.toolNames ?? []);
|
|
10709
|
-
const callAgentTools = toolNameSet.has("callAgent") ? prepareTools(["callAgent"]) : [];
|
|
10710
10183
|
const uiAskChoiceTools = toolNameSet.has("ask_user") ? prepareTools(["ask_user"]) : [];
|
|
10711
10184
|
const readPastedTextTools = toolNameSet.has("readPastedText") ? [
|
|
10712
10185
|
{
|
|
@@ -10740,7 +10213,6 @@ function buildOpenAiTools(args) {
|
|
|
10740
10213
|
}
|
|
10741
10214
|
] : [];
|
|
10742
10215
|
return [
|
|
10743
|
-
...callAgentTools,
|
|
10744
10216
|
...uiAskChoiceTools,
|
|
10745
10217
|
...readPastedTextTools,
|
|
10746
10218
|
...buildLocalWorkspaceOpenAiTools({
|
|
@@ -10775,7 +10247,7 @@ function addDefaultCliCoreTools(toolNames, env, options) {
|
|
|
10775
10247
|
}
|
|
10776
10248
|
function resolveCliEffectiveEnabledPacks(args) {
|
|
10777
10249
|
return resolveEffectiveEnabledPacks({
|
|
10778
|
-
enabledPacks: args
|
|
10250
|
+
enabledPacks: resolveAgentRequiredPackIds(args),
|
|
10779
10251
|
declaredOnly: args.declaredOnly,
|
|
10780
10252
|
emptyFallbackPacks: ["code"]
|
|
10781
10253
|
});
|
|
@@ -10804,6 +10276,7 @@ function resolveCliRequestedToolNames(agentConfig, env, systemBuiltinSkills, opt
|
|
|
10804
10276
|
expandEnabledPacks(
|
|
10805
10277
|
resolveCliEffectiveEnabledPacks({
|
|
10806
10278
|
enabledPacks: agentConfig?.enabledPacks,
|
|
10279
|
+
skills: agentConfig?.skills,
|
|
10807
10280
|
declaredOnly
|
|
10808
10281
|
}),
|
|
10809
10282
|
resolveRequestedRuntimeToolNames({ agentConfig })
|
|
@@ -10822,10 +10295,11 @@ function resolveCliRequestedToolNames(agentConfig, env, systemBuiltinSkills, opt
|
|
|
10822
10295
|
declaredOnly ? expanded : addDefaultSystemCapabilityTools(expanded),
|
|
10823
10296
|
systemBuiltinSkills
|
|
10824
10297
|
);
|
|
10825
|
-
|
|
10298
|
+
const afterDisabled = applyDisabledTools(
|
|
10826
10299
|
filtered,
|
|
10827
10300
|
agentConfig?.disabledTools
|
|
10828
10301
|
);
|
|
10302
|
+
return filterToolNamesForRunKind(afterDisabled, isSubtaskRun(env));
|
|
10829
10303
|
}
|
|
10830
10304
|
function resolveProviderOpenAiToolBundle(agentConfig, env, buildTools = buildOpenAiTools, additionalToolNames = [], options) {
|
|
10831
10305
|
const requestedToolNames = [
|
|
@@ -10898,167 +10372,456 @@ function buildServerPlatformOpenAiTools(args) {
|
|
|
10898
10372
|
...webTools
|
|
10899
10373
|
];
|
|
10900
10374
|
}
|
|
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
|
-
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
10940
|
-
|
|
10941
|
-
|
|
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
|
-
|
|
10375
|
+
|
|
10376
|
+
// packages/cli/client/hybridRecordStore.ts
|
|
10377
|
+
function resolveFallbackServers(env) {
|
|
10378
|
+
const values = [
|
|
10379
|
+
env.NOLO_SERVER_URL,
|
|
10380
|
+
env.BASE_URL,
|
|
10381
|
+
...NOLO_CLUSTER_SERVERS
|
|
10382
|
+
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
10383
|
+
return [...new Set(values.map(normalizeServerOrigin))];
|
|
10384
|
+
}
|
|
10385
|
+
function resolveAuthToken(env) {
|
|
10386
|
+
return resolvePlatformAuthToken(env);
|
|
10387
|
+
}
|
|
10388
|
+
function createCliHybridRecordStore(deps) {
|
|
10389
|
+
return createHybridRecordStore({
|
|
10390
|
+
db: deps.db,
|
|
10391
|
+
defaultServer: normalizeServerOrigin(
|
|
10392
|
+
deps.env.NOLO_SERVER || deps.env.BASE_URL || DEFAULT_NOLO_SERVER_URL
|
|
10393
|
+
),
|
|
10394
|
+
fallbackServers: resolveFallbackServers(deps.env),
|
|
10395
|
+
authToken: resolveAuthToken(deps.env),
|
|
10396
|
+
fetchImpl: deps.fetchImpl
|
|
10397
|
+
});
|
|
10398
|
+
}
|
|
10399
|
+
|
|
10400
|
+
// packages/agent-runtime/dialogTitleLlm.ts
|
|
10401
|
+
async function generateLocalDialogTitle(input) {
|
|
10402
|
+
const { env, messages, fallbackTitle } = input;
|
|
10403
|
+
const timeoutMs = input.timeoutMs ?? 15e3;
|
|
10404
|
+
const normalized = messages.filter((m) => m.role === "user" || m.role === "assistant").map((m, index) => ({
|
|
10405
|
+
id: m.id || `msg-${index}`,
|
|
10406
|
+
role: m.role,
|
|
10407
|
+
content: typeof m.content === "string" ? m.content : extractText(m.content)
|
|
10408
|
+
})).filter((m) => Boolean(m.content.trim()));
|
|
10409
|
+
if (normalized.length === 0) {
|
|
10410
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10411
|
+
}
|
|
10412
|
+
const earlyUserTurns = normalized.filter((m) => m.role === "user").slice(0, 2);
|
|
10413
|
+
const recentTurns = normalized.slice(-10);
|
|
10414
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10415
|
+
const visibleMessages = [...earlyUserTurns, ...recentTurns].filter((m) => {
|
|
10416
|
+
if (seen.has(m.id)) return false;
|
|
10417
|
+
seen.add(m.id);
|
|
10418
|
+
return true;
|
|
10419
|
+
}).map((m) => {
|
|
10420
|
+
const content = m.content.length > 500 ? `${m.content.slice(0, 500)}...` : m.content;
|
|
10421
|
+
return { role: m.role, content };
|
|
10422
|
+
});
|
|
10423
|
+
while (visibleMessages.length > 1 && JSON.stringify(visibleMessages).length > 4e3) {
|
|
10424
|
+
visibleMessages.shift();
|
|
10425
|
+
}
|
|
10426
|
+
if (visibleMessages.length === 0) {
|
|
10427
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10428
|
+
}
|
|
10429
|
+
if (input.resolveProviderConfig && input.buildRequest && input.parseResponse) {
|
|
10430
|
+
try {
|
|
10431
|
+
const providerConfig = await input.resolveProviderConfig({
|
|
10432
|
+
agentConfig: { ...BUILTIN_TITLE_LLM_CONFIG, key: BUILTIN_TITLE_LLM_CONFIG.id },
|
|
10433
|
+
env
|
|
10434
|
+
});
|
|
10435
|
+
if (providerConfig?.authToken) {
|
|
10436
|
+
const request = input.buildRequest({
|
|
10437
|
+
providerConfig,
|
|
10438
|
+
messages: [
|
|
10439
|
+
{
|
|
10440
|
+
role: "user",
|
|
10441
|
+
content: JSON.stringify(visibleMessages)
|
|
10442
|
+
}
|
|
10443
|
+
],
|
|
10444
|
+
stream: false
|
|
10445
|
+
});
|
|
10446
|
+
const res = await input.fetchImpl(request.url, {
|
|
10447
|
+
...request.init,
|
|
10448
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
10449
|
+
});
|
|
10450
|
+
if (res.ok) {
|
|
10451
|
+
const raw = await res.text().catch(() => "");
|
|
10452
|
+
const data = safeParseJson(raw);
|
|
10453
|
+
if (data) {
|
|
10454
|
+
const parsed = input.parseResponse({ providerConfig, data });
|
|
10455
|
+
const generated = normalizeDialogTitle(parsed.content);
|
|
10456
|
+
if (generated) {
|
|
10457
|
+
return { title: generated, source: "llm" };
|
|
10458
|
+
}
|
|
10459
|
+
}
|
|
10460
|
+
}
|
|
10461
|
+
}
|
|
10462
|
+
} catch {
|
|
10463
|
+
}
|
|
10464
|
+
}
|
|
10465
|
+
if (input.resolveDirectProviderConfig) {
|
|
10466
|
+
try {
|
|
10467
|
+
const envApiKey = env.OPENAI_API_KEY || env.NOLO_LOCAL_OPENAI_API_KEY || "";
|
|
10468
|
+
const directAgentConfig = input.agentConfig && input.agentConfig.apiSource !== "platform" ? {
|
|
10469
|
+
...input.agentConfig,
|
|
10470
|
+
// Fill env key only when the caller's agentConfig has no key of
|
|
10471
|
+
// its own; never overwrite an explicit agentConfig.apiKey.
|
|
10472
|
+
...envApiKey && !input.agentConfig.apiKey ? { apiKey: envApiKey } : {}
|
|
10473
|
+
} : {
|
|
10474
|
+
...BUILTIN_TITLE_LLM_CONFIG,
|
|
10475
|
+
apiSource: "custom",
|
|
10476
|
+
useServerProxy: false,
|
|
10477
|
+
key: BUILTIN_TITLE_LLM_CONFIG.id,
|
|
10478
|
+
...envApiKey ? { apiKey: envApiKey } : {}
|
|
10479
|
+
};
|
|
10480
|
+
const directConfig = await input.resolveDirectProviderConfig({
|
|
10481
|
+
agentConfig: directAgentConfig,
|
|
10482
|
+
env
|
|
10483
|
+
});
|
|
10484
|
+
if (directConfig?.endpoint) {
|
|
10485
|
+
const apiKeyHeader = directConfig.apiKeyHeader || "Authorization";
|
|
10486
|
+
const apiKey = directConfig.apiKey || "";
|
|
10487
|
+
if (!apiKey && isRemoteAuthEndpoint(directConfig.endpoint)) {
|
|
10488
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10489
|
+
}
|
|
10490
|
+
const authValue = apiKeyHeader.toLowerCase() === "authorization" && apiKey && !apiKey.startsWith("Bearer ") ? `Bearer ${apiKey}` : apiKey;
|
|
10491
|
+
const headers = {
|
|
10492
|
+
"content-type": "application/json",
|
|
10493
|
+
...apiKey ? { [apiKeyHeader]: authValue } : {}
|
|
10494
|
+
};
|
|
10495
|
+
const res = await input.fetchImpl(directConfig.endpoint, {
|
|
10496
|
+
method: "POST",
|
|
10497
|
+
headers,
|
|
10498
|
+
body: JSON.stringify({
|
|
10499
|
+
model: directConfig.model || input.agentConfig?.model || BUILTIN_TITLE_LLM_CONFIG.model,
|
|
10500
|
+
messages: [
|
|
10501
|
+
{ role: "system", content: BUILTIN_TITLE_LLM_CONFIG.prompt },
|
|
10502
|
+
{ role: "user", content: JSON.stringify(visibleMessages) }
|
|
10503
|
+
],
|
|
10504
|
+
stream: false
|
|
10505
|
+
}),
|
|
10506
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
10507
|
+
});
|
|
10508
|
+
if (res.ok) {
|
|
10509
|
+
const raw = await res.text().catch(() => "");
|
|
10510
|
+
const data = safeParseJson(raw);
|
|
10511
|
+
const rawContent = data?.choices?.[0]?.message?.content ?? "";
|
|
10512
|
+
const generated = normalizeDialogTitle(rawContent);
|
|
10513
|
+
if (generated) {
|
|
10514
|
+
return { title: generated, source: "llm" };
|
|
10515
|
+
}
|
|
10516
|
+
}
|
|
10517
|
+
}
|
|
10518
|
+
} catch {
|
|
10519
|
+
}
|
|
10520
|
+
}
|
|
10521
|
+
return { title: fallbackTitle, source: "fallback" };
|
|
10522
|
+
}
|
|
10523
|
+
function extractText(content) {
|
|
10524
|
+
if (typeof content === "string") return content;
|
|
10525
|
+
if (Array.isArray(content)) {
|
|
10526
|
+
const parts = content.map((part) => {
|
|
10527
|
+
if (!part) return "";
|
|
10528
|
+
if (typeof part === "string") return part;
|
|
10529
|
+
if (part.type === "text") return part.text ?? "";
|
|
10530
|
+
return "[\u56FE\u7247]";
|
|
10531
|
+
}).filter(Boolean);
|
|
10532
|
+
return parts.join(" ");
|
|
10533
|
+
}
|
|
10534
|
+
if (content && typeof content === "object") {
|
|
10535
|
+
const part = content;
|
|
10536
|
+
if (part.type === "text") return part.text ?? "";
|
|
10537
|
+
return "[\u56FE\u7247]";
|
|
10538
|
+
}
|
|
10539
|
+
return "";
|
|
10540
|
+
}
|
|
10541
|
+
function safeParseJson(raw) {
|
|
10542
|
+
try {
|
|
10543
|
+
return JSON.parse(raw);
|
|
10544
|
+
} catch {
|
|
10545
|
+
return null;
|
|
10546
|
+
}
|
|
10547
|
+
}
|
|
10548
|
+
function isRemoteAuthEndpoint(endpoint) {
|
|
10549
|
+
let host;
|
|
10550
|
+
try {
|
|
10551
|
+
host = new URL(endpoint).hostname.toLowerCase();
|
|
10552
|
+
} catch {
|
|
10553
|
+
return false;
|
|
10554
|
+
}
|
|
10555
|
+
if (!host) return false;
|
|
10556
|
+
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)) {
|
|
10557
|
+
return false;
|
|
10558
|
+
}
|
|
10559
|
+
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") {
|
|
10560
|
+
return true;
|
|
10561
|
+
}
|
|
10562
|
+
return false;
|
|
10563
|
+
}
|
|
10564
|
+
|
|
10565
|
+
// packages/cli/client/localRuntimeDialog.ts
|
|
10566
|
+
async function resolveStore(deps) {
|
|
10567
|
+
if (deps.store) return deps.store;
|
|
10568
|
+
return createCliHybridRecordStore({
|
|
10569
|
+
db: deps.db ?? await defaultLocalRuntimeDb(),
|
|
10570
|
+
env: deps.env,
|
|
10571
|
+
fetchImpl: deps.fetchImpl
|
|
10572
|
+
});
|
|
10573
|
+
}
|
|
10574
|
+
async function getOrCreateSharedStore(deps) {
|
|
10575
|
+
if (deps.store) return deps.store;
|
|
10576
|
+
const cacheKey = normalizeRuntimeCacheCwd(deps.cwd);
|
|
10577
|
+
let storePromise = hybridStoreCache.get(cacheKey);
|
|
10578
|
+
if (!storePromise) {
|
|
10579
|
+
storePromise = resolveStore(deps);
|
|
10580
|
+
hybridStoreCache.set(cacheKey, storePromise);
|
|
10581
|
+
}
|
|
10582
|
+
return storePromise;
|
|
10583
|
+
}
|
|
10584
|
+
function createLocalDialogTitleGenerator(deps, ctx) {
|
|
10585
|
+
if (!canUsePlatformChatProvider(deps.env) && !hasDirectOpenAiCompatibleProvider(deps.env)) {
|
|
10586
|
+
return null;
|
|
10587
|
+
}
|
|
10588
|
+
return async (input) => {
|
|
10589
|
+
const result = await generateLocalDialogTitle({
|
|
10590
|
+
messages: input.messages,
|
|
10591
|
+
env: deps.env,
|
|
10592
|
+
fetchImpl: async (url, init) => fetchWithTransientRetry(
|
|
10593
|
+
deps.fetchImpl ?? fetch,
|
|
10594
|
+
url,
|
|
10595
|
+
init,
|
|
10596
|
+
{
|
|
10597
|
+
sleep: deps.sleep,
|
|
10598
|
+
loopbackRequest: ctx.loopbackRequest,
|
|
10599
|
+
maxAttempts: 1
|
|
10600
|
+
}
|
|
10601
|
+
),
|
|
10602
|
+
resolveProviderConfig: async (args) => resolvePlatformChatProviderConfig({
|
|
10603
|
+
agentConfig: args.agentConfig,
|
|
10604
|
+
env: args.env,
|
|
10605
|
+
apiKeyRefResolver: ctx.apiKeyRefResolver,
|
|
10606
|
+
credentialBroker: ctx.credentialBroker
|
|
10607
|
+
}),
|
|
10608
|
+
resolveDirectProviderConfig: async (args) => resolveOpenAiCompatibleProviderConfig({
|
|
10609
|
+
agentConfig: args.agentConfig,
|
|
10610
|
+
env: args.env,
|
|
10611
|
+
apiKeyRefResolver: ctx.apiKeyRefResolver,
|
|
10612
|
+
credentialBroker: ctx.credentialBroker
|
|
10613
|
+
}),
|
|
10614
|
+
buildRequest: (args) => buildPlatformChatCompletionRequest({
|
|
10615
|
+
providerConfig: args.providerConfig,
|
|
10616
|
+
messages: args.messages,
|
|
10617
|
+
stream: false
|
|
10618
|
+
}),
|
|
10619
|
+
parseResponse: (args) => parsePlatformChatCompletionResponse({
|
|
10620
|
+
providerConfig: args.providerConfig,
|
|
10621
|
+
data: args.data,
|
|
10622
|
+
trace: []
|
|
10623
|
+
}),
|
|
10624
|
+
fallbackTitle: input.fallbackTitle,
|
|
10625
|
+
timeoutMs: 4e3
|
|
10967
10626
|
});
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10627
|
+
return result.source === "llm" ? result.title : null;
|
|
10628
|
+
};
|
|
10629
|
+
}
|
|
10630
|
+
async function writeLocalTokenRecord(args) {
|
|
10631
|
+
const usageRecords = args.input.usageRecords?.length ? args.input.usageRecords : args.input.result.usage ? [{
|
|
10632
|
+
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(),
|
|
10633
|
+
usage: args.input.result.usage,
|
|
10634
|
+
model: args.input.result.model,
|
|
10635
|
+
...args.input.result.provider ? { provider: args.input.result.provider } : {}
|
|
10636
|
+
}] : [];
|
|
10637
|
+
if (usageRecords.length === 0) {
|
|
10638
|
+
return [];
|
|
10639
|
+
}
|
|
10640
|
+
const ops = [];
|
|
10641
|
+
for (const item of usageRecords) {
|
|
10642
|
+
if (!item.usage || Object.keys(item.usage).length === 0) continue;
|
|
10643
|
+
const timestamp = args.now();
|
|
10644
|
+
const callId = item.callId || typeof item.usage.provider_call_id === "string" && item.usage.provider_call_id.trim() || args.createId();
|
|
10645
|
+
const prepared = prepareTokenUsageData({
|
|
10646
|
+
rawUsage: item.usage,
|
|
10647
|
+
agentConfig: {
|
|
10648
|
+
model: item.model || args.input.billingConfig?.model || "unknown",
|
|
10649
|
+
provider: item.provider || args.input.billingConfig?.provider,
|
|
10650
|
+
apiSource: args.input.billingConfig?.apiSource,
|
|
10651
|
+
apiKeyRef: args.input.billingConfig?.apiKeyRef,
|
|
10652
|
+
inputPrice: args.input.billingConfig?.inputPrice,
|
|
10653
|
+
outputPrice: args.input.billingConfig?.outputPrice,
|
|
10654
|
+
sharingLevel: args.input.billingConfig?.sharingLevel,
|
|
10655
|
+
id: args.input.billingConfig?.id,
|
|
10656
|
+
userId: args.input.billingConfig?.userId
|
|
10657
|
+
},
|
|
10658
|
+
userId: args.userId,
|
|
10659
|
+
agentId: args.input.agentKey,
|
|
10660
|
+
dialogId: args.dialogId,
|
|
10661
|
+
timestamp,
|
|
10662
|
+
entry_path: "cli-local"
|
|
10972
10663
|
});
|
|
10973
|
-
const
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
spaceId: ctx.spaceId,
|
|
10979
|
-
continueDialogId: childDialogId,
|
|
10980
|
-
parentDialogId
|
|
10664
|
+
const recordKey = createTokenKey.recordForStableCall(args.userId, callId);
|
|
10665
|
+
const tokenRecord = {
|
|
10666
|
+
id: args.createId(),
|
|
10667
|
+
type: "token",
|
|
10668
|
+
...prepared.tokenData
|
|
10981
10669
|
};
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10670
|
+
await args.store.write(recordKey, tokenRecord);
|
|
10671
|
+
ops.push({ type: "put", key: recordKey, value: tokenRecord });
|
|
10672
|
+
}
|
|
10673
|
+
return ops;
|
|
10674
|
+
}
|
|
10675
|
+
async function writeDialog(args) {
|
|
10676
|
+
let existingDialog = null;
|
|
10677
|
+
if (args.input.continueDialogId) {
|
|
10678
|
+
const dialogKey = `dialog-${args.userId}-${args.input.continueDialogId}`;
|
|
10679
|
+
existingDialog = await args.store.read(dialogKey);
|
|
10680
|
+
}
|
|
10681
|
+
const nowMs = args.now();
|
|
10682
|
+
const existingTitle = typeof existingDialog?.title === "string" ? existingDialog.title.trim() : "";
|
|
10683
|
+
const existingTitleSource = existingDialog?.titleSource;
|
|
10684
|
+
const titleTimeoutMs = args.titleTimeoutMs ?? 2500;
|
|
10685
|
+
let needsTitleUpdate = false;
|
|
10686
|
+
if (existingTitleSource === "manual") {
|
|
10687
|
+
needsTitleUpdate = false;
|
|
10688
|
+
} else if (!existingTitle) {
|
|
10689
|
+
needsTitleUpdate = true;
|
|
10690
|
+
} else {
|
|
10691
|
+
const titleUpdatedAtMs = parseTitleUpdatedAtMs(existingDialog);
|
|
10692
|
+
if (titleUpdatedAtMs > 0) {
|
|
10693
|
+
if (nowMs - titleUpdatedAtMs >= 30 * 60 * 1e3) {
|
|
10694
|
+
needsTitleUpdate = true;
|
|
10695
|
+
}
|
|
10696
|
+
} else {
|
|
10697
|
+
needsTitleUpdate = false;
|
|
10698
|
+
}
|
|
10699
|
+
}
|
|
10700
|
+
let titlePromise;
|
|
10701
|
+
if (needsTitleUpdate && args.titleGenerator) {
|
|
10702
|
+
const rawLastUserText = extractLastUserText(args.input.messages);
|
|
10703
|
+
const fallbackTitle = buildDialogFallbackTitleFromUserInput(rawLastUserText) || "Local agent run";
|
|
10704
|
+
titlePromise = args.titleGenerator({ messages: args.input.messages, fallbackTitle }).catch(() => null);
|
|
10705
|
+
}
|
|
10706
|
+
let resolvedTitle = null;
|
|
10707
|
+
if (titlePromise) {
|
|
10708
|
+
let timeoutId;
|
|
10709
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
10710
|
+
timeoutId = setTimeout(() => resolve(null), titleTimeoutMs);
|
|
10711
|
+
});
|
|
10712
|
+
try {
|
|
10713
|
+
resolvedTitle = await Promise.race([titlePromise, timeoutPromise]);
|
|
10714
|
+
} catch {
|
|
10715
|
+
resolvedTitle = null;
|
|
10716
|
+
} finally {
|
|
10717
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
10718
|
+
}
|
|
10719
|
+
}
|
|
10720
|
+
const plan = buildLocalDialogWritePlan({
|
|
10721
|
+
input: args.input,
|
|
10722
|
+
userId: args.userId,
|
|
10723
|
+
now: nowMs,
|
|
10724
|
+
createId: args.createId,
|
|
10725
|
+
existingDialog,
|
|
10726
|
+
cwd: args.cwd,
|
|
10727
|
+
...resolvedTitle ? { titleOverride: resolvedTitle } : {}
|
|
10728
|
+
});
|
|
10729
|
+
await args.store.batch(plan.ops);
|
|
10730
|
+
let tokenOps = [];
|
|
10731
|
+
try {
|
|
10732
|
+
tokenOps = await writeLocalTokenRecord({
|
|
10733
|
+
store: args.store,
|
|
10734
|
+
input: args.input,
|
|
10735
|
+
userId: args.userId,
|
|
10736
|
+
dialogId: plan.dialogId,
|
|
10737
|
+
now: args.now,
|
|
10738
|
+
createId: args.createId,
|
|
10739
|
+
output: args.output
|
|
10740
|
+
});
|
|
10741
|
+
} catch (error) {
|
|
10742
|
+
args.output?.write(
|
|
10743
|
+
`[nolo] Token usage record write failed (non-fatal): ${toErrorMessage(error)}
|
|
10998
10744
|
`
|
|
10745
|
+
);
|
|
10746
|
+
}
|
|
10747
|
+
const hasSubjectRefs = localTurnHasSubjectRefs(args.input);
|
|
10748
|
+
const isLocalUser = args.userId === "local";
|
|
10749
|
+
if (!isLocalUser) {
|
|
10750
|
+
try {
|
|
10751
|
+
const syncResult = await syncLocalDialogEvidenceToRemote({
|
|
10752
|
+
env: args.env,
|
|
10753
|
+
fetchImpl: args.fetchImpl,
|
|
10754
|
+
input: args.input,
|
|
10755
|
+
ops: [...plan.ops, ...tokenOps],
|
|
10756
|
+
output: args.output,
|
|
10757
|
+
userId: args.userId
|
|
10758
|
+
});
|
|
10759
|
+
if (!syncResult.attempted) {
|
|
10760
|
+
if (hasSubjectRefs) {
|
|
10761
|
+
args.output?.write(
|
|
10762
|
+
"[nolo] Local dialog evidence is local-only; set NOLO_SERVER and AUTH_TOKEN to make subjectRefs remotely queryable.\n"
|
|
10999
10763
|
);
|
|
11000
10764
|
}
|
|
11001
|
-
}
|
|
11002
|
-
return {
|
|
11003
|
-
content: JSON.stringify({
|
|
11004
|
-
success: true,
|
|
11005
|
-
status: "pending",
|
|
11006
|
-
agentKey,
|
|
11007
|
-
childDialogId,
|
|
11008
|
-
...parentDialogId ? { parentDialogId } : {}
|
|
11009
|
-
}),
|
|
11010
|
-
metadata: { callAgent: true, background: true, localRuntime: true }
|
|
11011
|
-
};
|
|
11012
|
-
}
|
|
11013
|
-
try {
|
|
11014
|
-
const childResult = await ctx.runChildTurn(childInputBase);
|
|
11015
|
-
return {
|
|
11016
|
-
content: JSON.stringify({
|
|
11017
|
-
success: true,
|
|
11018
|
-
agentKey,
|
|
11019
|
-
dialogId: childDialogId,
|
|
11020
|
-
model: childResult.model ?? null,
|
|
11021
|
-
provider: childResult.provider ?? null,
|
|
11022
|
-
content: childResult.content ?? "",
|
|
11023
|
-
usage: childResult.usage ?? null
|
|
11024
|
-
}),
|
|
11025
|
-
metadata: { callAgent: true, background: false, localRuntime: true }
|
|
11026
|
-
};
|
|
10765
|
+
}
|
|
11027
10766
|
} catch (error) {
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
await persistCliFailedChildDialog({
|
|
11031
|
-
store,
|
|
11032
|
-
userId,
|
|
11033
|
-
dialogId: childDialogId,
|
|
11034
|
-
errorMessage,
|
|
11035
|
-
now: now()
|
|
11036
|
-
});
|
|
11037
|
-
} catch (persistError) {
|
|
11038
|
-
deps.output?.write(
|
|
11039
|
-
`[nolo] failed to persist foreground child failure: ${toErrorMessage(
|
|
11040
|
-
persistError
|
|
11041
|
-
)}
|
|
11042
|
-
`
|
|
11043
|
-
);
|
|
10767
|
+
if (hasSubjectRefs) {
|
|
10768
|
+
throw error;
|
|
11044
10769
|
}
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
}),
|
|
11052
|
-
metadata: {
|
|
11053
|
-
callAgent: true,
|
|
11054
|
-
background: false,
|
|
11055
|
-
localRuntime: true,
|
|
11056
|
-
error: true
|
|
11057
|
-
}
|
|
11058
|
-
};
|
|
10770
|
+
args.output?.write(
|
|
10771
|
+
`[nolo] Remote dialog evidence sync failed; local dialog only: ${toErrorMessage(
|
|
10772
|
+
error
|
|
10773
|
+
)}
|
|
10774
|
+
`
|
|
10775
|
+
);
|
|
11059
10776
|
}
|
|
10777
|
+
}
|
|
10778
|
+
return { dialogId: plan.dialogId, title: plan.title };
|
|
10779
|
+
}
|
|
10780
|
+
function resolveCliDialogRecordKey(userId, dialogId) {
|
|
10781
|
+
if (dialogId.startsWith("dialog-") && !dialogId.includes("-msg-")) {
|
|
10782
|
+
return dialogId;
|
|
10783
|
+
}
|
|
10784
|
+
return `dialog-${userId}-${dialogId}`;
|
|
10785
|
+
}
|
|
10786
|
+
async function loadCliDialogSummary(args) {
|
|
10787
|
+
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10788
|
+
const record = await args.store.read(dialogKey);
|
|
10789
|
+
if (!record || typeof record !== "object") return null;
|
|
10790
|
+
const summary = typeof record.summary === "string" ? record.summary.trim() : "";
|
|
10791
|
+
if (!summary) return null;
|
|
10792
|
+
const summarizedBeforeId = record.summarizedBeforeId;
|
|
10793
|
+
return {
|
|
10794
|
+
summary,
|
|
10795
|
+
...typeof summarizedBeforeId === "string" && summarizedBeforeId ? { summarizedBeforeId } : {}
|
|
11060
10796
|
};
|
|
11061
10797
|
}
|
|
10798
|
+
async function saveCliDialogSummary(args) {
|
|
10799
|
+
const dialogKey = resolveCliDialogRecordKey(args.userId, args.dialogId);
|
|
10800
|
+
const existing = await args.store.read(dialogKey) ?? {};
|
|
10801
|
+
const bareId = typeof existing.id === "string" && existing.id ? existing.id : args.dialogId.startsWith("dialog-") ? args.dialogId.slice(args.dialogId.lastIndexOf("-") + 1) : args.dialogId;
|
|
10802
|
+
const compressionCount = typeof existing.compressionCount === "number" ? existing.compressionCount + 1 : 1;
|
|
10803
|
+
await args.store.write(dialogKey, {
|
|
10804
|
+
...existing,
|
|
10805
|
+
id: bareId,
|
|
10806
|
+
dbKey: dialogKey,
|
|
10807
|
+
type: "dialog",
|
|
10808
|
+
userId: args.userId,
|
|
10809
|
+
summary: args.summary,
|
|
10810
|
+
...args.summarizedBeforeId !== void 0 ? { summarizedBeforeId: args.summarizedBeforeId } : {},
|
|
10811
|
+
compressionCount,
|
|
10812
|
+
summaryPending: false,
|
|
10813
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10814
|
+
});
|
|
10815
|
+
}
|
|
10816
|
+
function parseTitleUpdatedAtMs(existingDialog) {
|
|
10817
|
+
const raw = existingDialog?.titleUpdatedAt;
|
|
10818
|
+
if (typeof raw === "number" && !Number.isNaN(raw)) return raw;
|
|
10819
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
10820
|
+
const parsed = Date.parse(raw);
|
|
10821
|
+
if (!Number.isNaN(parsed)) return parsed;
|
|
10822
|
+
}
|
|
10823
|
+
return 0;
|
|
10824
|
+
}
|
|
11062
10825
|
|
|
11063
10826
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
11064
10827
|
var currentMetaFile = fileURLToPath(import.meta.url);
|
|
@@ -11260,7 +11023,20 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11260
11023
|
const credentialBroker = createFileCredentialBroker();
|
|
11261
11024
|
const serverUrl = asOptionalTrimmedString(deps.env.NOLO_SERVER) ?? "https://us.nolo.chat";
|
|
11262
11025
|
const authToken = asOptionalTrimmedString(deps.env.AUTH_TOKEN);
|
|
11263
|
-
const syncFetcher = authToken ? (ref) =>
|
|
11026
|
+
const syncFetcher = authToken ? async (ref) => {
|
|
11027
|
+
try {
|
|
11028
|
+
return await fetchServerSyncedCredential(
|
|
11029
|
+
{ currentServer: serverUrl, authToken },
|
|
11030
|
+
ref
|
|
11031
|
+
);
|
|
11032
|
+
} catch (error) {
|
|
11033
|
+
logLocalRuntimeDiagnostic("credential.sync.unavailable", {
|
|
11034
|
+
ref,
|
|
11035
|
+
error: toErrorMessage(error)
|
|
11036
|
+
});
|
|
11037
|
+
return null;
|
|
11038
|
+
}
|
|
11039
|
+
} : void 0;
|
|
11264
11040
|
if (isAntigravityOAuthAgent(agentConfig)) {
|
|
11265
11041
|
const accessToken = await apiKeyRefResolver("antigravity");
|
|
11266
11042
|
if (!accessToken) {
|
|
@@ -11474,6 +11250,14 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11474
11250
|
return {
|
|
11475
11251
|
content,
|
|
11476
11252
|
...tool_calls ? { tool_calls } : {},
|
|
11253
|
+
// fetchCodexResponsesCompletion 已把 codex responses 流聚合完毕并归一化成
|
|
11254
|
+
// OpenAI chat.completions 形状:choices[0].finish_reason("stop"/"tool_calls")
|
|
11255
|
+
// + usage(prompt/completion/total_tokens)。必须透传,否则 localLoop 把正常走完
|
|
11256
|
+
// 的空轮误判成 stream_truncated、TUI context chip 也拿不到 token 数更新。
|
|
11257
|
+
finish_reason: typeof choice?.finish_reason === "string" ? choice.finish_reason : void 0,
|
|
11258
|
+
stream_complete: true,
|
|
11259
|
+
// body 类型是 Record<string, unknown>,透传 usage 需 cast 到 AgentRuntimeResult.usage。
|
|
11260
|
+
usage: result.body?.usage,
|
|
11477
11261
|
trace: messages
|
|
11478
11262
|
};
|
|
11479
11263
|
}
|
|
@@ -11923,9 +11707,7 @@ export {
|
|
|
11923
11707
|
t,
|
|
11924
11708
|
toolLabel,
|
|
11925
11709
|
agentRunCardLabels,
|
|
11926
|
-
QUOTA_ERROR_PATTERNS,
|
|
11927
|
-
isQuotaExhaustedError,
|
|
11928
11710
|
clearCliLocalRuntimePreparedAgentCache,
|
|
11929
|
-
|
|
11711
|
+
isSubtaskRun,
|
|
11930
11712
|
createCliLocalRuntimeAdapter
|
|
11931
11713
|
};
|