nolo-cli 0.8.0-alpha.2 → 0.8.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +1 -1
  2. package/_executeModel-42U3VOVZ.js +205 -0
  3. package/action-TLI3V62L.js +28 -0
  4. package/addContentAction-57RSIIMR.js +26 -0
  5. package/addDialogAgentAction-G3VWEA6E.js +68 -0
  6. package/agentDeleteCommand-5DD2IM3J.js +327 -0
  7. package/agentEmailCommands-6FACJBU4.js +628 -0
  8. package/agentListCommands-I6KZYCIG.js +223 -0
  9. package/agentMachineCommands-VKLIGMZA.js +425 -0
  10. package/agentPullCommand-O2MTUAFR.js +122 -0
  11. package/agentRecordCommands-7TZICYDT.js +96 -0
  12. package/agentRunCommand-L4OM23KV.js +114 -0
  13. package/agentRunControl-K4VKNEHF.js +57 -0
  14. package/agentRuntimeLocal-ZYEIPTY4.js +104 -0
  15. package/agentSlice-BX7GXSNO.js +42 -0
  16. package/authCommand-EB5JSOX5.js +581 -0
  17. package/authCommands-XPEHTKSM.js +35 -0
  18. package/chunk-25LCXTML.js +175 -0
  19. package/chunk-2ECQG4YX.js +22296 -0
  20. package/chunk-2FTTDCD4.js +675 -0
  21. package/chunk-2JCXITPK.js +1078 -0
  22. package/chunk-3ASDTTEI.js +1774 -0
  23. package/chunk-3EUW3WEO.js +8 -0
  24. package/chunk-3LY4F7SV.js +9293 -0
  25. package/chunk-4CQLVGRV.js +50 -0
  26. package/chunk-4IJYA27C.js +342 -0
  27. package/chunk-4O3CARJ4.js +231 -0
  28. package/chunk-4QEWT7KD.js +933 -0
  29. package/chunk-4SN6J65J.js +38 -0
  30. package/chunk-4VNS5WPM.js +42 -0
  31. package/chunk-4XENYTF5.js +222 -0
  32. package/chunk-4ZDM73SD.js +34 -0
  33. package/chunk-5CS33IBL.js +301 -0
  34. package/chunk-5EFXE3O7.js +138 -0
  35. package/chunk-5KLGBAAR.js +386 -0
  36. package/chunk-5MIDPSSK.js +206 -0
  37. package/chunk-5MMAK75Q.js +15 -0
  38. package/chunk-63W5N6P3.js +150 -0
  39. package/chunk-6HYVJV7B.js +102 -0
  40. package/chunk-6KHNO3SK.js +1948 -0
  41. package/chunk-6WD3OOJS.js +20 -0
  42. package/chunk-7DAJ4AI4.js +191 -0
  43. package/chunk-7GNGZRLZ.js +1939 -0
  44. package/chunk-7KCUSYT2.js +354 -0
  45. package/chunk-7U44LYTR.js +238 -0
  46. package/chunk-AFON4QUU.js +112 -0
  47. package/chunk-AGFH73SK.js +239 -0
  48. package/chunk-AL2KDGR2.js +27339 -0
  49. package/chunk-AS4PVWA4.js +221 -0
  50. package/chunk-ATNTHIZI.js +13 -0
  51. package/chunk-AVMKZHBC.js +85 -0
  52. package/chunk-AZPCASRE.js +36 -0
  53. package/chunk-BBYVOSU2.js +792 -0
  54. package/chunk-C3RUNRHT.js +51 -0
  55. package/chunk-C4FTUXVF.js +146 -0
  56. package/chunk-CF2WZF4N.js +134 -0
  57. package/chunk-CF7PE763.js +10 -0
  58. package/chunk-CKOJQDKR.js +198 -0
  59. package/chunk-CMKUBIGW.js +1550 -0
  60. package/chunk-CWMSB67P.js +34 -0
  61. package/chunk-DCOA4QSN.js +105 -0
  62. package/chunk-DFFIZ25G.js +30 -0
  63. package/chunk-DSZUWUYB.js +478 -0
  64. package/chunk-DWLEOOGR.js +8 -0
  65. package/chunk-DZ3XJVET.js +231 -0
  66. package/chunk-EHLHSX7R.js +1433 -0
  67. package/chunk-ENOG22KJ.js +939 -0
  68. package/chunk-FSO5B7GH.js +171 -0
  69. package/chunk-FVYY6MCS.js +1447 -0
  70. package/chunk-G3SUCT4W.js +8 -0
  71. package/chunk-GAKEBQD6.js +30 -0
  72. package/chunk-GBRG75BQ.js +86 -0
  73. package/chunk-GU3PEVGZ.js +4723 -0
  74. package/chunk-H33743XH.js +25 -0
  75. package/chunk-HNMXYYJR.js +12 -0
  76. package/chunk-HNW7IJSK.js +71 -0
  77. package/chunk-I42VC5KR.js +15 -0
  78. package/chunk-I6XMPTMR.js +113 -0
  79. package/chunk-IDZTNRP2.js +85 -0
  80. package/chunk-ISNCLGUZ.js +146 -0
  81. package/chunk-IWX4UW2E.js +548 -0
  82. package/chunk-JBTJAPUF.js +35 -0
  83. package/chunk-JEXVIMYZ.js +55 -0
  84. package/chunk-JRKKFRAV.js +537 -0
  85. package/chunk-JZPBVBIY.js +94 -0
  86. package/chunk-KKY4B2Q2.js +21 -0
  87. package/chunk-KQHGZWSV.js +63 -0
  88. package/chunk-KUG52IAP.js +8 -0
  89. package/chunk-KX6YBIHG.js +8 -0
  90. package/chunk-LCBAMY2M.js +60 -0
  91. package/chunk-LM6IYQ3F.js +16 -0
  92. package/chunk-LTRXGFMS.js +83 -0
  93. package/chunk-M76ECQRD.js +13658 -0
  94. package/chunk-MRC4Q34M.js +188 -0
  95. package/chunk-MTU75CZ2.js +91 -0
  96. package/chunk-N54XAP77.js +19 -0
  97. package/chunk-O2ZNTTET.js +3272 -0
  98. package/chunk-O4BU24WZ.js +3212 -0
  99. package/chunk-OLZBQWZU.js +6 -0
  100. package/chunk-OOSFSFMA.js +271 -0
  101. package/chunk-OPZYGHUC.js +89 -0
  102. package/chunk-OWOHNGCN.js +50 -0
  103. package/chunk-P3PKED2I.js +962 -0
  104. package/chunk-QSJ3HFEF.js +8 -0
  105. package/chunk-RCSJFQPB.js +9036 -0
  106. package/chunk-RL776AGR.js +190 -0
  107. package/chunk-ROWQEJRP.js +139 -0
  108. package/chunk-S7Z2HMCN.js +25 -0
  109. package/chunk-SDJDLO5W.js +628 -0
  110. package/chunk-SOTZ6RDN.js +69 -0
  111. package/chunk-TILFE6LV.js +381 -0
  112. package/chunk-U4TRT5V4.js +246 -0
  113. package/chunk-U6VC4MU4.js +8 -0
  114. package/chunk-UAD2WT54.js +64 -0
  115. package/chunk-UB6SN4NJ.js +421 -0
  116. package/chunk-URUUZLPA.js +807 -0
  117. package/chunk-UTLZINAP.js +3066 -0
  118. package/chunk-VC6OZXO5.js +298 -0
  119. package/chunk-VF4K2QE6.js +21 -0
  120. package/chunk-VHBWHNVT.js +59 -0
  121. package/chunk-VIDPVFP3.js +20 -0
  122. package/chunk-VP4WJWKW.js +8882 -0
  123. package/chunk-VUW5FBDB.js +573 -0
  124. package/chunk-VVX233PH.js +482 -0
  125. package/chunk-VX3SXJ3N.js +2052 -0
  126. package/chunk-W4NVOSFF.js +37 -0
  127. package/chunk-WWC7I6TA.js +8 -0
  128. package/chunk-WZSRQNQG.js +2587 -0
  129. package/chunk-XBUBEFNX.js +34 -0
  130. package/chunk-XENYHRUE.js +104 -0
  131. package/chunk-Y5GCAMGP.js +9 -0
  132. package/chunk-YPRZSPF3.js +148 -0
  133. package/chunk-Z4NR32XR.js +50 -0
  134. package/chunk-ZNFJWEN4.js +56 -0
  135. package/cliExecutor-K3F7DMRO.js +36 -0
  136. package/clipboardy-BVE3LVEH.js +12001 -0
  137. package/createAgentAutomationAction-RJF3N2QY.js +866 -0
  138. package/createDialogAction-DRSPS6CE.js +55 -0
  139. package/createPageAction-6B2WMNO3.js +172 -0
  140. package/db-HCJ5PRB5.js +271 -0
  141. package/dbSlice-Q3TM2FJV.js +60 -0
  142. package/deleteFile-OW53A6BX.js +41 -0
  143. package/dialogCommands-4IX4XIZE.js +63 -0
  144. package/dialogSlice-3M7KX2TX.js +148 -0
  145. package/docCreateCommands-SIL3NPGT.js +220 -0
  146. package/docDeleteCommands-7IOMLUS4.js +181 -0
  147. package/docReadCommands-FNFXUA5L.js +134 -0
  148. package/docStore-SV7E34D4.js +98 -0
  149. package/docUpdateCommands-X2HNDVUC.js +318 -0
  150. package/fetchMessages-KTNM7QAR.js +17 -0
  151. package/getPricing-3E6UNPKL.js +30 -0
  152. package/handleSendMessageAction-JYETO5RZ.js +185 -0
  153. package/index.js +188 -112958
  154. package/lib-FYYBQIXS.js +19839 -0
  155. package/localDialogRead-2VRI24F4.js +26 -0
  156. package/localFirstLog-DHNOY2NA.js +19 -0
  157. package/localRuntimeAuthority-TEGCOWX4.js +471 -0
  158. package/localRuntimeDb-LGDF6FQP.js +12 -0
  159. package/machineCommands-RIO3RP5Q.js +781 -0
  160. package/machineInfo-M6KB6HZN.js +10 -0
  161. package/machineWsRunDispatch-W7UYLGB5.js +112 -0
  162. package/memoryCommands-O4MIPIWQ.js +476 -0
  163. package/models-4OPOOLFS.js +9 -0
  164. package/offlineMarxistsAgentCommand-BCPJITJL.js +242 -0
  165. package/package.json +4 -24
  166. package/read-GW7ZEI23.js +17 -0
  167. package/readDocTool-HUFU6OCT.js +16 -0
  168. package/readlineWorkspace-27JR7WPW.js +5682 -0
  169. package/removeDialogAgentAction-CXKR4NJI.js +73 -0
  170. package/runAgentClientLoop-HZFAPJHS.js +293 -0
  171. package/runtimeDoctorCommands-LRHLPDRC.js +289 -0
  172. package/setDialogExtraReferencesAction-6RKUSXHX.js +60 -0
  173. package/setPrimaryDialogAgentAction-T3UTBEFG.js +80 -0
  174. package/settingSlice-IVKXJXMG.js +199 -0
  175. package/skillDiscovery-UGSQGX2U.js +16 -0
  176. package/skillSummaryMarker-42HKSXYY.js +9 -0
  177. package/slateToRenderMarkdown-Y5IYN73U.js +7 -0
  178. package/slateUtils-2M7MUTWX.js +19 -0
  179. package/spaceCommands-E7VOF4LO.js +450 -0
  180. package/spaceSlice-TSVROA5U.js +149 -0
  181. package/streamAgentChatTurn-3C5RQZJF.js +4510 -0
  182. package/tableCommands-O7O2LBEG.js +1286 -0
  183. package/toolApiClient-QI3YBNWB.js +26 -0
  184. package/tools-EQDEKR6N.js +87 -0
  185. package/tuiSummaryLlmCaller-RV3THLZF.js +78 -0
  186. package/understanding-3CUQQ6SV.js +271 -0
  187. package/updateCommands-VOSPKXFF.js +31 -0
  188. package/updateDialogTitleAction-3XV7VWSZ.js +188 -0
@@ -0,0 +1,4510 @@
1
+ import {
2
+ applyModelLayerOverride
3
+ } from "./chunk-LTRXGFMS.js";
4
+ import {
5
+ buildStaticUserPolicyContext,
6
+ resolveSpaceContextPreloadPlan
7
+ } from "./chunk-4O3CARJ4.js";
8
+ import {
9
+ getFinalPrice,
10
+ getModelPricing,
11
+ getPrices,
12
+ hasExplicitAgentPricing
13
+ } from "./chunk-YPRZSPF3.js";
14
+ import {
15
+ buildCliPrompt
16
+ } from "./chunk-ATNTHIZI.js";
17
+ import {
18
+ INVALID_TOOL_ARGS_REPLACEMENT,
19
+ buildInvalidToolCallSelfHealResult,
20
+ filterAndCleanMessages,
21
+ handleToolCalls,
22
+ parseApiError,
23
+ parseToolCallArguments,
24
+ persistToolMessages,
25
+ readStreamChunk,
26
+ sanitizeOutboundResponsesInput,
27
+ sendOpenAICompletionsRequest,
28
+ updateTotalUsage
29
+ } from "./chunk-6KHNO3SK.js";
30
+ import "./chunk-JEXVIMYZ.js";
31
+ import {
32
+ prepareTools
33
+ } from "./chunk-FSO5B7GH.js";
34
+ import {
35
+ fetchReferenceContents,
36
+ generateRequestBody,
37
+ mergeReferences,
38
+ performFetchRequest,
39
+ performServerProxyFetchWithRetry,
40
+ resolveAgentCallPlan,
41
+ resolveClientWire,
42
+ resolveReferenceAssets,
43
+ resolveToolsFromKeys
44
+ } from "./chunk-7GNGZRLZ.js";
45
+ import "./chunk-C3RUNRHT.js";
46
+ import {
47
+ getPublicImageAgentDefaultProfile,
48
+ getPublicImageAgentMode
49
+ } from "./chunk-VIDPVFP3.js";
50
+ import {
51
+ TOOL_PACKS,
52
+ applyDefaultWebToolPacks,
53
+ applyDisabledTools,
54
+ createSSEParser,
55
+ expandEnabledPacks,
56
+ getAllToolRuns,
57
+ shouldBlockForGptPro
58
+ } from "./chunk-AL2KDGR2.js";
59
+ import "./chunk-GAKEBQD6.js";
60
+ import "./chunk-KQHGZWSV.js";
61
+ import "./chunk-AS4PVWA4.js";
62
+ import "./chunk-3LY4F7SV.js";
63
+ import {
64
+ extractCategorizedMentions
65
+ } from "./chunk-VP4WJWKW.js";
66
+ import "./chunk-63W5N6P3.js";
67
+ import "./chunk-VF4K2QE6.js";
68
+ import {
69
+ getDocState
70
+ } from "./chunk-UB6SN4NJ.js";
71
+ import "./chunk-ENOG22KJ.js";
72
+ import "./chunk-VC6OZXO5.js";
73
+ import "./chunk-25LCXTML.js";
74
+ import "./chunk-XENYHRUE.js";
75
+ import {
76
+ PERSONALIZATION_DIALOG_CATEGORY,
77
+ addToolMessage,
78
+ addUserMessage,
79
+ buildPersonalizationDialogPolicyContext,
80
+ estimateTokenCount,
81
+ extractReferenceKeysFromMessage,
82
+ finalizeTransientMessageOnError,
83
+ getModelContextWindow,
84
+ getModelInfo,
85
+ messageStreamEnd,
86
+ messageStreaming,
87
+ planContextUsage,
88
+ prepareAndPersistUserMessage,
89
+ removeTransientMessage,
90
+ selectAllMsgs,
91
+ selectCurrentDialogConfig,
92
+ selectCurrentSpaceId,
93
+ selectCurrentTable,
94
+ selectCurrentUserBalance,
95
+ selectDialogConfigByKey,
96
+ selectTableRows,
97
+ selectViewMode
98
+ } from "./chunk-2ECQG4YX.js";
99
+ import "./chunk-4ZDM73SD.js";
100
+ import "./chunk-MRC4Q34M.js";
101
+ import "./chunk-MTU75CZ2.js";
102
+ import "./chunk-CWMSB67P.js";
103
+ import "./chunk-VUW5FBDB.js";
104
+ import {
105
+ createCliChatTurnStream,
106
+ getCliChatSession,
107
+ startCliChatSession
108
+ } from "./chunk-5EFXE3O7.js";
109
+ import "./chunk-Z4NR32XR.js";
110
+ import "./chunk-M76ECQRD.js";
111
+ import "./chunk-SOTZ6RDN.js";
112
+ import "./chunk-I6XMPTMR.js";
113
+ import "./chunk-UAD2WT54.js";
114
+ import "./chunk-DCOA4QSN.js";
115
+ import {
116
+ buildLinkedSpacesSection,
117
+ buildSpaceContextLayer
118
+ } from "./chunk-C4FTUXVF.js";
119
+ import "./chunk-KKY4B2Q2.js";
120
+ import "./chunk-WZSRQNQG.js";
121
+ import {
122
+ assertDesktopAgentRuntimeTurnBodyHasNoRawSecrets,
123
+ buildDesktopAgentRuntimeAgentConfigSnapshot,
124
+ buildDesktopAgentRuntimeDialogHistorySnapshot
125
+ } from "./chunk-TILFE6LV.js";
126
+ import {
127
+ resolveAgentImageInputSupport
128
+ } from "./chunk-4QEWT7KD.js";
129
+ import "./chunk-OPZYGHUC.js";
130
+ import "./chunk-AGFH73SK.js";
131
+ import {
132
+ extractImagePartsFromResponseOutput,
133
+ extractTextFromResponseOutput,
134
+ toResponsesTools
135
+ } from "./chunk-JRKKFRAV.js";
136
+ import {
137
+ canonicalizeToolNames,
138
+ prioritizeToolNames,
139
+ resolveRuntimeToolSurfaceForAgent
140
+ } from "./chunk-P3PKED2I.js";
141
+ import "./chunk-5MMAK75Q.js";
142
+ import {
143
+ getApiEndpoint,
144
+ getModelConfig,
145
+ getProviderByModelName
146
+ } from "./chunk-BBYVOSU2.js";
147
+ import "./chunk-5CS33IBL.js";
148
+ import "./chunk-JZPBVBIY.js";
149
+ import "./chunk-IWX4UW2E.js";
150
+ import {
151
+ resolveToolBaseUrl
152
+ } from "./chunk-5MIDPSSK.js";
153
+ import {
154
+ extractCustomId
155
+ } from "./chunk-DFFIZ25G.js";
156
+ import {
157
+ addActiveController,
158
+ clearPendingUserInputQueue,
159
+ dequeueUserInput,
160
+ removeActiveController,
161
+ selectActiveControllers,
162
+ selectPendingFiles,
163
+ selectPendingUserInputQueue,
164
+ tokenUsageLiveUpdate
165
+ } from "./chunk-3ASDTTEI.js";
166
+ import "./chunk-DWLEOOGR.js";
167
+ import {
168
+ toErrorMessage
169
+ } from "./chunk-HNMXYYJR.js";
170
+ import {
171
+ selectAiRecentContentLimit,
172
+ selectCurrentServer,
173
+ selectGlobalPrompt,
174
+ selectKnowledgeCaptureLevel,
175
+ selectMaxExecutionTime,
176
+ selectSpaceContextLevel,
177
+ selectUserTonePreset
178
+ } from "./chunk-VX3SXJ3N.js";
179
+ import "./chunk-Y5GCAMGP.js";
180
+ import {
181
+ patch,
182
+ read,
183
+ selectById,
184
+ write
185
+ } from "./chunk-URUUZLPA.js";
186
+ import "./chunk-AZPCASRE.js";
187
+ import "./chunk-7U44LYTR.js";
188
+ import {
189
+ asRecordOrEmpty
190
+ } from "./chunk-KX6YBIHG.js";
191
+ import {
192
+ createDialogMessageKeyAndId,
193
+ dialogMessageKey
194
+ } from "./chunk-O4BU24WZ.js";
195
+ import {
196
+ asNonEmptyStringArray
197
+ } from "./chunk-I42VC5KR.js";
198
+ import {
199
+ asOptionalFiniteNumber
200
+ } from "./chunk-WWC7I6TA.js";
201
+ import "./chunk-QSJ3HFEF.js";
202
+ import "./chunk-DSZUWUYB.js";
203
+ import {
204
+ selectIdentityToken,
205
+ selectIdentityUser,
206
+ selectIdentityUserId,
207
+ selectRuntimeCurrentServer
208
+ } from "./chunk-UTLZINAP.js";
209
+ import {
210
+ getIsDesktopApp,
211
+ isAbortError
212
+ } from "./chunk-OOSFSFMA.js";
213
+ import "./chunk-GBRG75BQ.js";
214
+ import "./chunk-4SN6J65J.js";
215
+ import "./chunk-LCBAMY2M.js";
216
+ import {
217
+ asTrimmedString
218
+ } from "./chunk-3EUW3WEO.js";
219
+ import "./chunk-U6VC4MU4.js";
220
+ import "./chunk-CF7PE763.js";
221
+ import {
222
+ asOptionalTrimmedString
223
+ } from "./chunk-G3SUCT4W.js";
224
+ import {
225
+ isRecord
226
+ } from "./chunk-KUG52IAP.js";
227
+ import "./chunk-4VNS5WPM.js";
228
+
229
+ // packages/ai/agent/isVoiceModel.ts
230
+ function isVoiceModel(model, provider) {
231
+ const providerLower = String(provider || "").toLowerCase();
232
+ const modelLower = String(model || "").toLowerCase();
233
+ if (providerLower === "google" && modelLower.includes("live")) return true;
234
+ if (modelLower.includes("live-preview")) return true;
235
+ if (modelLower.includes("live-001")) return true;
236
+ if (modelLower.includes("native-audio")) return true;
237
+ return false;
238
+ }
239
+
240
+ // packages/ai/agent/isLiveAudioOnlyAgent.ts
241
+ function isLiveAudioOnlyAgent(agent) {
242
+ if (agent.defaultInteractionMode !== "live_audio") return false;
243
+ return isVoiceModel(agent.model, agent.provider);
244
+ }
245
+
246
+ // packages/ai/agent/projectDesktopToolUiContent.ts
247
+ var DESKTOP_TOOL_UI_CONTENT_MAX_CHARS = 48e3;
248
+ function clipUiText(value, max = DESKTOP_TOOL_UI_CONTENT_MAX_CHARS) {
249
+ if (value.length <= max) return value;
250
+ return `${value.slice(0, Math.max(0, max - 20))}
251
+ \u2026[truncated for UI]`;
252
+ }
253
+ function tryParseJsonRecord(text) {
254
+ const trimmed = text.trim();
255
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return null;
256
+ try {
257
+ const parsed = JSON.parse(trimmed);
258
+ return isRecord(parsed) ? parsed : null;
259
+ } catch {
260
+ return null;
261
+ }
262
+ }
263
+ function parseShellToolTextContent(content) {
264
+ const text = content ?? "";
265
+ if (!text.trim()) return { stdout: "", stderr: "" };
266
+ const exitMatch = text.match(/(?:^|\n)exitCode:\s*(-?\d+)\s*$/);
267
+ const exitCode = exitMatch ? Number(exitMatch[1]) : void 0;
268
+ const body = (exitMatch ? text.slice(0, exitMatch.index) : text).replace(
269
+ /\s+$/,
270
+ ""
271
+ );
272
+ let stdout = "";
273
+ let stderr = "";
274
+ if (body.startsWith("stdout:\n") || body.includes("\nstdout:\n")) {
275
+ const afterStdout = body.replace(/^[\s\S]*?stdout:\n/, "");
276
+ if (afterStdout.includes("\n\nstderr:\n")) {
277
+ const [out, err] = afterStdout.split("\n\nstderr:\n");
278
+ stdout = out ?? "";
279
+ stderr = err ?? "";
280
+ } else if (afterStdout.startsWith("stderr:\n")) {
281
+ stderr = afterStdout.slice("stderr:\n".length);
282
+ } else {
283
+ stdout = afterStdout;
284
+ }
285
+ } else if (body.startsWith("stderr:\n") || body.includes("\nstderr:\n")) {
286
+ stderr = body.replace(/^[\s\S]*?stderr:\n/, "");
287
+ } else {
288
+ stdout = body;
289
+ }
290
+ return {
291
+ stdout,
292
+ stderr,
293
+ ...typeof exitCode === "number" && Number.isFinite(exitCode) ? { exitCode } : {}
294
+ };
295
+ }
296
+ function resolveShellCommand(metadata, argumentsPreview) {
297
+ return asOptionalTrimmedString(metadata.command) || asOptionalTrimmedString(metadata.cmd) || asOptionalTrimmedString(argumentsPreview) || "";
298
+ }
299
+ function projectDesktopToolUiContent(args) {
300
+ const toolName = asOptionalTrimmedString(args.toolName) || "tool";
301
+ const metadata = isRecord(args.metadata) ? args.metadata : {};
302
+ const rawContent = typeof args.content === "string" ? args.content : typeof args.summary === "string" ? args.summary : typeof args.message === "string" ? args.message : "";
303
+ if (toolName === "execShell") {
304
+ const existing = tryParseJsonRecord(rawContent);
305
+ if (existing && (typeof existing.stdout === "string" || typeof existing.command === "string" || typeof existing.stderr === "string")) {
306
+ const command2 = asOptionalTrimmedString(existing.command) || resolveShellCommand(metadata, args.argumentsPreview);
307
+ return JSON.stringify({
308
+ ...existing,
309
+ command: command2,
310
+ cwd: asOptionalTrimmedString(existing.cwd) || asOptionalTrimmedString(metadata.cwd) || null,
311
+ exitCode: asOptionalFiniteNumber(existing.exitCode) ?? asOptionalFiniteNumber(metadata.exitCode)
312
+ });
313
+ }
314
+ const parsed = parseShellToolTextContent(rawContent);
315
+ const command = resolveShellCommand(metadata, args.argumentsPreview);
316
+ return JSON.stringify({
317
+ command,
318
+ cwd: asOptionalTrimmedString(metadata.cwd) || null,
319
+ stdout: clipUiText(parsed.stdout),
320
+ stderr: clipUiText(parsed.stderr),
321
+ exitCode: asOptionalFiniteNumber(metadata.exitCode) ?? parsed.exitCode,
322
+ timedOut: metadata.timedOut === true,
323
+ blocked: metadata.blocked === true
324
+ });
325
+ }
326
+ if (toolName === "readFile" || toolName === "read_file") {
327
+ const filePath = asOptionalTrimmedString(metadata.path) || asOptionalTrimmedString(metadata.filePath) || asOptionalTrimmedString(metadata.file_path) || asOptionalTrimmedString(args.argumentsPreview) || "";
328
+ const body = typeof args.content === "string" && args.content || typeof args.summary === "string" && args.summary || typeof args.message === "string" && args.message || "";
329
+ return JSON.stringify({
330
+ filePath,
331
+ content: clipUiText(body),
332
+ ...asOptionalFiniteNumber(metadata.startLine) != null ? { startLine: asOptionalFiniteNumber(metadata.startLine) } : {},
333
+ ...asOptionalFiniteNumber(metadata.endLine) != null ? { endLine: asOptionalFiniteNumber(metadata.endLine) } : {},
334
+ ...asOptionalFiniteNumber(metadata.totalLines) != null ? { totalLines: asOptionalFiniteNumber(metadata.totalLines) } : {},
335
+ ...metadata.truncated === true ? { truncated: true } : {}
336
+ });
337
+ }
338
+ const preferred = typeof args.content === "string" && args.content || typeof args.summary === "string" && args.summary || typeof args.message === "string" && args.message || "";
339
+ return clipUiText(preferred);
340
+ }
341
+
342
+ // packages/ai/agent/desktopTurnSegments.ts
343
+ function attachToolCallIdToSegment(segments, callId) {
344
+ if (!segments || segments.length === 0) return;
345
+ const current = segments[segments.length - 1];
346
+ if (!current.toolCallIds) {
347
+ current.toolCallIds = [];
348
+ }
349
+ current.toolCallIds.push(callId);
350
+ }
351
+ function resolveSegmentToolCalls(toolCallIds, turnMessages) {
352
+ if (!toolCallIds || toolCallIds.length === 0 || !Array.isArray(turnMessages) || turnMessages.length === 0) {
353
+ return [];
354
+ }
355
+ const callMap = /* @__PURE__ */ new Map();
356
+ for (const msg of turnMessages) {
357
+ if (Array.isArray(msg?.tool_calls)) {
358
+ for (const tc of msg.tool_calls) {
359
+ if (tc && typeof tc.id === "string") {
360
+ callMap.set(tc.id, tc);
361
+ }
362
+ }
363
+ }
364
+ }
365
+ const resolved = [];
366
+ for (const id of toolCallIds) {
367
+ const tc = callMap.get(id);
368
+ if (tc) {
369
+ resolved.push(tc);
370
+ }
371
+ }
372
+ return resolved;
373
+ }
374
+ function buildMinimalToolCallsFromIds(toolCallIds, toolNameById) {
375
+ if (!toolCallIds || toolCallIds.length === 0) return [];
376
+ const result = [];
377
+ for (const id of toolCallIds) {
378
+ if (!toolNameById.has(id)) continue;
379
+ const name = toolNameById.get(id) || "tool";
380
+ result.push({ id, type: "function", function: { name, arguments: "{}" } });
381
+ }
382
+ return result;
383
+ }
384
+ function selectPersistableFinalizedSegments(segments) {
385
+ if (!Array.isArray(segments)) return [];
386
+ return segments.filter(
387
+ (segment) => segment.finalized && (segment.content.length > 0 || segment.toolCallIds && segment.toolCallIds.length > 0)
388
+ );
389
+ }
390
+
391
+ // packages/chat/queue/chatQueueLifecycleActions.ts
392
+ function runChatQueueTurnEnd(payload) {
393
+ return (_dispatch, _getState, extra) => {
394
+ const adapter = extra?.chatQueueAdapter;
395
+ if (!adapter) return;
396
+ void adapter.notifyTurnEnd(payload.dialogKey, {
397
+ ok: payload.ok,
398
+ aborted: payload.aborted
399
+ });
400
+ };
401
+ }
402
+
403
+ // packages/ai/agent/getFullChatContextKeys.ts
404
+ var difference = (arrA, arrB) => {
405
+ if (!arrA.length) return [];
406
+ if (!arrB.length) return [...arrA];
407
+ const exclude = new Set(arrB);
408
+ return arrA.filter((item) => !exclude.has(item));
409
+ };
410
+ var getFullChatContextKeys = async (state, dispatch, agentConfig, userInput, dialogConfig) => {
411
+ const msgs = selectAllMsgs(
412
+ state,
413
+ dialogConfig?.dbKey ? extractCustomId(dialogConfig.dbKey) : dialogConfig?.id
414
+ );
415
+ const botInstructionKeys = /* @__PURE__ */ new Set();
416
+ const botKnowledgeKeys = /* @__PURE__ */ new Set();
417
+ if (Array.isArray(agentConfig.references)) {
418
+ for (const ref of agentConfig.references) {
419
+ if (!ref?.dbKey) continue;
420
+ if (ref.type === "instruction") {
421
+ botInstructionKeys.add(ref.dbKey);
422
+ } else {
423
+ botKnowledgeKeys.add(ref.dbKey);
424
+ }
425
+ }
426
+ }
427
+ const currentInputKeys = /* @__PURE__ */ new Set();
428
+ if (Array.isArray(userInput)) {
429
+ for (const part of userInput) {
430
+ if (part?.pageKey) currentInputKeys.add(part.pageKey);
431
+ if (part?.dialogKey) currentInputKeys.add(part.dialogKey);
432
+ }
433
+ }
434
+ const historyKeys = /* @__PURE__ */ new Set();
435
+ const savedKeys = dialogConfig?.referenceKeys;
436
+ if (Array.isArray(savedKeys)) {
437
+ savedKeys.forEach((k) => historyKeys.add(k));
438
+ }
439
+ const scanContentParts = (msg) => {
440
+ if (!msg) return;
441
+ for (const key of extractReferenceKeysFromMessage(msg)) {
442
+ historyKeys.add(key);
443
+ }
444
+ };
445
+ if (msgs && msgs.length > 0) {
446
+ const summarizedBeforeId = dialogConfig?.summarizedBeforeId;
447
+ if (!summarizedBeforeId) {
448
+ for (const msg of msgs) scanContentParts(msg);
449
+ } else {
450
+ let foundMarker = false;
451
+ let startScan = false;
452
+ for (const msg of msgs) {
453
+ if (!startScan) {
454
+ if (msg.id === summarizedBeforeId) {
455
+ foundMarker = true;
456
+ startScan = true;
457
+ }
458
+ continue;
459
+ }
460
+ scanContentParts(msg);
461
+ }
462
+ if (!foundMarker) {
463
+ console.warn(`[getFullChatContextKeys] marker ${summarizedBeforeId} not found, scanning all`);
464
+ for (const msg of msgs) scanContentParts(msg);
465
+ }
466
+ }
467
+ }
468
+ return {
469
+ botInstructionKeys,
470
+ currentInputKeys,
471
+ historyKeys,
472
+ botKnowledgeKeys
473
+ };
474
+ };
475
+ var deduplicateContextKeys = (keys) => {
476
+ const {
477
+ botInstructionKeys,
478
+ currentInputKeys,
479
+ historyKeys,
480
+ botKnowledgeKeys
481
+ } = keys;
482
+ const finalBotInstructionKeys = Array.from(botInstructionKeys);
483
+ const finalCurrentInputKeys = difference(
484
+ Array.from(currentInputKeys),
485
+ finalBotInstructionKeys
486
+ );
487
+ const finalHistoryKeys = difference(Array.from(historyKeys), [
488
+ ...finalBotInstructionKeys,
489
+ ...finalCurrentInputKeys
490
+ ]);
491
+ const finalBotKnowledgeKeys = difference(Array.from(botKnowledgeKeys), [
492
+ ...finalBotInstructionKeys,
493
+ ...finalCurrentInputKeys,
494
+ ...finalHistoryKeys
495
+ ]);
496
+ return {
497
+ botInstructionsContext: finalBotInstructionKeys,
498
+ currentInputContext: finalCurrentInputKeys,
499
+ historyContext: finalHistoryKeys,
500
+ botKnowledgeContext: finalBotKnowledgeKeys
501
+ };
502
+ };
503
+
504
+ // packages/ai/chat/streamRetry.ts
505
+ var MAX_INITIAL_STREAM_RETRIES = 1;
506
+ var DEFAULT_INITIAL_STREAM_RETRY_AFTER_MS = 1500;
507
+ var normalizeInitialStreamRetryAfterMs = (value) => {
508
+ const parsed = Number(value);
509
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.round(parsed) : DEFAULT_INITIAL_STREAM_RETRY_AFTER_MS;
510
+ };
511
+ var isRetryableInitialStreamError = (error) => {
512
+ if (!error || isAbortError(error)) return false;
513
+ const message = typeof error?.message === "string" ? error.message : String(error);
514
+ return /ECONNRESET|ECONNREFUSED|EPIPE|socket hang up|network error|failed to fetch|fetch failed|load failed|connection closed|stream ended before first visible delta|response stream ended before first visible delta|模型响应流 .* 秒内没有返回新内容/i.test(
515
+ message
516
+ );
517
+ };
518
+ var waitForInitialStreamRetry = async (retryAfterMs, signal) => {
519
+ if (signal?.aborted) {
520
+ const abortError = new Error("Aborted");
521
+ abortError.name = "AbortError";
522
+ throw abortError;
523
+ }
524
+ await new Promise((resolve, reject) => {
525
+ const onAbort = () => {
526
+ clearTimeout(timeoutId);
527
+ signal?.removeEventListener("abort", onAbort);
528
+ const abortError = new Error("Aborted");
529
+ abortError.name = "AbortError";
530
+ reject(abortError);
531
+ };
532
+ const timeoutId = setTimeout(() => {
533
+ signal?.removeEventListener("abort", onAbort);
534
+ resolve();
535
+ }, normalizeInitialStreamRetryAfterMs(retryAfterMs));
536
+ signal?.addEventListener("abort", onAbort, { once: true });
537
+ });
538
+ };
539
+
540
+ // packages/ai/chat/sendOpenAIResponseRequest.ts
541
+ var seg = (txt) => [{ type: "text", text: txt ?? "" }];
542
+ var shouldEnableBuiltInImageGeneration = (agentConfig) => String(agentConfig?.provider || "").toLowerCase() === "openai" && !getModelInfo(String(agentConfig?.model || ""))?.hasImageOutput && !!agentConfig?.imageConfig?.enabled;
543
+ var withImageGenerationStage = (messageMetadata, stage) => {
544
+ const previousState = messageMetadata?.imageGenerationState;
545
+ if (previousState?.kind !== "image_generation") {
546
+ return messageMetadata;
547
+ }
548
+ return {
549
+ ...messageMetadata ?? {},
550
+ imageGenerationState: {
551
+ ...previousState,
552
+ stage
553
+ }
554
+ };
555
+ };
556
+ var shouldShowImageSavingState = (contentBuffer) => contentBuffer.some((part) => part?.type === "image_url") && !contentBuffer.some(
557
+ (part) => part?.type === "text" && typeof part.text === "string" && part.text.trim()
558
+ );
559
+ var logQuickChatPerfStage = (startedAt, stage, details) => {
560
+ if (!startedAt) return;
561
+ const now = typeof performance !== "undefined" ? performance.now() : Date.now();
562
+ console.info("[QuickChatPerf]", {
563
+ stage,
564
+ elapsedMs: now - startedAt,
565
+ ...typeof performance !== "undefined" ? { atMs: now } : {},
566
+ ...details ?? {}
567
+ });
568
+ };
569
+ var safeCancel = async (reader) => {
570
+ if (!reader) return;
571
+ try {
572
+ await reader.cancel();
573
+ } catch {
574
+ }
575
+ };
576
+ var ensureToolCall = (state, key, partial) => {
577
+ let toolCall = state.assistantToolCalls.find((call) => call.id === key);
578
+ if (!toolCall) {
579
+ toolCall = {
580
+ id: key,
581
+ type: "function",
582
+ function: { name: "", arguments: "" }
583
+ };
584
+ state.assistantToolCalls.push(toolCall);
585
+ }
586
+ if (partial.id) toolCall.id = partial.id;
587
+ if (partial.function?.name) toolCall.function.name = partial.function.name;
588
+ if (typeof partial.function?.arguments === "string") {
589
+ toolCall.function.arguments = partial.function.arguments;
590
+ }
591
+ return toolCall;
592
+ };
593
+ var extractTextFromOutputItem = (item) => {
594
+ if (item?.type !== "message" || !Array.isArray(item.content)) return "";
595
+ return item.content.filter(
596
+ (content) => content?.type === "output_text" && typeof content.text === "string"
597
+ ).map((content) => content.text).join("");
598
+ };
599
+ var getStreamErrorMessage = (event) => {
600
+ const directMessage = asOptionalTrimmedString(event?.message);
601
+ if (directMessage) return directMessage;
602
+ const nestedMessage = asOptionalTrimmedString(event?.error?.message) ?? asOptionalTrimmedString(event?.error?.msg);
603
+ if (nestedMessage) return nestedMessage;
604
+ const nestedCode = asOptionalTrimmedString(event?.error?.code) ?? asOptionalTrimmedString(event?.code);
605
+ if (nestedCode) return nestedCode;
606
+ const nestedType = asOptionalTrimmedString(event?.error?.type);
607
+ if (nestedType) return nestedType;
608
+ const eventType = asOptionalTrimmedString(event?.type);
609
+ if (eventType && eventType !== "error") return eventType;
610
+ return "Unknown error";
611
+ };
612
+ var sendOpenAIResponseRequest = async ({
613
+ bodyData,
614
+ agentConfig,
615
+ thunkApi,
616
+ dialogKey,
617
+ parentMessageId,
618
+ messageMetadata,
619
+ quickChatPerfStartedAt
620
+ }) => {
621
+ const { dispatch, getState, signal: thunkSignal } = thunkApi;
622
+ const dialogId = extractCustomId(dialogKey);
623
+ const controller = new AbortController();
624
+ thunkSignal.addEventListener("abort", () => controller.abort());
625
+ const signal = controller.signal;
626
+ const streamSpaceId = selectCurrentSpaceId(getState()) || void 0;
627
+ let messageId;
628
+ let msgKey;
629
+ if (parentMessageId) {
630
+ messageId = parentMessageId;
631
+ msgKey = `msg:${dialogId}:${messageId}`;
632
+ } else {
633
+ const newIds = createDialogMessageKeyAndId(dialogId);
634
+ messageId = newIds.messageId;
635
+ msgKey = newIds.key;
636
+ }
637
+ dispatch(addActiveController({ messageId, controller, dialogKey }));
638
+ const state = {
639
+ content: "",
640
+ contentBuffer: [],
641
+ reasoning: "",
642
+ usage: null,
643
+ assistantToolCalls: [],
644
+ completedResponse: null
645
+ };
646
+ let activeMessageMetadata = messageMetadata;
647
+ const buildMeta = (hasPendingInteraction = false, hasHandedOff = false, finishReason = null) => ({
648
+ hasToolCalls: state.assistantToolCalls.length > 0,
649
+ hasPendingInteraction,
650
+ hasHandedOff,
651
+ finishReason,
652
+ messageId,
653
+ usage: state.usage ?? void 0
654
+ });
655
+ const resetStateForRetry = () => {
656
+ state.content = "";
657
+ state.contentBuffer = [];
658
+ state.reasoning = "";
659
+ state.usage = null;
660
+ state.assistantToolCalls = [];
661
+ state.completedResponse = null;
662
+ activeMessageMetadata = messageMetadata;
663
+ };
664
+ const canRetryInitialResponseAttempt = (attempt, loggedFirstVisibleDelta, finishReason) => attempt < MAX_INITIAL_STREAM_RETRIES && !loggedFirstVisibleDelta && !state.assistantToolCalls.length && !finishReason && !state.completedResponse;
665
+ const flush = () => dispatch(
666
+ messageStreaming({
667
+ id: messageId,
668
+ dialogId,
669
+ dbKey: msgKey,
670
+ content: state.contentBuffer,
671
+ thinkContent: state.reasoning,
672
+ role: "assistant",
673
+ agentKey: agentConfig.dbKey,
674
+ cybotKey: agentConfig.dbKey,
675
+ ...asOptionalTrimmedString(agentConfig?.name) ? { agentName: asOptionalTrimmedString(agentConfig?.name) } : {},
676
+ ...activeMessageMetadata ?? {}
677
+ })
678
+ );
679
+ const finalize = async () => {
680
+ if (!state.content) {
681
+ const completedText = extractTextFromResponseOutput(state.completedResponse);
682
+ if (completedText) {
683
+ state.content = completedText;
684
+ }
685
+ }
686
+ const completedImages = extractImagePartsFromResponseOutput(state.completedResponse);
687
+ if (state.contentBuffer.length === 0) {
688
+ state.contentBuffer = [
689
+ ...state.content ? seg(state.content) : [],
690
+ ...completedImages
691
+ ];
692
+ } else if (completedImages.length > 0 && !state.contentBuffer.some((part) => part.type === "image_url")) {
693
+ state.contentBuffer = [...state.contentBuffer, ...completedImages];
694
+ }
695
+ if (state.contentBuffer.length === 0 && state.content) {
696
+ state.contentBuffer = seg(state.content);
697
+ }
698
+ activeMessageMetadata = withImageGenerationStage(
699
+ activeMessageMetadata,
700
+ "saving"
701
+ );
702
+ if (activeMessageMetadata?.imageGenerationState && shouldShowImageSavingState(state.contentBuffer)) {
703
+ dispatch(
704
+ messageStreaming({
705
+ id: messageId,
706
+ dialogId,
707
+ dbKey: msgKey,
708
+ content: "",
709
+ thinkContent: state.reasoning,
710
+ role: "assistant",
711
+ agentKey: agentConfig.dbKey,
712
+ cybotKey: agentConfig.dbKey,
713
+ ...asOptionalTrimmedString(agentConfig?.name) ? { agentName: asOptionalTrimmedString(agentConfig?.name) } : {},
714
+ ...activeMessageMetadata ?? {}
715
+ })
716
+ );
717
+ } else {
718
+ flush();
719
+ }
720
+ await dispatch(
721
+ messageStreamEnd({
722
+ finalContentBuffer: state.contentBuffer,
723
+ totalUsage: state.usage,
724
+ msgKey,
725
+ agentConfig,
726
+ dialogId,
727
+ dialogKey,
728
+ messageId,
729
+ reasoningBuffer: state.reasoning,
730
+ messageMetadata: activeMessageMetadata,
731
+ toolCalls: state.assistantToolCalls,
732
+ spaceId: streamSpaceId
733
+ })
734
+ );
735
+ };
736
+ const processToolCalls = async () => {
737
+ if (!state.assistantToolCalls.length) {
738
+ await finalize();
739
+ return buildMeta(false, false, null);
740
+ }
741
+ const validCalls = [];
742
+ const invalidCalls = [];
743
+ for (const call of state.assistantToolCalls) {
744
+ if (!call) continue;
745
+ if (parseToolCallArguments(call?.function?.arguments).valid) {
746
+ validCalls.push(call);
747
+ } else {
748
+ invalidCalls.push({
749
+ ...call,
750
+ type: "function",
751
+ function: {
752
+ name: call?.function?.name ?? "",
753
+ arguments: INVALID_TOOL_ARGS_REPLACEMENT
754
+ }
755
+ });
756
+ }
757
+ }
758
+ if (invalidCalls.length > 0) {
759
+ const invalidById = /* @__PURE__ */ new Map();
760
+ for (const call of invalidCalls) {
761
+ if (call?.id) invalidById.set(call.id, call);
762
+ }
763
+ state.assistantToolCalls = state.assistantToolCalls.map((call) => {
764
+ const invalid = call?.id ? invalidById.get(call.id) : void 0;
765
+ if (!invalid) return call;
766
+ return {
767
+ ...call,
768
+ type: "function",
769
+ function: {
770
+ name: invalid.function?.name ?? call.function?.name ?? "",
771
+ arguments: INVALID_TOOL_ARGS_REPLACEMENT
772
+ }
773
+ };
774
+ });
775
+ for (let i = 0; i < invalidCalls.length; i++) {
776
+ const call = invalidCalls[i];
777
+ const callId = call?.id || `call_${Date.now()}_${Math.random().toString(36).slice(2)}`;
778
+ const toolIndex = validCalls.length + i;
779
+ const runningToolMessageId = `${messageId}-t${String(toolIndex).padStart(3, "0")}`;
780
+ const runningToolDbKey = dialogMessageKey(dialogId, runningToolMessageId);
781
+ const toolName = call?.function?.name || "unknown";
782
+ const selfHealContent = buildInvalidToolCallSelfHealResult(callId, toolName);
783
+ const toolMessage = {
784
+ id: runningToolMessageId,
785
+ dbKey: runningToolDbKey,
786
+ role: "tool",
787
+ content: selfHealContent,
788
+ toolCallId: callId,
789
+ thinkContent: "",
790
+ cybotKey: agentConfig.dbKey,
791
+ isStreaming: false,
792
+ toolName,
793
+ parentMessageId: messageId,
794
+ toolPayload: {
795
+ toolName,
796
+ status: "failed",
797
+ input: {},
798
+ rawToolCall: call,
799
+ error: {
800
+ type: "InvalidToolCallArguments",
801
+ message: "\u5DE5\u5177\u53C2\u6570 JSON \u88AB\u622A\u65AD\u6216\u975E\u6CD5\uFF0C\u5DF2\u8DF3\u8FC7\u6267\u884C\u5E76\u66FF\u6362\u4E3A\u5360\u4F4D arguments\u3002",
802
+ retryable: true
803
+ },
804
+ summary: `\u274C ${toolName} \u53C2\u6570\u88AB\u622A\u65AD\uFF0C\u5DF2\u8DF3\u8FC7`
805
+ }
806
+ };
807
+ dispatch(addToolMessage(toolMessage));
808
+ const { controller: _c, ...messageToWrite } = toolMessage;
809
+ await dispatch(
810
+ write({
811
+ data: { ...messageToWrite, type: "msg" /* MSG */ },
812
+ customKey: runningToolDbKey
813
+ })
814
+ );
815
+ }
816
+ }
817
+ if (!validCalls.length) {
818
+ await finalize();
819
+ return buildMeta(false, false, null);
820
+ }
821
+ if (state.usage) {
822
+ dispatch(
823
+ tokenUsageLiveUpdate({
824
+ input_tokens: state.usage.prompt_tokens ?? state.usage.input_tokens,
825
+ output_tokens: state.usage.completion_tokens ?? state.usage.output_tokens,
826
+ cost: state.usage.cost,
827
+ dialogKey
828
+ })
829
+ );
830
+ }
831
+ const result = await dispatch(
832
+ handleToolCalls({
833
+ accumulatedCalls: validCalls,
834
+ currentContentBuffer: state.contentBuffer,
835
+ agentConfig,
836
+ messageId,
837
+ dialogId,
838
+ dialogKey
839
+ })
840
+ ).unwrap();
841
+ state.content = Array.isArray(result.finalContentBuffer) ? result.finalContentBuffer.filter((part) => part?.type === "text").map((part) => part.text ?? "").join("") : state.content;
842
+ state.contentBuffer = Array.isArray(result.finalContentBuffer) ? result.finalContentBuffer : state.contentBuffer;
843
+ await finalize();
844
+ return buildMeta(result.hasPendingInteraction, result.hasHandedOff, null);
845
+ };
846
+ let reader;
847
+ try {
848
+ if (!parentMessageId) {
849
+ dispatch(
850
+ messageStreaming({
851
+ id: messageId,
852
+ dialogId,
853
+ dbKey: msgKey,
854
+ content: "",
855
+ role: "assistant",
856
+ agentKey: agentConfig.dbKey,
857
+ cybotKey: agentConfig.dbKey,
858
+ ...asOptionalTrimmedString(agentConfig?.name) ? { agentName: asOptionalTrimmedString(agentConfig?.name) } : {},
859
+ ...activeMessageMetadata ?? {},
860
+ isStreaming: true
861
+ })
862
+ );
863
+ }
864
+ const functionTools = getModelInfo(agentConfig.model)?.hasImageOutput ? [] : prepareTools(agentConfig.tools ?? [], { provider: agentConfig.provider });
865
+ const imageMode = getPublicImageAgentMode(agentConfig);
866
+ const imageProfile = imageMode === "continuous" ? getPublicImageAgentDefaultProfile("continuous") : null;
867
+ const tools = [
868
+ ...toResponsesTools(functionTools) ?? [],
869
+ ...shouldEnableBuiltInImageGeneration(agentConfig) ? [{ type: "image_generation" }] : [],
870
+ ...imageMode === "continuous" ? [
871
+ {
872
+ type: "image_generation",
873
+ action: "auto",
874
+ quality: imageProfile?.quality,
875
+ output_format: imageProfile?.outputFormat
876
+ }
877
+ ] : []
878
+ ];
879
+ const sanitizedInput = Array.isArray(bodyData?.input) ? sanitizeOutboundResponsesInput(bodyData.input) : bodyData?.input;
880
+ const baseBodyData = sanitizedInput !== bodyData?.input ? { ...bodyData, input: sanitizedInput } : bodyData;
881
+ const requestBody = {
882
+ ...baseBodyData,
883
+ ...tools.length ? { tools, tool_choice: baseBodyData.tool_choice ?? "auto" } : {},
884
+ stream: true
885
+ };
886
+ const api = getApiEndpoint(agentConfig);
887
+ const token = selectIdentityToken(getState());
888
+ logQuickChatPerfStage(quickChatPerfStartedAt, "openai-response-fetch-starting", {
889
+ api,
890
+ dialogKey
891
+ });
892
+ attemptLoop:
893
+ for (let attempt = 0; attempt <= MAX_INITIAL_STREAM_RETRIES; attempt += 1) {
894
+ const response = await performFetchRequest({
895
+ agentConfig,
896
+ api,
897
+ bodyData: requestBody,
898
+ currentServer: selectRuntimeCurrentServer(getState()),
899
+ signal,
900
+ token: token ?? "",
901
+ dialogId
902
+ });
903
+ logQuickChatPerfStage(quickChatPerfStartedAt, "openai-response-fetch-response", {
904
+ ok: response.ok,
905
+ status: response.status,
906
+ dialogKey
907
+ });
908
+ activeMessageMetadata = withImageGenerationStage(
909
+ activeMessageMetadata,
910
+ "generating"
911
+ );
912
+ if (!parentMessageId && activeMessageMetadata?.imageGenerationState) {
913
+ dispatch(
914
+ messageStreaming({
915
+ id: messageId,
916
+ dialogId,
917
+ dbKey: msgKey,
918
+ content: "",
919
+ role: "assistant",
920
+ agentKey: agentConfig.dbKey,
921
+ cybotKey: agentConfig.dbKey,
922
+ ...asOptionalTrimmedString(agentConfig?.name) ? { agentName: asOptionalTrimmedString(agentConfig?.name) } : {},
923
+ ...activeMessageMetadata ?? {},
924
+ isStreaming: true
925
+ })
926
+ );
927
+ }
928
+ if (!response.ok) {
929
+ const errorMessage = await parseApiError(response);
930
+ state.content = `[\u9519\u8BEF: ${errorMessage}]`;
931
+ await finalize();
932
+ return buildMeta();
933
+ }
934
+ reader = response.body?.getReader();
935
+ if (!reader) {
936
+ if (canRetryInitialResponseAttempt(attempt, false, null)) {
937
+ resetStateForRetry();
938
+ await waitForInitialStreamRetry(1500, signal);
939
+ continue;
940
+ }
941
+ await finalize();
942
+ return buildMeta();
943
+ }
944
+ const parseSSE = createSSEParser();
945
+ const decoder = new TextDecoder();
946
+ let finishReason = null;
947
+ let loggedFirstStreamChunk = false;
948
+ let loggedFirstParsedEvent = false;
949
+ let loggedFirstVisibleDelta = false;
950
+ try {
951
+ while (true) {
952
+ const { done, value } = await readStreamChunk(reader, { signal });
953
+ if (done) {
954
+ if (canRetryInitialResponseAttempt(attempt, loggedFirstVisibleDelta, finishReason)) {
955
+ await safeCancel(reader);
956
+ reader = void 0;
957
+ resetStateForRetry();
958
+ await waitForInitialStreamRetry(1500, signal);
959
+ continue attemptLoop;
960
+ }
961
+ const meta = await processToolCalls();
962
+ return {
963
+ ...meta,
964
+ finishReason: meta.finishReason ?? finishReason
965
+ };
966
+ }
967
+ if (!loggedFirstStreamChunk) {
968
+ loggedFirstStreamChunk = true;
969
+ logQuickChatPerfStage(
970
+ quickChatPerfStartedAt,
971
+ "openai-response-first-stream-chunk",
972
+ { dialogKey, byteLength: value.byteLength }
973
+ );
974
+ }
975
+ const chunk = decoder.decode(value, { stream: true });
976
+ const events = parseSSE(chunk);
977
+ if (events.length > 0 && !loggedFirstParsedEvent) {
978
+ loggedFirstParsedEvent = true;
979
+ logQuickChatPerfStage(
980
+ quickChatPerfStartedAt,
981
+ "openai-response-first-sse-event",
982
+ { dialogKey, eventCount: events.length }
983
+ );
984
+ }
985
+ const eventList = Array.isArray(events) ? events : [events];
986
+ for (const event of eventList) {
987
+ if (event?.usage) {
988
+ state.usage = updateTotalUsage(state.usage, event.usage);
989
+ }
990
+ if (event?.type === "error" || event?.error) {
991
+ const streamError = new Error(getStreamErrorMessage(event));
992
+ if (canRetryInitialResponseAttempt(attempt, loggedFirstVisibleDelta, finishReason) && isRetryableInitialStreamError(streamError)) {
993
+ await safeCancel(reader);
994
+ reader = void 0;
995
+ resetStateForRetry();
996
+ await waitForInitialStreamRetry(1500, signal);
997
+ continue attemptLoop;
998
+ }
999
+ state.content += `
1000
+ [Error: ${getStreamErrorMessage(event)}]`;
1001
+ await finalize();
1002
+ return buildMeta();
1003
+ }
1004
+ switch (event?.type) {
1005
+ case "response.output_text.delta":
1006
+ if (event.delta) {
1007
+ state.content += event.delta;
1008
+ state.contentBuffer = seg(state.content);
1009
+ if (!loggedFirstVisibleDelta) {
1010
+ loggedFirstVisibleDelta = true;
1011
+ logQuickChatPerfStage(
1012
+ quickChatPerfStartedAt,
1013
+ "openai-response-first-visible-delta",
1014
+ { dialogKey }
1015
+ );
1016
+ }
1017
+ flush();
1018
+ }
1019
+ break;
1020
+ case "response.reasoning.delta":
1021
+ if (event.delta?.text) {
1022
+ state.reasoning += event.delta.text;
1023
+ flush();
1024
+ }
1025
+ break;
1026
+ case "response.reasoning.done":
1027
+ if (event.text) {
1028
+ state.reasoning += event.text;
1029
+ flush();
1030
+ }
1031
+ break;
1032
+ case "response.output_item.added":
1033
+ case "response.output_item.done": {
1034
+ const item = event.item;
1035
+ if (!state.content) {
1036
+ const itemText = extractTextFromOutputItem(item);
1037
+ if (itemText) {
1038
+ state.content = itemText;
1039
+ state.contentBuffer = seg(state.content);
1040
+ if (!loggedFirstVisibleDelta) {
1041
+ loggedFirstVisibleDelta = true;
1042
+ logQuickChatPerfStage(
1043
+ quickChatPerfStartedAt,
1044
+ "openai-response-first-visible-delta",
1045
+ { dialogKey }
1046
+ );
1047
+ }
1048
+ flush();
1049
+ }
1050
+ }
1051
+ if (item?.type === "function_call") {
1052
+ ensureToolCall(state, item.call_id || item.id, {
1053
+ id: item.call_id || item.id,
1054
+ function: {
1055
+ name: item.name || "",
1056
+ arguments: typeof item.arguments === "string" ? item.arguments : ""
1057
+ }
1058
+ });
1059
+ }
1060
+ break;
1061
+ }
1062
+ case "response.function_call_arguments.delta": {
1063
+ const key = event.call_id || event.item_id || `${event.output_index ?? 0}`;
1064
+ const toolCall = ensureToolCall(state, key, {
1065
+ id: event.call_id || key,
1066
+ function: { name: event.name || "", arguments: "" }
1067
+ });
1068
+ toolCall.function.arguments += event.delta ?? "";
1069
+ break;
1070
+ }
1071
+ case "response.function_call_arguments.done": {
1072
+ const key = event.call_id || event.item_id || `${event.output_index ?? 0}`;
1073
+ ensureToolCall(state, key, {
1074
+ id: event.call_id || key,
1075
+ function: {
1076
+ name: event.name || "",
1077
+ arguments: typeof event.arguments === "string" ? event.arguments : typeof event.output?.arguments === "string" ? event.output.arguments : ""
1078
+ }
1079
+ });
1080
+ break;
1081
+ }
1082
+ case "response.completed":
1083
+ state.completedResponse = event.response ?? null;
1084
+ finishReason = event.response?.status === "completed" ? "stop" : event.response?.status ?? null;
1085
+ if (event.response?.usage) {
1086
+ state.usage = updateTotalUsage(state.usage, event.response.usage);
1087
+ }
1088
+ break;
1089
+ case "response.failed":
1090
+ state.content += `
1091
+ [API Failed: ${event.response?.error?.message || "unknown"}]`;
1092
+ finishReason = "error";
1093
+ await finalize();
1094
+ return buildMeta(false, false, finishReason);
1095
+ case "response.incomplete":
1096
+ state.content += `
1097
+ [Incomplete: ${event.response?.incomplete_details?.reason || "unknown"}]`;
1098
+ finishReason = "incomplete";
1099
+ await finalize();
1100
+ return buildMeta(false, false, finishReason);
1101
+ default:
1102
+ break;
1103
+ }
1104
+ }
1105
+ }
1106
+ } catch (error) {
1107
+ if (canRetryInitialResponseAttempt(attempt, loggedFirstVisibleDelta, finishReason) && isRetryableInitialStreamError(
1108
+ error ?? new Error("response stream ended before first visible delta")
1109
+ )) {
1110
+ await safeCancel(reader);
1111
+ reader = void 0;
1112
+ resetStateForRetry();
1113
+ await waitForInitialStreamRetry(1500, signal);
1114
+ continue;
1115
+ }
1116
+ throw error;
1117
+ }
1118
+ }
1119
+ return buildMeta(false, false, null);
1120
+ } catch (error) {
1121
+ state.content += isAbortError(error) ? "[\u7528\u6237\u4E2D\u65AD]" : `[\u5F02\u5E38: ${error?.message || "unknown"}]`;
1122
+ await finalize();
1123
+ return buildMeta(false, false, "error");
1124
+ } finally {
1125
+ logQuickChatPerfStage(quickChatPerfStartedAt, "openai-response-stream-finished", {
1126
+ dialogKey
1127
+ });
1128
+ dispatch(removeActiveController({ messageId, dialogKey }));
1129
+ await safeCancel(reader);
1130
+ }
1131
+ };
1132
+
1133
+ // packages/ai/agent/cleanAgentMessages.ts
1134
+ var isEmptyContent = (content) => {
1135
+ if (content == null) return true;
1136
+ if (typeof content === "string") {
1137
+ return content.trim().length === 0;
1138
+ }
1139
+ if (Array.isArray(content)) {
1140
+ return content.length === 0;
1141
+ }
1142
+ return false;
1143
+ };
1144
+ var buildAgentViewMessages = (allMessages, currentAgentKey) => {
1145
+ const result = [];
1146
+ for (const msg of allMessages) {
1147
+ if (!msg) continue;
1148
+ const role = msg.role;
1149
+ if (!role) continue;
1150
+ const hasToolCalls = Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 || Array.isArray(msg.toolCalls) && msg.toolCalls.length > 0;
1151
+ const empty = isEmptyContent(msg.content);
1152
+ if (role === "assistant" && empty && !hasToolCalls) {
1153
+ continue;
1154
+ }
1155
+ const isCurrentAgent = msg.cybotKey === currentAgentKey;
1156
+ if (role === "user") {
1157
+ result.push(msg);
1158
+ continue;
1159
+ }
1160
+ if (role === "assistant") {
1161
+ if (isCurrentAgent) {
1162
+ result.push(msg);
1163
+ } else {
1164
+ const cloned = { ...msg };
1165
+ if (cloned.tool_calls) {
1166
+ delete cloned.tool_calls;
1167
+ }
1168
+ if (cloned.toolCalls) {
1169
+ delete cloned.toolCalls;
1170
+ }
1171
+ const rawAgentName = cloned.agentName;
1172
+ const agentName = rawAgentName && String(rawAgentName).trim() ? String(rawAgentName).trim() : "\u5176\u4ED6 Agent";
1173
+ if (typeof cloned.content === "string") {
1174
+ const trimmed = cloned.content.trim();
1175
+ if (trimmed) {
1176
+ cloned.content = `\u3010${agentName}\u3011 ${trimmed}`;
1177
+ } else {
1178
+ cloned.content = `\u3010${agentName}\u3011\uFF08\u4F7F\u7528\u4E86\u5DE5\u5177\u751F\u6210\u56DE\u590D\uFF09`;
1179
+ }
1180
+ } else {
1181
+ cloned.content = `\u3010${agentName}\u3011\uFF08\u4F7F\u7528\u4E86\u5DE5\u5177\u751F\u6210\u56DE\u590D\uFF09`;
1182
+ }
1183
+ result.push(cloned);
1184
+ }
1185
+ continue;
1186
+ }
1187
+ if (role === "tool") {
1188
+ if (isCurrentAgent) {
1189
+ result.push(msg);
1190
+ } else {
1191
+ continue;
1192
+ }
1193
+ continue;
1194
+ }
1195
+ result.push(msg);
1196
+ }
1197
+ return result;
1198
+ };
1199
+
1200
+ // packages/ai/agent/quickChatModelOverride.ts
1201
+ function applyQuickChatModelOverride(base, override) {
1202
+ return applyModelLayerOverride(
1203
+ base,
1204
+ override
1205
+ );
1206
+ }
1207
+
1208
+ // packages/ai/agent/canvasEditingContext.ts
1209
+ function buildCanvasNodeEditingContextSummary(runtimeOptions) {
1210
+ if (runtimeOptions?.editingTarget?.kind !== "canvas_node") return null;
1211
+ const editingTarget = runtimeOptions.editingTarget;
1212
+ const metadata = editingTarget.metadata ?? {};
1213
+ const selectedNodeId = typeof metadata.selectedNodeId === "string" ? metadata.selectedNodeId : editingTarget.key ?? "(\u672A\u77E5\u8282\u70B9)";
1214
+ const part = typeof metadata.part === "string" ? metadata.part : editingTarget.title ?? selectedNodeId;
1215
+ const nodeType = typeof metadata.type === "string" ? metadata.type : "(\u672A\u77E5\u7C7B\u578B)";
1216
+ const path = Array.isArray(metadata.path) ? metadata.path.filter((item) => typeof item === "string") : [];
1217
+ const props = asRecordOrEmpty(metadata.props);
1218
+ const style = asRecordOrEmpty(metadata.style);
1219
+ return [
1220
+ "\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1ACanvas Tree \u4E2D\u7684\u4E00\u4E2A\u9009\u4E2D\u8282\u70B9\u3002",
1221
+ `- \u8282\u70B9 ID: ${selectedNodeId}`,
1222
+ `- part: ${part}`,
1223
+ `- \u8282\u70B9\u7C7B\u578B: ${nodeType}`,
1224
+ ...path.length ? [`- \u8282\u70B9\u8DEF\u5F84: ${path.join(" > ")}`] : [],
1225
+ "",
1226
+ "\u5F53\u524D\u8282\u70B9 props:",
1227
+ JSON.stringify(props, null, 2),
1228
+ "",
1229
+ "\u5F53\u524D\u8282\u70B9 style:",
1230
+ JSON.stringify(style, null, 2),
1231
+ "",
1232
+ "\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
1233
+ `1. \u5982\u679C\u7528\u6237\u8981\u6C42\u4FEE\u6539\u5F53\u524D\u6A21\u5757\uFF0C\u53EA\u8F93\u51FA updateNode\uFF0C\u76EE\u6807 id \u5FC5\u987B\u662F ${selectedNodeId}\u3002`,
1234
+ "2. \u4E0D\u8981\u91CD\u5EFA root/shell\uFF0C\u4E0D\u8981\u91CD\u65B0 append \u5DF2\u5B58\u5728\u7684\u5927\u5757\u5185\u5BB9\u3002",
1235
+ "3. \u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u65B0\u589E\u5B50\u6A21\u5757\uFF0C\u5426\u5219\u4E0D\u8981 appendNode\u3002",
1236
+ "4. \u56DE\u590D\u4ECD\u5FC5\u987B\u9075\u5B88 Canvas Tree MVP \u534F\u8BAE\uFF1A\u53EA\u8F93\u51FA canvas_snapshot NDJSON\uFF0C\u4E0D\u8981\u8F93\u51FA\u89E3\u91CA\u6216\u6E90\u7801\u3002"
1237
+ ].join("\n");
1238
+ }
1239
+
1240
+ // packages/ai/agent/buildEditingContext.ts
1241
+ var buildAppConstraintPacks = (args) => {
1242
+ const imports = new Set(args.externalImports);
1243
+ const fileSet = new Set(args.fileNames);
1244
+ const packs = [
1245
+ {
1246
+ id: "repair-loop",
1247
+ title: "\u9884\u68C0\u4E0E\u5B9A\u70B9\u4FEE\u590D",
1248
+ rules: [
1249
+ "\u6BCF\u6B21\u6539\u5B8C\u4EE3\u7801\u540E\uFF0C\u5148\u8C03\u7528 appPreflight\uFF0C\u53EA\u6709\u9884\u68C0\u901A\u8FC7\u540E\u518D\u8C03\u7528 appDeploy\u3002",
1250
+ "\u5982\u679C preflight / deploy \u5931\u8D25\uFF0C\u4F18\u5148\u6839\u636E\u8FD4\u56DE\u7684 issues \u505A\u5B9A\u70B9\u4FEE\u590D\uFF0C\u7136\u540E\u91CD\u65B0 preflight\uFF1B\u4E0D\u8981\u65E0\u5173\u91CD\u5199\u6574\u9875\u5E94\u7528\u3002",
1251
+ "\u5982\u679C\u5DE5\u5177\u7ED3\u679C\u91CC\u5E26\u6709 repairPlan\uFF0C\u9ED8\u8BA4\u7ACB\u5373\u6267\u884C repairPlan \u4E2D\u7684\u5C40\u90E8\u4FEE\u590D\u6B65\u9AA4\uFF0C\u4E0D\u8981\u5148\u505C\u4E0B\u6765\u95EE\u7528\u6237\u3002",
1252
+ "\u5982\u679C\u5DE5\u5177\u7ED3\u679C\u660E\u786E\u8BF4\u660E\u662F HTML / \u975E JSON \u54CD\u5E94\u3001transport failure \u6216 retryable=false\uFF0C\u505C\u6B62\u81EA\u52A8 deploy \u91CD\u8BD5\uFF1B\u8FD9\u8BF4\u660E\u5F53\u524D\u662F\u5E73\u53F0\u901A\u9053\u5F02\u5E38\uFF0C\u4E0D\u662F\u4EE3\u7801\u95EE\u9898\u3002"
1253
+ ]
1254
+ },
1255
+ {
1256
+ id: "design-system",
1257
+ title: "\u8BBE\u8BA1\u7CFB\u7EDF\u4E0E\u5C0F\u6539\u52A8\u7EA6\u675F",
1258
+ rules: [
1259
+ "\u5148\u68C0\u67E5\u5F53\u524D\u5E94\u7528\u662F\u5426\u5DF2\u7ECF\u6709 theme / tokens / designSystem / \u5171\u4EAB\u6837\u5F0F\u5E38\u91CF\uFF1B\u5982\u679C\u5DF2\u6709\uFF0C\u4F18\u5148\u6CBF\u7528\u8FD9\u5957\u8BBE\u8BA1\u7CFB\u7EDF\uFF0C\u4E0D\u8981\u5E73\u884C\u518D\u9020\u4E00\u5957\u3002",
1260
+ "\u5982\u679C\u5F53\u524D\u5E94\u7528\u8FD8\u6CA1\u6709\u8BBE\u8BA1\u7CFB\u7EDF\uFF0C\u800C\u7528\u6237\u9700\u6C42\u6D89\u53CA UI / \u6837\u5F0F / \u65B0\u9875\u9762\uFF0C\u4F18\u5148\u8865\u4E00\u5C42\u6700\u5C0F\u5171\u4EAB token\uFF08colors\u3001typography\u3001spacing\u3001radius\u3001shadow\uFF09\uFF0C\u518D\u8BA9\u7EC4\u4EF6\u6D88\u8D39\u8FD9\u4E9B token\u3002",
1261
+ "\u5982\u679C\u5F53\u524D\u5E94\u7528\u662F\u65E7\u5199\u6CD5\uFF1A\u89C6\u89C9\u503C\u6563\u843D\u5728\u591A\u4E2A\u7EC4\u4EF6\u7684\u786C\u7F16\u7801 style / \u5E38\u91CF\u91CC\uFF0C\u800C\u672C\u6B21\u9700\u6C42\u53EA\u662F\u8C03\u5B57\u4F53\u3001\u989C\u8272\u3001\u95F4\u8DDD\u3001\u5706\u89D2\u3001\u9634\u5F71\uFF0C\u9ED8\u8BA4\u6267\u884C\u4E00\u6B21\u6700\u5C0F token \u8FC1\u79FB\uFF0C\u518D\u5728 token \u5C42\u5B8C\u6210\u8C03\u6574\uFF1B\u4E0D\u8981\u7EE7\u7EED\u628A\u65B0\u6570\u5B57\u6563\u843D\u5199\u56DE\u591A\u4E2A\u4F4D\u7F6E\u3002",
1262
+ "\u5F53\u7528\u6237\u53EA\u662F\u60F3\u8C03\u5B57\u4F53\u5927\u5C0F\u3001\u5B57\u91CD\u3001\u989C\u8272\u3001\u5706\u89D2\u3001\u9634\u5F71\u3001\u95F4\u8DDD\u7B49\u89C6\u89C9\u53C2\u6570\u65F6\uFF0C\u4F18\u5148\u4FEE\u6539 token \u6216\u547D\u4E2D\u7684\u5C40\u90E8\u7EC4\u4EF6\uFF0C\u4E0D\u8981\u987A\u624B\u91CD\u5199\u6574\u4E2A\u9875\u9762\u7ED3\u6784\u3002",
1263
+ "\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u6574\u4F53\u6539\u7248\u6216\u91CD\u505A\u98CE\u683C\uFF0C\u5426\u5219\u4E0D\u8981\u8FDE\u5E26\u4FEE\u6539\u5E03\u5C40\u3001\u7EC4\u4EF6\u6811\u3001\u6587\u6848\u3001\u6570\u636E\u6D41\u3001\u8DEF\u7531\u6216\u672A\u547D\u4E2D\u7684\u9875\u9762\u3002",
1264
+ "\u5982\u679C\u53EA\u662F\u5C0F\u6539\u4E00\u5904\uFF0C\u5C3D\u91CF\u628A\u53D8\u66F4\u6536\u655B\u5728\u5C11\u6570\u6587\u4EF6\uFF0C\u5E76\u4FDD\u6301\u672A\u547D\u4E2D\u6587\u4EF6\u7684\u7ED3\u6784\u4E0E\u547D\u540D\u7A33\u5B9A\u3002"
1265
+ ]
1266
+ }
1267
+ ];
1268
+ if (args.framework === "react-spa" || fileSet.has("main.tsx") || fileSet.has("App.tsx")) {
1269
+ packs.push({
1270
+ id: "react-spa-core",
1271
+ title: "React SPA \u5F62\u6001\u4FDD\u6301",
1272
+ rules: [
1273
+ '\u7EE7\u7EED\u6CBF\u7528 framework: "react-spa" + files\uFF0C\u4E0D\u8981\u9000\u56DE\u5355\u6587\u4EF6 Worker\u3002',
1274
+ "\u4FDD\u7559\u7A33\u5B9A\u5165\u53E3\u7ED3\u6784\uFF0C\u4F18\u5148\u7EF4\u62A4 main.tsx + App.tsx\uFF0C\u518D\u5C40\u90E8\u4FEE\u6539\u7EC4\u4EF6\u6587\u4EF6\u3002"
1275
+ ]
1276
+ });
1277
+ }
1278
+ if (imports.has("react-icons/lu")) {
1279
+ packs.push({
1280
+ id: "react-icons-lu",
1281
+ title: "Lucide \u56FE\u6807\u5B89\u5168\u89C4\u5219",
1282
+ rules: [
1283
+ "\u53EA\u80FD\u4F7F\u7528 react-icons/lu \u4E2D\u771F\u5B9E\u5B58\u5728\u7684\u56FE\u6807\u540D\uFF0C\u4E0D\u8981\u731C\u6D4B\u53D8\u4F53\u540D\u3002",
1284
+ "\u5982\u679C\u4E0D\u786E\u5B9A\u56FE\u6807\u540D\uFF0C\u4F18\u5148\u4F7F\u7528 LuCircle\u3001LuCheck\u3001LuX\u3001LuInfo\u3001LuArrowRight \u8FD9\u7C7B\u57FA\u7840\u56FE\u6807\u3002"
1285
+ ]
1286
+ });
1287
+ }
1288
+ if (imports.has("leaflet") || imports.has("react-leaflet")) {
1289
+ packs.push({
1290
+ id: "leaflet",
1291
+ title: "Leaflet \u5730\u56FE\u7EA6\u675F",
1292
+ rules: [
1293
+ "\u4E0D\u8981\u624B\u52A8 import leaflet.css\uFF1B\u5E73\u53F0\u4F1A\u81EA\u52A8\u6CE8\u5165 Leaflet \u6837\u5F0F\u3002",
1294
+ "\u4FEE\u6539\u5730\u56FE\u65F6\u4F18\u5148\u4FDD\u7559\u73B0\u6709\u5750\u6807\u3001\u7F29\u653E\u548C\u56FE\u5C42\u7ED3\u6784\uFF0C\u53EA\u505A\u5FC5\u8981\u7684\u4EA4\u4E92\u6216\u89C6\u89C9\u8C03\u6574\u3002"
1295
+ ]
1296
+ });
1297
+ }
1298
+ if (imports.has("@xyflow/react")) {
1299
+ packs.push({
1300
+ id: "xyflow",
1301
+ title: "Flow \u56FE\u7F16\u8F91\u7EA6\u675F",
1302
+ rules: [
1303
+ "\u4E0D\u8981\u65B0\u589E\u5916\u90E8 CSS import\uFF1B\u9700\u8981\u6837\u5F0F\u65F6\u76F4\u63A5\u8865\u6700\u5C0F\u5FC5\u8981\u5185\u8054\u6837\u5F0F\u6216\u7EC4\u4EF6\u5185 style \u6807\u7B7E\u3002",
1304
+ "\u4F18\u5148\u590D\u7528\u73B0\u6709\u8282\u70B9/\u8FB9\u6570\u636E\u7ED3\u6784\uFF0C\u907F\u514D\u91CD\u5199\u6574\u5957 flow \u753B\u5E03\u3002"
1305
+ ]
1306
+ });
1307
+ }
1308
+ if (imports.has("echarts") || imports.has("echarts-for-react")) {
1309
+ packs.push({
1310
+ id: "echarts",
1311
+ title: "\u56FE\u8868\u6539\u52A8\u7EA6\u675F",
1312
+ rules: [
1313
+ "\u4F18\u5148\u5C40\u90E8\u4FEE\u6539 option \u914D\u7F6E\u3001\u6570\u636E\u6620\u5C04\u548C\u7EC4\u4EF6 props\uFF0C\u4E0D\u8981\u91CD\u5199\u6574\u4E2A\u56FE\u8868\u9875\u9762\u3002",
1314
+ "\u54CD\u5E94\u5F0F\u5E03\u5C40\u4F18\u5148\u9760\u5BB9\u5668\u5C3A\u5BF8\u548C\u73B0\u6709\u7EC4\u4EF6\u7ED3\u6784\u8C03\u6574\uFF0C\u4E0D\u8981\u989D\u5916\u5F15\u5165 CSS \u6587\u4EF6\u3002"
1315
+ ]
1316
+ });
1317
+ }
1318
+ if (imports.has("docx") || imports.has("xlsx")) {
1319
+ packs.push({
1320
+ id: "file-processing",
1321
+ title: "\u6587\u6863/\u8868\u683C\u5904\u7406\u7EA6\u675F",
1322
+ rules: [
1323
+ "\u4E0D\u8981\u628A\u5927\u578B\u6570\u636E\u6216\u6A21\u677F\u5185\u5BB9\u76F4\u63A5\u5185\u5D4C\u8FDB\u4EE3\u7801\u5E38\u91CF\uFF1B\u4F18\u5148\u4FDD\u7559\u8FD0\u884C\u65F6\u52A0\u8F7D\u65B9\u5F0F\u3002",
1324
+ "\u4FEE\u6539\u5BFC\u5165\u5BFC\u51FA\u903B\u8F91\u65F6\uFF0C\u4F18\u5148\u6CBF\u7528\u73B0\u6709\u6587\u4EF6\u5904\u7406\u94FE\u8DEF\u548C\u6570\u636E\u7ED3\u6784\u3002"
1325
+ ]
1326
+ });
1327
+ }
1328
+ return packs;
1329
+ };
1330
+ var formatAppConstraintPacks = (packs) => {
1331
+ if (packs.length === 0) return [];
1332
+ return [
1333
+ "",
1334
+ "\u5F53\u524D\u6FC0\u6D3B\u7EA6\u675F\u5305\uFF08\u6309\u5F53\u524D\u5E94\u7528\u4F9D\u8D56/\u5F62\u6001\u52A8\u6001\u6CE8\u5165\uFF09\uFF1A",
1335
+ ...packs.flatMap((pack) => [
1336
+ `- ${pack.title}\uFF08${pack.id}\uFF09`,
1337
+ ...pack.rules.map((rule) => ` - ${rule}`)
1338
+ ])
1339
+ ];
1340
+ };
1341
+ var buildEditingContextSummary = (state, runtimeOptions) => {
1342
+ const targetKind = runtimeOptions?.editingTarget?.kind;
1343
+ if (targetKind === "table") {
1344
+ const table = selectCurrentTable(state);
1345
+ const rows = selectTableRows(state);
1346
+ const metadata = runtimeOptions?.editingTarget?.metadata;
1347
+ const focusContext = metadata && typeof metadata === "object" ? metadata.focusContext : null;
1348
+ if (!table) return null;
1349
+ const columns = Array.isArray(table.columns) ? table.columns : [];
1350
+ const columnSummaries = columns.length ? columns.map((c) => {
1351
+ const displayName = c.label || c.name;
1352
+ const type = c.type || "text";
1353
+ const requiredFlag = c.required ? "\u5FC5\u586B" : "\u53EF\u9009";
1354
+ const primaryFlag = c.isPrimary ? "\uFF0C\u4E3B\u5B57\u6BB5" : "";
1355
+ const optionsStr = Array.isArray(c.options) && c.options.length ? `\uFF0C\u53EF\u9009\u503C\uFF1A${c.options.join(" | ")}` : "";
1356
+ const descStr = c.description ? `\u3002\u8BF4\u660E\uFF1A${c.description}` : "";
1357
+ return `- ${c.name}\uFF08\u663E\u793A\u540D\uFF1A${displayName}\uFF0C\u7C7B\u578B\uFF1A${type}\uFF0C${requiredFlag}${primaryFlag}${optionsStr}${descStr}\uFF09`;
1358
+ }) : ["- (\u5F53\u524D\u8868\u5C1A\u672A\u5B9A\u4E49\u5B57\u6BB5)"];
1359
+ const sampleRows = Array.isArray(rows) ? rows.slice(0, 20) : [];
1360
+ const rowsPreview = sampleRows.length ? JSON.stringify(sampleRows, null, 2) : "(\u5F53\u524D\u8868\u6682\u65E0\u884C\u6570\u636E)";
1361
+ const tableTitle = table.displayName ?? table.tableId ?? "(\u672A\u547D\u540D\u8868)";
1362
+ const tableDesc = table.description ? `\u7528\u9014\u8BF4\u660E\uFF1A${table.description}` : "(\u6682\u65E0\u7528\u9014\u8BF4\u660E)";
1363
+ const tableTagsLine = Array.isArray(table.tags) && table.tags.length ? `- \u5173\u952E\u8BCD\u6807\u7B7E: ${table.tags.join(", ")}` : null;
1364
+ return [
1365
+ "\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u5F20\u6570\u636E\u8868\uFF08Editing Table\uFF09\u3002",
1366
+ `- \u8868 ID: ${table.tableId}`,
1367
+ `- \u663E\u793A\u540D\u79F0: ${tableTitle}`,
1368
+ `- ${tableDesc}`,
1369
+ ...tableTagsLine ? [tableTagsLine] : [],
1370
+ ...focusContext && typeof focusContext === "object" && "columnName" in focusContext ? [
1371
+ "",
1372
+ "\u5F53\u524D\u7126\u70B9\uFF08Focus Context\uFF09\uFF1A",
1373
+ `- \u5F53\u524D\u5355\u5143\u683C\u5217: ${String(focusContext.columnName ?? "(\u672A\u77E5\u5217)")}`,
1374
+ ...focusContext.rowTitle ? [`- \u5F53\u524D\u884C\u6807\u9898: ${String(focusContext.rowTitle)}`] : [],
1375
+ ...focusContext.rowIndex !== null && focusContext.rowIndex !== void 0 ? [`- \u5F53\u524D\u884C\u53F7: ${Number(focusContext.rowIndex) + 1}`] : [],
1376
+ ...focusContext.cellPreview ? [`- \u5F53\u524D\u5355\u5143\u683C\u5185\u5BB9\u9884\u89C8: ${String(focusContext.cellPreview)}`] : []
1377
+ ] : [],
1378
+ "",
1379
+ "\u5B57\u6BB5\u5B9A\u4E49\uFF08Field Schema\uFF09\uFF1A",
1380
+ ...columnSummaries,
1381
+ "",
1382
+ "\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
1383
+ "\u5F53\u7528\u6237\u5E0C\u671B\u5728\u5F53\u524D\u8868\u4E2D\u201C\u65B0\u589E\u4E00\u884C / \u65B0\u589E\u8BB0\u5F55 / \u63D2\u5165\u4E00\u6761 / \u5E2E\u6211\u8BB0\u4E00\u6761 xxx\u201D\u65F6\uFF1A",
1384
+ "1. \u5FC5\u987B\u8C03\u7528\u5DE5\u5177 addTableRow\uFF08\u800C\u4E0D\u662F\u53EA\u5728\u56DE\u7B54\u4E2D\u53E3\u5934\u63CF\u8FF0\u8981\u65B0\u589E\u7684\u6570\u636E\uFF09\u3002",
1385
+ "2. \u8C03\u7528 addTableRow \u65F6\uFF1A",
1386
+ " - \u4F7F\u7528\u53C2\u6570 values\uFF08\u4E00\u4E2A\u5BF9\u8C61\uFF09\uFF0C\u5176\u4E2D\u6BCF\u4E2A key \u5FC5\u987B\u662F\u4E0A\u9762\u5B57\u6BB5\u540D\u4E4B\u4E00\uFF08name\uFF0C\u800C\u4E0D\u662F label\uFF09\u3002",
1387
+ ' - \u4F8B\u5982\uFF1A{"values":{"title":"\u4FEE Bug #123","status":"todo","note":"\u9AD8\u4F18\u5148\u7EA7"}}\u3002',
1388
+ " - \u5C3D\u91CF\u4ECE\u7528\u6237\u7684\u81EA\u7136\u8BED\u8A00\u4E2D\u63A8\u65AD\u5E76\u586B\u6EE1\u6240\u6709\u76F8\u5173\u5B57\u6BB5\uFF1B\u5BF9\u4E8E\u5FC5\u586B\u5B57\u6BB5\uFF08required=true\uFF09\u5C24\u5176\u8981\u6CE8\u610F\u3002",
1389
+ ' - \u7528\u6237\u6CA1\u6709\u63D0\u5230\u7684\u5B57\u6BB5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u7A7A\u5B57\u7B26\u4E32 "" \u6216 null \u4F5C\u4E3A\u5360\u4F4D\u3002',
1390
+ " - \u7EDD\u4E0D\u8981\u4F20\u5165\u7A7A\u5BF9\u8C61 {} \u4F5C\u4E3A values\u3002",
1391
+ "",
1392
+ "\u4EE5\u4E0B\u662F\u90E8\u5206\u793A\u4F8B\u884C\uFF08\u6700\u591A 20 \u884C\uFF0C\u7528\u4E8E\u5E2E\u52A9\u4F60\u7406\u89E3\u5217\u542B\u4E49\uFF0C\u8BF7\u907F\u514D\u5728\u56DE\u7B54\u4E2D\u5B8C\u6574\u7C98\u8D34\u6574\u8868\uFF09\uFF1A",
1393
+ rowsPreview
1394
+ ].join("\n");
1395
+ }
1396
+ if (targetKind === "page" || targetKind === "article") {
1397
+ const page = getDocState();
1398
+ const metadata = runtimeOptions?.editingTarget?.metadata;
1399
+ const focusContext = metadata && typeof metadata === "object" ? metadata.focusContext : null;
1400
+ if (!page) return null;
1401
+ const title = page.title ?? "(\u672A\u547D\u540D\u9875\u9762)";
1402
+ return [
1403
+ "\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u4E2A\u9875\u9762 / \u6587\u7AE0\uFF08Editing Document\uFF09\u3002",
1404
+ `- \u6807\u9898: ${title}`,
1405
+ ...focusContext && typeof focusContext === "object" && "anchorPath" in focusContext ? [
1406
+ "",
1407
+ "\u5F53\u524D\u7126\u70B9\uFF08Focus Context\uFF09\uFF1A",
1408
+ `- \u5149\u6807\u662F\u5426\u6298\u53E0: ${Boolean(focusContext.isCollapsed) ? "\u662F" : "\u5426"}`,
1409
+ ...focusContext.blockType ? [`- \u5F53\u524D\u5757\u7C7B\u578B: ${String(focusContext.blockType)}`] : [],
1410
+ ...focusContext.selectedText ? [`- \u5F53\u524D\u9009\u4E2D\u6587\u672C: ${String(focusContext.selectedText)}`] : [],
1411
+ ...focusContext.anchorPath?.length ? [`- \u5F53\u524D\u951A\u70B9\u8DEF\u5F84: ${focusContext.anchorPath.join(" > ")}`] : []
1412
+ ] : [],
1413
+ "",
1414
+ "\u5982\u679C\u7528\u6237\u8981\u6C42\u4F60\u5BF9\u8FD9\u7BC7\u6587\u7AE0\u8FDB\u884C\u4FEE\u6539\u6216\u4F18\u5316\uFF0C\u8BF7\u5728\u56DE\u7B54\u4E2D\u660E\u786E\u6307\u51FA\u4FEE\u6539\u65B9\u5411\u3002",
1415
+ "\u5982\u679C\u5B58\u5728\u5F53\u524D\u9009\u533A\u6216\u5149\u6807\u4E0A\u4E0B\u6587\uFF0C\u4F18\u5148\u56F4\u7ED5\u8BE5\u5C40\u90E8\u4F4D\u7F6E\u505A\u5B9A\u70B9\u6539\u5199\uFF0C\u800C\u4E0D\u662F\u6CDB\u6CDB\u91CD\u5199\u6574\u7BC7\u6587\u6863\u3002"
1416
+ ].join("\n");
1417
+ }
1418
+ if (targetKind === "app") {
1419
+ const editingTarget = runtimeOptions?.editingTarget;
1420
+ const metadata = editingTarget?.metadata;
1421
+ const appId = editingTarget?.key ?? "(\u672A\u77E5 appId)";
1422
+ const title = editingTarget?.title ?? "(\u672A\u547D\u540D\u5E94\u7528)";
1423
+ const framework = typeof metadata?.framework === "string" ? metadata.framework : "worker";
1424
+ const appUrl = typeof metadata?.appUrl === "string" ? metadata.appUrl : null;
1425
+ const fileNames = Array.isArray(metadata?.fileNames) ? metadata.fileNames.filter((name) => typeof name === "string") : [];
1426
+ const externalImports = Array.isArray(metadata?.externalImports) ? metadata.externalImports.filter(
1427
+ (name) => typeof name === "string"
1428
+ ) : [];
1429
+ const sourceSummary = asOptionalTrimmedString(editingTarget?.summary) ?? null;
1430
+ const selectedNode = metadata && typeof metadata === "object" && metadata.selectedNode && typeof metadata.selectedNode === "object" ? metadata.selectedNode : null;
1431
+ const constraintPacks = buildAppConstraintPacks({
1432
+ framework,
1433
+ fileNames,
1434
+ externalImports
1435
+ });
1436
+ if (selectedNode && typeof selectedNode.cssPath === "string") {
1437
+ const tagName = typeof selectedNode.tagName === "string" && selectedNode.tagName ? selectedNode.tagName : "\u5143\u7D20";
1438
+ const cssPath = String(selectedNode.cssPath);
1439
+ const outerHTMLSnippet = typeof selectedNode.outerHTMLSnippet === "string" ? selectedNode.outerHTMLSnippet : "";
1440
+ const textSnippet = typeof selectedNode.textSnippet === "string" ? selectedNode.textSnippet : "";
1441
+ const noloLoc = typeof selectedNode.noloLoc === "string" ? selectedNode.noloLoc : "";
1442
+ constraintPacks.push({
1443
+ id: "selected-node",
1444
+ title: "\u7528\u6237\u9009\u4E2D\u8282\u70B9\uFF08\u5B9A\u70B9\u4FEE\u6539\uFF09",
1445
+ rules: [
1446
+ `\u7528\u6237\u5DF2\u5728\u9884\u89C8\u4E2D\u7CBE\u51C6\u9009\u4E2D\u4E00\u4E2A\u5143\u7D20\uFF1A<${tagName}> \uFF0CCSS \u8DEF\u5F84\uFF1A${cssPath}${noloLoc ? `\uFF0C\u6E90\u7801\u4F4D\u7F6E\uFF1A${noloLoc}` : ""}\u3002\u672C\u8F6E\u4FEE\u6539\u5FC5\u987B\u4EE5\u8FD9\u4E2A\u5143\u7D20\u4E3A\u4E2D\u5FC3\u3002`,
1447
+ `\u9009\u4E2D\u5143\u7D20\u7684 HTML \u7247\u6BB5\uFF08\u53EF\u80FD\u622A\u65AD\uFF09\uFF1A${outerHTMLSnippet}${textSnippet ? `\uFF1B\u53EF\u89C1\u6587\u672C\uFF1A${textSnippet}` : ""}\u3002\u5148\u5728\u6E90\u7801\u6587\u4EF6\u4E2D\u5B9A\u4F4D\u5230\u751F\u6210\u8FD9\u6BB5 HTML \u7684\u4EE3\u7801\uFF0C\u518D\u52A8\u624B\u3002`,
1448
+ "\u4FEE\u6539\u6536\u655B\u5728\u8BE5\u5143\u7D20\u53CA\u5176\u76F4\u63A5\u6837\u5F0F\u6765\u6E90\uFF08\u547D\u4E2D\u7684\u7EC4\u4EF6/\u7C7B/design token\uFF09\uFF1B\u8C03\u89C6\u89C9\u53C2\u6570\u4F18\u5148\u6539 token \u6216\u5C40\u90E8\u7EC4\u4EF6\u3002",
1449
+ "\u7981\u6B62\u91CD\u5199\u672A\u547D\u4E2D\u7684\u9875\u9762\u7ED3\u6784\u3001\u5E03\u5C40\u3001\u6587\u6848\u3001\u6570\u636E\u6D41\u6216\u5176\u4ED6\u7EC4\u4EF6\uFF1B\u4FDD\u6301\u672A\u547D\u4E2D\u6587\u4EF6\u4E0D\u53D8\u3002",
1450
+ "\u5982\u679C\u6309 CSS \u8DEF\u5F84\u548C HTML \u7247\u6BB5\u5728\u6E90\u7801\u4E2D\u627E\u4E0D\u5230\u5BF9\u5E94\u4F4D\u7F6E\uFF0C\u5148\u5411\u7528\u6237\u8BF4\u660E\u5E76\u8BF7\u7528\u6237\u91CD\u65B0\u9009\u62E9\uFF0C\u4E0D\u8981\u51ED\u731C\u6D4B\u5927\u8303\u56F4\u6539\u52A8\u3002"
1451
+ ]
1452
+ });
1453
+ }
1454
+ return [
1455
+ "\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u4E2A Web \u5E94\u7528\uFF08Editing App\uFF09\u3002",
1456
+ `- \u5E94\u7528 ID: ${appId}`,
1457
+ `- \u540D\u79F0: ${title}`,
1458
+ `- \u6280\u672F\u5F62\u6001: ${framework}`,
1459
+ ...appUrl ? [`- \u5F53\u524D\u8BBF\u95EE\u5730\u5740: ${appUrl}`] : [],
1460
+ ...fileNames.length ? [`- \u5F53\u524D\u6E90\u7801\u6587\u4EF6: ${fileNames.join(", ")}`] : ["- \u5F53\u524D\u6E90\u7801\u6587\u4EF6: (\u672A\u63D0\u4F9B\u591A\u6587\u4EF6\u6E05\u5355\uFF1B\u53EF\u80FD\u662F\u5355\u6587\u4EF6\u6E90\u7801\uFF0C\u4E5F\u53EF\u80FD\u53EA\u5269\u90E8\u7F72\u4EA7\u7269)"],
1461
+ ...externalImports.length ? [`- \u5F53\u524D\u4F9D\u8D56\u767D\u540D\u5355\u547D\u4E2D: ${externalImports.join(", ")}`] : [],
1462
+ ...sourceSummary ? ["", sourceSummary] : [],
1463
+ "",
1464
+ "\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
1465
+ "1. \u7528\u6237\u8981\u6C42\u4FEE\u6539\u5F53\u524D\u5E94\u7528\u65F6\uFF0C\u5148\u8C03\u7528 appRead \u83B7\u53D6\u5F53\u524D\u4EE3\u7801/\u6587\u4EF6\uFF0C\u518D\u57FA\u4E8E\u73B0\u6709\u5B9E\u73B0\u4FEE\u6539\u3002",
1466
+ "2. \u5982\u679C appRead \u8FD4\u56DE workspaceRef/sourceFiles/sourceOmitted\uFF0C\u4E0D\u8981\u6574\u7AD9\u91CD\u5199\uFF1B\u4F7F\u7528 App Builder \u7684\u53D7\u9650 workspace \u6587\u4EF6\u5DE5\u5177\uFF1AappFileList=listFiles\u3001appFileSearch=searchFiles\u3001appFileRead=readFile\u3001appFileReplace=editFile\u3001appFileWrite=writeFile\u3002\u5148\u5B9A\u4F4D\u6587\u4EF6\u4E0E\u547D\u4E2D\u884C\uFF0C\u5927\u6587\u4EF6\u53EA\u8BFB\u53D6\u5FC5\u8981\u884C\u8303\u56F4\uFF1B\u6587\u5B57\u3001\u6837\u5F0F\u3001token\u3001\u5C40\u90E8\u903B\u8F91\u7B49\u5C0F\u6539\u52A8\u5FC5\u987B\u4F18\u5148\u7528 appFileReplace \u7CBE\u786E\u66FF\u6362\u552F\u4E00\u7247\u6BB5\uFF0C\u53EA\u6709\u65B0\u5EFA\u6587\u4EF6\u6216\u786E\u5B9E\u9700\u8981\u6574\u6587\u4EF6\u91CD\u5199\u65F6\u624D\u7528 appFileWrite\u3002",
1467
+ "3. \u5148\u8BC6\u522B\u5F53\u524D\u5E94\u7528\u662F\u5426\u5DF2\u6709 theme / tokens / design system\uFF1B\u5DF2\u6709\u5C31\u4F18\u5148\u6539\u8FD9\u5C42\uFF0C\u6CA1\u6709\u518D\u8865\u4E00\u5C42\u6700\u5C0F\u5171\u4EAB token\uFF0C\u518D\u57FA\u4E8E token \u8C03\u6574\u7EC4\u4EF6\u3002",
1468
+ "4. \u5982\u679C\u5F53\u524D\u5E94\u7528\u8FD8\u662F\u65E7\u5199\u6CD5\uFF1A\u89C6\u89C9\u503C\u6563\u843D\u5728\u7EC4\u4EF6\u786C\u7F16\u7801 style \u91CC\uFF0C\u800C\u7528\u6237\u53EA\u662F\u505A\u5B57\u4F53/\u989C\u8272/\u95F4\u8DDD\u7B49\u89C6\u89C9\u5FAE\u8C03\uFF0C\u9ED8\u8BA4\u5148\u628A\u547D\u4E2D\u7684\u89C6\u89C9\u503C\u62BD\u5230\u6700\u5C0F token \u5C42\uFF0C\u518D\u5B8C\u6210\u672C\u6B21\u4FEE\u6539\uFF1B\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4E0D\u8981\u91CD\u6784\u3002",
1469
+ `5. \u91CD\u65B0\u90E8\u7F72\u5F53\u524D\u5E94\u7528\u65F6\uFF0CappDeploy \u5FC5\u987B\u7EE7\u7EED\u4F20\u540C\u4E00\u4E2A appId\uFF08${appId}\uFF09\uFF0C\u907F\u514D\u521B\u5EFA\u65B0\u5E94\u7528\u3002`,
1470
+ framework === "nolo-react" ? "6. \u5F53\u524D\u5E94\u7528\u662F Nolo React SSR\uFF0C\u4FEE\u6539\u65F6\u4F18\u5148\u4F7F\u7528\u53D7\u9650 app workspace \u6587\u4EF6\u5DE5\u5177\u64CD\u4F5C\u6E90\u7801\u5DE5\u4F5C\u533A\uFF0C\u7136\u540E appPreflight/appDeploy\uFF1B\u4E0D\u8981\u9000\u56DE react-spa \u6216\u5355\u6587\u4EF6 Worker\u3002" : framework === "react-spa" ? '6. \u5F53\u524D\u5E94\u7528\u662F React SPA\uFF0C\u4FEE\u6539\u65F6\u7EE7\u7EED\u6CBF\u7528 framework: "react-spa" + files\uFF0C\u4E0D\u8981\u9000\u56DE\u5355\u6587\u4EF6 Worker\u3002' : "6. \u5F53\u524D\u5E94\u7528\u76EE\u524D\u662F Worker \u5F62\u6001\uFF1B\u5982\u679C\u9700\u6C42\u53D8\u6210\u590D\u6742\u4EA4\u4E92\u6216\u56FE\u8868\uFF0C\u53EF\u4EE5\u8BC4\u4F30\u5347\u7EA7\u4E3A React SPA\u3002",
1471
+ ...fileNames.length ? [] : [
1472
+ "7. \u5F53\u524D\u6CA1\u6709\u6E90\u7801\u6587\u4EF6\u6E05\u5355\u65F6\uFF0C\u5FC5\u987B\u5148\u7528 appRead \u5224\u65AD\u8BFB\u5230\u7684\u662F\u53EF\u7EF4\u62A4\u6E90\u7801\u8FD8\u662F\u90E8\u7F72\u4EA7\u7269 / \u6253\u5305 bundle\u3002",
1473
+ "8. \u5982\u679C appRead \u8FD4\u56DE\u7684\u662F HTML \u58F3\u3001importmap\u3001\u538B\u7F29 bundle \u6216\u660E\u663E\u4E0D\u662F\u539F\u59CB\u6E90\u7801\u6587\u4EF6\uFF0C\u7981\u6B62\u5728\u672A\u544A\u77E5\u7528\u6237\u98CE\u9669\u7684\u60C5\u51B5\u4E0B\u6574\u7AD9\u91CD\u5199\uFF1B\u5E94\u5148\u8BF4\u660E\u201C\u5F53\u524D\u7F3A\u5C11\u539F\u59CB\u6E90\u7801\u5FEB\u7167\uFF0C\u7EE7\u7EED\u4FEE\u6539\u66F4\u50CF\u6574\u4F53\u91CD\u5EFA\u201D\uFF0C\u7B49\u7528\u6237\u786E\u8BA4\u540E\u518D\u7EE7\u7EED\u3002"
1474
+ ],
1475
+ "9. \u5982\u679C\u7528\u6237\u53EA\u662F\u8981\u8C03\u5B57\u4F53\u5927\u5C0F\u3001\u914D\u8272\u3001\u5706\u89D2\u3001\u9634\u5F71\u3001\u7559\u767D\u7B49\u89C6\u89C9\u7EC6\u8282\uFF0C\u9ED8\u8BA4\u4F18\u5148\u6539\u8BBE\u8BA1 token \u6216\u547D\u4E2D\u7684\u5C40\u90E8\u7EC4\u4EF6\uFF1B\u5BF9\u65E7\u5199\u6CD5\u5E94\u7528\u5219\u4F18\u5148\u505A\u6700\u5C0F token \u8FC1\u79FB\uFF0C\u4E0D\u8981\u53EA\u6539\u6563\u843D\u786C\u7F16\u7801\u3002",
1476
+ "10. \u6BCF\u6B21\u4FEE\u6539\u5B8C\u6210\u540E\uFF0C\u5148 appPreflight\uFF0C\u518D appDeploy\uFF1B\u5982\u679C\u5931\u8D25\uFF0C\u6309\u8FD4\u56DE issues \u5B9A\u70B9\u4FEE\u590D\u3002",
1477
+ "11. \u56DE\u590D\u7528\u6237\u65F6\u4F18\u5148\u8BF4\u660E\u505A\u4E86\u4EC0\u4E48\u53D8\u5316\u3001\u73B0\u5728\u5E94\u7528\u53EF\u4EE5\u600E\u4E48\u7528\uFF0C\u800C\u4E0D\u662F\u76F4\u63A5\u5806\u4EE3\u7801\u3002",
1478
+ ...formatAppConstraintPacks(constraintPacks)
1479
+ ].join("\n");
1480
+ }
1481
+ if (targetKind === "image" || targetKind === "file") {
1482
+ const editingTarget = runtimeOptions?.editingTarget;
1483
+ const metadata = editingTarget?.metadata;
1484
+ const title = editingTarget?.title ?? "(\u672A\u547D\u540D\u5BF9\u8C61)";
1485
+ const objectKey = editingTarget?.key ?? "(\u672A\u77E5 key)";
1486
+ const fileId = typeof metadata?.fileId === "string" ? metadata.fileId : null;
1487
+ const url = typeof metadata?.url === "string" ? metadata.url : null;
1488
+ const size = typeof metadata?.size === "number" ? metadata.size : null;
1489
+ return [
1490
+ `\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u4E2A${targetKind === "image" ? "\u56FE\u7247" : "\u6587\u4EF6"}\u5BF9\u8C61\uFF08Editing ${targetKind === "image" ? "Image" : "File"}\uFF09\u3002`,
1491
+ `- \u5BF9\u8C61 key: ${objectKey}`,
1492
+ `- \u6807\u9898: ${title}`,
1493
+ ...fileId ? [`- fileId: ${fileId}`] : [],
1494
+ ...url ? [`- \u8D44\u6E90\u5730\u5740: ${url}`] : [],
1495
+ ...size !== null ? [`- \u6587\u4EF6\u5927\u5C0F: ${size} bytes`] : [],
1496
+ "",
1497
+ "\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
1498
+ targetKind === "image" ? "\u5F53\u524D\u9636\u6BB5\u4F18\u5148\u5E2E\u52A9\u7528\u6237\u7406\u89E3\u56FE\u7247\u5185\u5BB9\u3001\u63D0\u70BC\u91CD\u70B9\u3001\u547D\u540D\u5F52\u7C7B\u548C\u4E0B\u4E00\u6B65\u5904\u7406\u5EFA\u8BAE\u3002\u4E0D\u8981\u5047\u88C5\u5DF2\u7ECF\u5B8C\u6210\u590D\u6742\u56FE\u7247\u7F16\u8F91\u3002" : "\u5F53\u524D\u9636\u6BB5\u4F18\u5148\u5E2E\u52A9\u7528\u6237\u7406\u89E3\u6587\u4EF6\u7528\u9014\u3001\u63D0\u53D6\u5904\u7406\u601D\u8DEF\u3001\u7ED9\u51FA\u6574\u7406\u5EFA\u8BAE\u548C\u4E0B\u4E00\u6B65\u64CD\u4F5C\u5EFA\u8BAE\u3002\u4E0D\u8981\u5047\u88C5\u5DF2\u7ECF\u5B8C\u6574\u89E3\u6790\u6587\u4EF6\u5185\u5BB9\u3002"
1499
+ ].join("\n");
1500
+ }
1501
+ if (targetKind === "canvas_node") {
1502
+ return buildCanvasNodeEditingContextSummary(runtimeOptions);
1503
+ }
1504
+ return null;
1505
+ };
1506
+
1507
+ // packages/ai/agent/appWorkingMemory.ts
1508
+ var APP_TOOL_NAMES = /* @__PURE__ */ new Set([
1509
+ "appList",
1510
+ "appRead",
1511
+ "appDeploy",
1512
+ "appPreflight",
1513
+ "appDelete"
1514
+ ]);
1515
+ var contentToText = (content) => {
1516
+ if (!content) return "";
1517
+ if (typeof content === "string") return content;
1518
+ if (Array.isArray(content)) {
1519
+ return content.map((part) => "text" in part ? part.text ?? "" : "").join("\n");
1520
+ }
1521
+ return "";
1522
+ };
1523
+ var parseAppListEntries = (text) => text.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("- **") && line.includes("(appId:"));
1524
+ var buildRecentAppToolMemory = (messages, toolRuns) => {
1525
+ const messageById = new Map(messages.map((msg) => [msg.id, msg]));
1526
+ const recentRuns = [...toolRuns].filter((run) => APP_TOOL_NAMES.has(run.toolName)).sort((a, b) => (b.startedAt ?? 0) - (a.startedAt ?? 0)).slice(0, 8);
1527
+ if (recentRuns.length === 0) return null;
1528
+ const lines = [
1529
+ "\u8FD9\u4E9B\u4FE1\u606F\u6765\u81EA\u5F53\u524D\u5BF9\u8BDD\u91CC\u6700\u8FD1\u7684 app \u5DE5\u5177\u8C03\u7528\uFF0C\u4E0D\u4F9D\u8D56\u53F3\u4FA7\u7F16\u8F91\u6001\u3002"
1530
+ ];
1531
+ const latestDeployLike = recentRuns.find(
1532
+ (run) => ["appDeploy", "appRead", "appPreflight"].includes(run.toolName)
1533
+ );
1534
+ if (latestDeployLike) {
1535
+ const input = latestDeployLike.input ?? {};
1536
+ const parts = [
1537
+ `- \u6700\u8FD1\u4E00\u6B21\u5173\u952E app \u64CD\u4F5C: ${latestDeployLike.toolName}`,
1538
+ typeof input.appId === "string" ? `appId=${input.appId}` : null,
1539
+ typeof input.name === "string" ? `name=${input.name}` : null,
1540
+ typeof input.framework === "string" ? `framework=${input.framework}` : null
1541
+ ].filter(Boolean);
1542
+ lines.push(parts.join("\uFF0C"));
1543
+ }
1544
+ const relatedMessages = recentRuns.map((run) => messageById.get(run.messageId)).filter((msg) => !!msg);
1545
+ const appListMessage = relatedMessages.find((msg) => msg.toolName === "appList");
1546
+ if (appListMessage) {
1547
+ const entries = parseAppListEntries(contentToText(appListMessage.content)).slice(0, 5);
1548
+ if (entries.length > 0) {
1549
+ lines.push("- \u6700\u8FD1\u4E00\u6B21 appList \u7ED3\u679C\uFF1A");
1550
+ lines.push(...entries.map((entry) => ` ${entry}`));
1551
+ }
1552
+ }
1553
+ const latestReadMessage = relatedMessages.find((msg) => msg.toolName === "appRead");
1554
+ if (latestReadMessage) {
1555
+ const text = contentToText(latestReadMessage.content);
1556
+ const appId = text.match(/- appId:\s*(.+)/)?.[1]?.trim();
1557
+ const url = text.match(/- 访问地址:\s*(.+)/)?.[1]?.trim();
1558
+ if (appId || url) {
1559
+ lines.push(
1560
+ [
1561
+ "- \u6700\u8FD1\u4E00\u6B21 appRead \u771F\u503C:",
1562
+ appId ? `appId=${appId}` : null,
1563
+ url ? `url=${url}` : null
1564
+ ].filter(Boolean).join("\uFF0C")
1565
+ );
1566
+ }
1567
+ }
1568
+ const latestPreflightRun = recentRuns.find((run) => run.toolName === "appPreflight");
1569
+ if (latestPreflightRun) {
1570
+ lines.push(
1571
+ [
1572
+ "- \u6700\u8FD1\u4E00\u6B21 appPreflight:",
1573
+ latestPreflightRun.status === "failed" ? "\u5931\u8D25" : "\u5DF2\u6267\u884C",
1574
+ latestPreflightRun.outputSummary ? `\u6458\u8981=${latestPreflightRun.outputSummary}` : null
1575
+ ].filter(Boolean).join("\uFF0C")
1576
+ );
1577
+ }
1578
+ const latestDeployMessage = relatedMessages.find((msg) => msg.toolName === "appDeploy");
1579
+ if (latestDeployMessage) {
1580
+ const text = contentToText(latestDeployMessage.content);
1581
+ const appId = text.match(/- appId:\s*(.+)/)?.[1]?.trim();
1582
+ const url = text.match(/- 访问地址:\s*(.+)/)?.[1]?.trim();
1583
+ if (appId || url) {
1584
+ lines.push(
1585
+ [
1586
+ "- \u6700\u8FD1\u4E00\u6B21 appDeploy \u7ED3\u679C:",
1587
+ appId ? `appId=${appId}` : null,
1588
+ url ? `url=${url}` : null
1589
+ ].filter(Boolean).join("\uFF0C")
1590
+ );
1591
+ }
1592
+ }
1593
+ lines.push(
1594
+ "- \u5982\u679C\u7528\u6237\u8BF4\u201C\u521A\u624D\u90A3\u4E2A app / \u90A3\u4E2A\u7F51\u7AD9\u201D\uFF0C\u4F18\u5148\u628A\u5B83\u7406\u89E3\u4E3A\u4E0A\u9762\u6700\u8FD1\u4E00\u6B21\u88AB\u8BFB\u53D6\u3001\u9884\u68C0\u6216\u90E8\u7F72\u7684\u5E94\u7528\uFF1B\u82E5\u4ECD\u6709\u6B67\u4E49\uFF0C\u518D\u7528 appList \u6216 appRead \u786E\u8BA4\u3002"
1595
+ );
1596
+ return lines.join("\n");
1597
+ };
1598
+
1599
+ // packages/ai/agent/streamAgentChatTurnUtils.ts
1600
+ var BROWSER_UNAVAILABLE_CORE_TOOLS = {
1601
+ queryModelUsage: true,
1602
+ createAgentAutomation: true,
1603
+ notifyUser: true
1604
+ };
1605
+ var getRuntimeCoreTools = () => {
1606
+ if (typeof window === "undefined") {
1607
+ return [...TOOL_PACKS.CORE];
1608
+ }
1609
+ return TOOL_PACKS.CORE.filter(
1610
+ (toolName) => !BROWSER_UNAVAILABLE_CORE_TOOLS[toolName]
1611
+ );
1612
+ };
1613
+ var isInlineVisualArtifactAgent = (agentConfig) => {
1614
+ const tags = Array.isArray(agentConfig.tags) ? agentConfig.tags : [];
1615
+ return tags.some(
1616
+ (tag) => typeof tag === "string" && ["inline-artifact", "streaming-ui"].includes(tag)
1617
+ );
1618
+ };
1619
+ var estimateTokensOfMessage = (msg) => {
1620
+ let content = "";
1621
+ if (typeof msg.content === "string") {
1622
+ content = msg.content;
1623
+ } else if (Array.isArray(msg.content)) {
1624
+ content = msg.content.map((p) => {
1625
+ if (p.type === "text") return p.text || "";
1626
+ if (p.type === "image_url") return "[image]";
1627
+ return "[non-text]";
1628
+ }).join("");
1629
+ } else if (msg.content && typeof msg.content === "object") {
1630
+ content = JSON.stringify(msg.content);
1631
+ }
1632
+ let extraTokens = 0;
1633
+ if (Array.isArray(msg.tool_calls)) {
1634
+ const toolsStr = JSON.stringify(msg.tool_calls);
1635
+ extraTokens = estimateTokenCount(toolsStr);
1636
+ }
1637
+ return estimateTokenCount(content) + extraTokens;
1638
+ };
1639
+ var classifyConversationLoad = (messages) => {
1640
+ const N = 20;
1641
+ if (!Array.isArray(messages) || messages.length === 0) return "light";
1642
+ const tail = messages.slice(-N);
1643
+ const tokenSamples = tail.map(estimateTokensOfMessage);
1644
+ if (tokenSamples.length === 0) return "light";
1645
+ const sum = tokenSamples.reduce((acc, v) => acc + v, 0);
1646
+ const avg = sum / tokenSamples.length;
1647
+ const sorted = [...tokenSamples].sort((a, b) => a - b);
1648
+ const p95 = sorted[Math.floor((sorted.length - 1) * 0.95)];
1649
+ if (p95 < 200 && avg < 120) {
1650
+ return "light";
1651
+ }
1652
+ if (p95 > 2e3 || avg > 1200) {
1653
+ return "heavy";
1654
+ }
1655
+ return "medium";
1656
+ };
1657
+ var compressOldToolResults = (messages, maxChars = 800) => {
1658
+ let lastToolCallAssistantIdx = -1;
1659
+ for (let i = messages.length - 1; i >= 0; i--) {
1660
+ if (messages[i].role === "assistant" && Array.isArray(messages[i].tool_calls) && messages[i].tool_calls.length > 0) {
1661
+ lastToolCallAssistantIdx = i;
1662
+ break;
1663
+ }
1664
+ }
1665
+ return messages.map((msg, idx) => {
1666
+ if (msg.role !== "tool") return msg;
1667
+ if (idx > lastToolCallAssistantIdx) return msg;
1668
+ const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
1669
+ if (content.length <= maxChars) return msg;
1670
+ return {
1671
+ ...msg,
1672
+ content: content.slice(0, maxChars) + `
1673
+ \u2026[\u622A\u65AD\uFF0C\u539F\u59CB\u957F\u5EA6 ${content.length} \u5B57\u7B26]`
1674
+ };
1675
+ });
1676
+ };
1677
+ var trimMessagesWithSummary = (messages, contextWindow, summaryTokenCount) => {
1678
+ const recentLoad = classifyConversationLoad(messages);
1679
+ const { rawMessageBudget, minTailTokens } = planContextUsage({
1680
+ contextWindow,
1681
+ summaryTokens: summaryTokenCount,
1682
+ recentLoad
1683
+ });
1684
+ if (!Array.isArray(messages) || messages.length === 0) return messages;
1685
+ let totalTokens = 0;
1686
+ let keepCount = 0;
1687
+ for (let i = messages.length - 1; i >= 0; i--) {
1688
+ const t = estimateTokensOfMessage(messages[i]);
1689
+ if (totalTokens + t > rawMessageBudget) break;
1690
+ totalTokens += t;
1691
+ keepCount++;
1692
+ }
1693
+ if (keepCount >= messages.length) {
1694
+ return messages;
1695
+ }
1696
+ if (totalTokens < minTailTokens) {
1697
+ const maxBudgetWithSlack = rawMessageBudget * 1.2;
1698
+ for (let i = messages.length - 1 - keepCount; i >= 0; i--) {
1699
+ const t = estimateTokensOfMessage(messages[i]);
1700
+ if (totalTokens + t > maxBudgetWithSlack) break;
1701
+ totalTokens += t;
1702
+ keepCount++;
1703
+ if (totalTokens >= minTailTokens) break;
1704
+ }
1705
+ }
1706
+ if (keepCount === 0 && messages.length > 0) {
1707
+ keepCount = Math.min(2, messages.length);
1708
+ }
1709
+ let cutIndex = messages.length - keepCount;
1710
+ if (cutIndex < 0) cutIndex = 0;
1711
+ while (cutIndex < messages.length && messages[cutIndex].role === "tool") {
1712
+ cutIndex++;
1713
+ }
1714
+ return messages.slice(cutIndex);
1715
+ };
1716
+ var createDbSliceTurnContextSource = (dispatch) => ({
1717
+ readRecord: async (dbKey) => {
1718
+ const result = await dispatch(read({ dbKey })).unwrap();
1719
+ return result ?? null;
1720
+ }
1721
+ });
1722
+ var joinMapValues = (map) => Array.from(map.values()).join("");
1723
+ var hasImageInMessages = (messages) => {
1724
+ if (!Array.isArray(messages)) return false;
1725
+ return messages.some((msg) => {
1726
+ const content = msg.content;
1727
+ if (!Array.isArray(content)) return false;
1728
+ return content.some(
1729
+ (part) => part && typeof part === "object" && part.type === "image_url" && part.image_url && typeof part.image_url.url === "string" && part.image_url.url.trim() !== ""
1730
+ );
1731
+ });
1732
+ };
1733
+ var REJECT_NO_VISION_MESSAGE = "\u5F53\u524D Agent \u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF0C\u8BF7\u6539\u7528\u6587\u672C\u6216\u6587\u6863\u3002";
1734
+ function shouldRejectImageInputForAgent(agentConfig, messages) {
1735
+ const agentHasVision = resolveAgentImageInputSupport(agentConfig);
1736
+ if (!agentHasVision && hasImageInMessages(messages)) {
1737
+ return REJECT_NO_VISION_MESSAGE;
1738
+ }
1739
+ return null;
1740
+ }
1741
+ var formatCurrentInputContext = (pendingFiles, currentInputMap) => {
1742
+ if (pendingFiles.length === 0 || currentInputMap.size === 0) {
1743
+ return joinMapValues(currentInputMap);
1744
+ }
1745
+ const relevantPendingFiles = pendingFiles.filter((file) => {
1746
+ const key = file.sourceDialogKey || file.dialogKey || file.pageKey;
1747
+ return key && currentInputMap.has(key);
1748
+ });
1749
+ if (relevantPendingFiles.length === 0) {
1750
+ return joinMapValues(currentInputMap);
1751
+ }
1752
+ const filesByGroup = /* @__PURE__ */ new Map();
1753
+ for (const file of relevantPendingFiles) {
1754
+ const groupKey = file.groupId || file.id;
1755
+ const group = filesByGroup.get(groupKey);
1756
+ if (group) {
1757
+ group.push(file);
1758
+ } else {
1759
+ filesByGroup.set(groupKey, [file]);
1760
+ }
1761
+ }
1762
+ let sourceCounter = 1;
1763
+ let output = "";
1764
+ filesByGroup.forEach((filesInGroup) => {
1765
+ const isGroup = filesInGroup.length > 1;
1766
+ const sourceName = isGroup ? filesInGroup[0].name.split(" (")[0] : filesInGroup[0].name;
1767
+ output += `--- Source ${sourceCounter}: "${sourceName}" ---
1768
+ `;
1769
+ filesInGroup.forEach((file) => {
1770
+ const key = file.sourceDialogKey || file.dialogKey || file.pageKey;
1771
+ if (!key) return;
1772
+ const content = currentInputMap.get(key);
1773
+ if (!content) return;
1774
+ if (isGroup) {
1775
+ output += `### Document: "${file.name}"
1776
+ ${content}
1777
+ `;
1778
+ } else {
1779
+ output += `${content}
1780
+ `;
1781
+ }
1782
+ });
1783
+ output += `--- End of Source ${sourceCounter} ---
1784
+
1785
+ `;
1786
+ sourceCounter++;
1787
+ });
1788
+ return output;
1789
+ };
1790
+ var validateAccessAndBalance = (agentConfig, state) => {
1791
+ const userBalance = selectCurrentUserBalance(state);
1792
+ const currentUserId = selectIdentityUserId(state);
1793
+ const isCustomApi = agentConfig.apiSource === "custom";
1794
+ const isCliApi = agentConfig.apiSource === "cli";
1795
+ const isDeviceLocalOwner = agentConfig.userId === "local" && !currentUserId;
1796
+ const isOwner = isDeviceLocalOwner || Boolean(currentUserId) && agentConfig.userId === currentUserId;
1797
+ if (!isOwner) {
1798
+ const hasWhitelist = Array.isArray(agentConfig.whitelist) && agentConfig.whitelist.length > 0;
1799
+ if (hasWhitelist) {
1800
+ const isUserInWhitelist = !!currentUserId && agentConfig.whitelist?.includes(currentUserId);
1801
+ if (!isUserInWhitelist) {
1802
+ return "\u60A8\u4E0D\u5728\u8BE5\u5E94\u7528\u7684\u767D\u540D\u5355\u4E2D\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002";
1803
+ }
1804
+ }
1805
+ }
1806
+ if (isCustomApi || isCliApi) {
1807
+ return null;
1808
+ }
1809
+ const SUBSCRIPTION_OAUTH_REFS = /* @__PURE__ */ new Set([
1810
+ "cursor",
1811
+ "chatgpt",
1812
+ "xai",
1813
+ "antigravity",
1814
+ "claude"
1815
+ ]);
1816
+ if (SUBSCRIPTION_OAUTH_REFS.has((agentConfig.apiKeyRef ?? "").trim().toLowerCase())) {
1817
+ return null;
1818
+ }
1819
+ const isPlatformApi = agentConfig.apiSource === "platform" || agentConfig.useServerProxy === true;
1820
+ if (isDeviceLocalOwner && !isPlatformApi) {
1821
+ return null;
1822
+ }
1823
+ if (typeof userBalance !== "number") {
1824
+ const hasSessionUser = Boolean(
1825
+ state?.auth?.currentUser?.userId
1826
+ );
1827
+ if (!currentUserId || !hasSessionUser) {
1828
+ return "\u8BF7\u767B\u5F55\u540E\u4F7F\u7528\u5E73\u53F0\u6A21\u578B\uFF0C\u6216\u6539\u7528\u672C\u5730\u81EA\u5B9A\u4E49/API/CLI Agent\u3002";
1829
+ }
1830
+ return "\u6B63\u5728\u83B7\u53D6\u7528\u6237\u4F59\u989D\uFF0C\u8BF7\u7A0D\u5019...";
1831
+ }
1832
+ const serverPrices = getModelPricing(agentConfig.provider || "", agentConfig.model);
1833
+ if (!serverPrices && !hasExplicitAgentPricing(agentConfig)) {
1834
+ return "\u65E0\u6CD5\u83B7\u53D6\u6A21\u578B\u5B9A\u4EF7\u4FE1\u606F\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
1835
+ }
1836
+ const prices = getPrices(agentConfig, serverPrices ?? null);
1837
+ const maxPrice = getFinalPrice(prices);
1838
+ if (userBalance < maxPrice) {
1839
+ return "\u4F59\u989D\u4E0D\u8DB3\uFF0C\u8BF7\u5145\u503C\u540E\u518D\u8BD5\u3002";
1840
+ }
1841
+ return null;
1842
+ };
1843
+ var fetchMemoryOverlayContext = async (state, agentConfig, userInput, dialogConfig) => {
1844
+ const token = typeof state?.auth?.currentToken === "string" ? state.auth.currentToken : null;
1845
+ const currentServer = typeof state?.settings?.currentServer === "string" ? state.settings.currentServer : null;
1846
+ const agentKey = asOptionalTrimmedString(agentConfig.dbKey) ?? "";
1847
+ if (!token || !currentServer || !agentKey) return null;
1848
+ const baseUrl = resolveToolBaseUrl(currentServer);
1849
+ if (!baseUrl) return null;
1850
+ const inputText = typeof userInput === "string" ? userInput : JSON.stringify(userInput ?? "");
1851
+ const spaceId = asOptionalTrimmedString(dialogConfig?.spaceId) ?? (state?.space?.viewMode === "all" ? void 0 : asOptionalTrimmedString(state?.space?.currentSpaceId));
1852
+ try {
1853
+ const response = await fetch(`${baseUrl}/api/memory/query`, {
1854
+ method: "POST",
1855
+ headers: {
1856
+ "Content-Type": "application/json",
1857
+ Authorization: `Bearer ${token}`
1858
+ },
1859
+ body: JSON.stringify({
1860
+ agentKey,
1861
+ userInput: inputText,
1862
+ ...spaceId ? { spaceId } : {}
1863
+ })
1864
+ });
1865
+ if (!response.ok) return null;
1866
+ const payload = await response.json().catch(() => null);
1867
+ return asOptionalTrimmedString(payload?.promptBlock) ?? null;
1868
+ } catch {
1869
+ return null;
1870
+ }
1871
+ };
1872
+ var buildStaticContexts = async (state, dispatch, agentConfig, dialogConfig, referenceContentCache) => {
1873
+ const keySets = await getFullChatContextKeys(
1874
+ state,
1875
+ dispatch,
1876
+ agentConfig,
1877
+ "",
1878
+ // 静态上下文不需要 userInput
1879
+ void 0
1880
+ // 静态上下文不需要 dialogConfig
1881
+ );
1882
+ const finalKeys = deduplicateContextKeys(keySets);
1883
+ const fetchReferences = (keys) => fetchReferenceContents(keys, dispatch, {
1884
+ format: "simplified_markdown",
1885
+ inlineMentionMeta: true,
1886
+ preloaded: referenceContentCache
1887
+ });
1888
+ const [botInstructionsMap, botKnowledgeMap] = await Promise.all([
1889
+ fetchReferences(finalKeys.botInstructionsContext),
1890
+ fetchReferences(finalKeys.botKnowledgeContext)
1891
+ ]);
1892
+ const globalPrompt = selectGlobalPrompt(state);
1893
+ const userTonePreset = selectUserTonePreset(state);
1894
+ const knowledgeCaptureLevel = selectKnowledgeCaptureLevel(state);
1895
+ const spaceContextLevel = selectSpaceContextLevel(state);
1896
+ const userRecentLimit = selectAiRecentContentLimit(state);
1897
+ const contextWindow = getModelContextWindow(agentConfig.model) || 128e3;
1898
+ const preloadPlan = resolveSpaceContextPreloadPlan(spaceContextLevel);
1899
+ const dynamicLimit = Math.floor(contextWindow * preloadPlan.preloadBudgetRatio / 150);
1900
+ const recentLimit = preloadPlan.includeRecentContent ? Math.max(3, Math.min(userRecentLimit, Math.max(3, dynamicLimit))) : 0;
1901
+ const turnContextSource = createDbSliceTurnContextSource(dispatch);
1902
+ let spaceContext = null;
1903
+ if (spaceContextLevel > 1) {
1904
+ const spaceLayer = await buildSpaceContextLayer({
1905
+ source: turnContextSource,
1906
+ spaceId: dialogConfig?.spaceId,
1907
+ recentContentLimit: recentLimit
1908
+ });
1909
+ spaceContext = spaceLayer ? spaceLayer.content.trim() : null;
1910
+ }
1911
+ const linkedSpaceIds = agentConfig.linkedSpaces || [];
1912
+ if (linkedSpaceIds.length > 0 && spaceContextLevel > 1) {
1913
+ const linkedSection = await buildLinkedSpacesSection({
1914
+ source: turnContextSource,
1915
+ linkedSpaceIds
1916
+ });
1917
+ if (linkedSection) {
1918
+ spaceContext = (spaceContext ?? "") + `
1919
+
1920
+ ${linkedSection}`;
1921
+ }
1922
+ }
1923
+ const dialogPolicyContext = dialogConfig?.category === PERSONALIZATION_DIALOG_CATEGORY ? buildPersonalizationDialogPolicyContext() : null;
1924
+ return {
1925
+ botInstructionsContext: joinMapValues(botInstructionsMap),
1926
+ botKnowledgeContext: joinMapValues(botKnowledgeMap),
1927
+ spaceContext,
1928
+ userGlobalPrompt: globalPrompt,
1929
+ userPolicyContext: [
1930
+ buildStaticUserPolicyContext({
1931
+ agentConfig,
1932
+ settingsRecord: {
1933
+ userTonePreset,
1934
+ knowledgeCaptureLevel,
1935
+ spaceContextLevel,
1936
+ enableReadCurrentSpace: spaceContextLevel > 1
1937
+ }
1938
+ }),
1939
+ dialogPolicyContext
1940
+ ].filter(Boolean).join("\n")
1941
+ };
1942
+ };
1943
+ var buildDynamicContexts = async (state, dispatch, agentConfig, userInput, runtimeOptions, referenceContentCache, dialogKey) => {
1944
+ let dialogSummary = null;
1945
+ let dialogConfig;
1946
+ if (dialogKey) {
1947
+ dialogConfig = selectById(state, dialogKey);
1948
+ if (dialogConfig?.summary) {
1949
+ dialogSummary = dialogConfig.summary;
1950
+ }
1951
+ }
1952
+ const keySets = await getFullChatContextKeys(
1953
+ state,
1954
+ dispatch,
1955
+ agentConfig,
1956
+ userInput,
1957
+ dialogConfig
1958
+ );
1959
+ const finalKeys = deduplicateContextKeys(keySets);
1960
+ const fetchReferences = (keys) => fetchReferenceContents(keys, dispatch, {
1961
+ format: "simplified_markdown",
1962
+ inlineMentionMeta: true,
1963
+ preloaded: referenceContentCache
1964
+ });
1965
+ const [currentInputMap, historyMap] = await Promise.all([
1966
+ fetchReferences(finalKeys.currentInputContext),
1967
+ fetchReferences(finalKeys.historyContext)
1968
+ ]);
1969
+ const pendingFiles = selectPendingFiles(state);
1970
+ const formattedCurrentInputContext = formatCurrentInputContext(
1971
+ pendingFiles,
1972
+ currentInputMap
1973
+ );
1974
+ const dialogId = dialogConfig?.id ?? null;
1975
+ const currentDialogMessages = selectAllMsgs(state, dialogId);
1976
+ const currentDialogMessageIds = new Set(currentDialogMessages.map((msg) => msg.id));
1977
+ const currentDialogToolRuns = getAllToolRuns().filter(
1978
+ (run) => currentDialogMessageIds.has(run.messageId)
1979
+ );
1980
+ const editingContext = buildEditingContextSummary(state, runtimeOptions);
1981
+ const appWorkingMemory = buildRecentAppToolMemory(
1982
+ currentDialogMessages,
1983
+ currentDialogToolRuns
1984
+ );
1985
+ const memoryOverlay = await fetchMemoryOverlayContext(
1986
+ state,
1987
+ agentConfig,
1988
+ userInput,
1989
+ dialogConfig
1990
+ );
1991
+ return {
1992
+ currentInputContext: formattedCurrentInputContext.trim() || null,
1993
+ historyContext: joinMapValues(historyMap),
1994
+ editingContext,
1995
+ appWorkingMemory,
1996
+ memoryOverlay,
1997
+ dialogSummary,
1998
+ referenceKeys: dialogConfig?.referenceKeys || []
1999
+ };
2000
+ };
2001
+ var mergeContexts = (staticCtx, dynamicCtx) => ({
2002
+ botInstructionsContext: staticCtx.botInstructionsContext || void 0,
2003
+ botKnowledgeContext: staticCtx.botKnowledgeContext || void 0,
2004
+ spaceContext: staticCtx.spaceContext || void 0,
2005
+ userGlobalPrompt: staticCtx.userGlobalPrompt || void 0,
2006
+ userPolicyContext: staticCtx.userPolicyContext || void 0,
2007
+ currentInputContext: dynamicCtx.currentInputContext,
2008
+ historyContext: dynamicCtx.historyContext || void 0,
2009
+ editingContext: dynamicCtx.editingContext,
2010
+ appWorkingMemory: dynamicCtx.appWorkingMemory,
2011
+ memoryOverlay: dynamicCtx.memoryOverlay,
2012
+ dialogSummary: dynamicCtx.dialogSummary,
2013
+ referenceKeys: dynamicCtx.referenceKeys
2014
+ });
2015
+ var mergeAgentToolsWithRuntime = (agentConfig, referencedTools, mentionedTools, runtimeOptions, state) => {
2016
+ const rawBaseTools = Array.isArray(agentConfig.tools) ? agentConfig.tools : [];
2017
+ const agentEnabledPacks = agentConfig?.enabledPacks;
2018
+ const isInlineArtifact = isInlineVisualArtifactAgent(agentConfig);
2019
+ const effectiveEnabledPacks = Array.isArray(agentEnabledPacks) && agentEnabledPacks.length > 0 ? agentEnabledPacks : isInlineArtifact ? agentEnabledPacks ?? [] : ["long-term-memory"];
2020
+ const expandedPackTools = expandEnabledPacks(
2021
+ effectiveEnabledPacks,
2022
+ rawBaseTools
2023
+ );
2024
+ const baseTools = canonicalizeToolNames(expandedPackTools);
2025
+ const requiredSkillTools = canonicalizeToolNames(
2026
+ agentConfig.referencedTools ?? []
2027
+ );
2028
+ const recommendedSkillTools = canonicalizeToolNames(
2029
+ agentConfig.recommendedSkillTools ?? []
2030
+ );
2031
+ const recommendedSkillHints = [
2032
+ ...new Set(asNonEmptyStringArray(agentConfig.recommendedSkillHints))
2033
+ ];
2034
+ const skillPromptPatches = [
2035
+ ...new Set(asNonEmptyStringArray(agentConfig.skillPromptPatches))
2036
+ ];
2037
+ const webPadded = applyDefaultWebToolPacks({
2038
+ toolNames: baseTools,
2039
+ skipWeb: isInlineVisualArtifactAgent(agentConfig)
2040
+ });
2041
+ const enhancedTools = /* @__PURE__ */ new Set([
2042
+ ...webPadded,
2043
+ ...isInlineVisualArtifactAgent(agentConfig) ? [] : getRuntimeCoreTools(),
2044
+ ...isInlineVisualArtifactAgent(agentConfig) ? [] : requiredSkillTools,
2045
+ ...isInlineVisualArtifactAgent(agentConfig) ? [] : canonicalizeToolNames(referencedTools),
2046
+ ...isInlineVisualArtifactAgent(agentConfig) ? [] : canonicalizeToolNames(mentionedTools)
2047
+ ]);
2048
+ const extraTools = isInlineVisualArtifactAgent(agentConfig) ? [] : canonicalizeToolNames(runtimeOptions?.extraTools ?? []);
2049
+ for (const t of extraTools) {
2050
+ enhancedTools.add(t);
2051
+ }
2052
+ if (!isInlineVisualArtifactAgent(agentConfig)) {
2053
+ const viewMode = state ? selectViewMode(state) : "categories";
2054
+ if (viewMode === "all") {
2055
+ enhancedTools.delete("search_workspace");
2056
+ enhancedTools.add("search_all_spaces");
2057
+ } else {
2058
+ enhancedTools.delete("search_all_spaces");
2059
+ enhancedTools.add("search_workspace");
2060
+ }
2061
+ }
2062
+ return {
2063
+ ...agentConfig,
2064
+ tools: applyDisabledTools(
2065
+ prioritizeToolNames(
2066
+ Array.from(enhancedTools),
2067
+ recommendedSkillTools
2068
+ ),
2069
+ agentConfig?.disabledTools
2070
+ ),
2071
+ recommendedSkillTools,
2072
+ recommendedSkillHints,
2073
+ skillPromptPatches
2074
+ };
2075
+ };
2076
+ var applyImageConfigRuntimeOverride = (agentConfig, runtimeOptions) => {
2077
+ const override = runtimeOptions?.imageConfigOverride;
2078
+ if (!override) {
2079
+ return agentConfig;
2080
+ }
2081
+ const baseImageConfig = agentConfig.imageConfig ?? {};
2082
+ return {
2083
+ ...agentConfig,
2084
+ ...override.imageModelOverride ? { model: override.imageModelOverride } : {},
2085
+ imageConfig: {
2086
+ ...baseImageConfig,
2087
+ ...override
2088
+ }
2089
+ };
2090
+ };
2091
+ var formatImageWaitHint = (range) => {
2092
+ if (!range || typeof range.min !== "number" || typeof range.max !== "number") {
2093
+ return void 0;
2094
+ }
2095
+ return `\u901A\u5E38\u9700\u8981 ${range.min}-${range.max} \u79D2`;
2096
+ };
2097
+ var resolveAgentImageModelIdentity = (agentConfig) => {
2098
+ let providerKey = (agentConfig.provider || "").toLowerCase();
2099
+ let modelName = agentConfig.model ?? "";
2100
+ if (modelName.includes("/")) {
2101
+ const slash = modelName.indexOf("/");
2102
+ if (!providerKey) providerKey = modelName.slice(0, slash);
2103
+ modelName = modelName.slice(slash + 1);
2104
+ }
2105
+ try {
2106
+ return {
2107
+ providerKey,
2108
+ modelConfig: getModelConfig(providerKey, modelName)
2109
+ };
2110
+ } catch {
2111
+ try {
2112
+ const detected = getProviderByModelName(modelName);
2113
+ if (!detected) {
2114
+ return { providerKey, modelConfig: null };
2115
+ }
2116
+ return {
2117
+ providerKey: detected,
2118
+ modelConfig: getModelConfig(detected, modelName)
2119
+ };
2120
+ } catch {
2121
+ return { providerKey, modelConfig: null };
2122
+ }
2123
+ }
2124
+ };
2125
+ var EXPLICIT_IMAGE_GENERATION_TOOL_NAMES = /* @__PURE__ */ new Set([
2126
+ "openAIGptImage",
2127
+ "openAIGptImageGenerate",
2128
+ "openAIGptImageEdit",
2129
+ "chatgptWebImageGenerate",
2130
+ "geminiFlashImage",
2131
+ "geminiProImagePreview"
2132
+ ]);
2133
+ var agentUsesExplicitImageGenerationTool = (agentConfig) => {
2134
+ const toolNames = Array.isArray(agentConfig.tools) ? agentConfig.tools : Array.isArray(agentConfig.toolNames) ? agentConfig.toolNames : [];
2135
+ return toolNames.some(
2136
+ (name) => typeof name === "string" && EXPLICIT_IMAGE_GENERATION_TOOL_NAMES.has(name.trim())
2137
+ );
2138
+ };
2139
+ var resolveImageGenerationStreamingState = (agentConfig, args) => {
2140
+ const { modelConfig } = resolveAgentImageModelIdentity(agentConfig);
2141
+ const hasImageOutput = !!(modelConfig?.hasImageOutput ?? modelConfig?.supportsImageOutput) || agentConfig.imageConfig?.enabled === true || agentUsesExplicitImageGenerationTool(agentConfig);
2142
+ if (!hasImageOutput) {
2143
+ return void 0;
2144
+ }
2145
+ const currentProfile = modelConfig?.imageGenerationProfiles?.find(
2146
+ (profile) => profile.imageModel === modelConfig.name
2147
+ );
2148
+ const usesWebImageTool = agentUsesExplicitImageGenerationTool(agentConfig) && (Array.isArray(agentConfig.tools) ? agentConfig.tools : []).includes("chatgptWebImageGenerate");
2149
+ return {
2150
+ kind: "image_generation",
2151
+ stage: args?.stage ?? args?.previous?.stage ?? "submitted",
2152
+ startedAt: args?.previous?.startedAt ?? Date.now(),
2153
+ waitHint: formatImageWaitHint(modelConfig?.imageGenerationWaitTimeSeconds) ?? (usesWebImageTool ? "\u7F51\u9875\u751F\u56FE\u901A\u5E38\u9700\u8981 30 \u79D2\u5230\u51E0\u5206\u949F\uFF0C\u5207\u6362\u5BF9\u8BDD\u4E0D\u4F1A\u4E2D\u65AD" : "\u901A\u5E38\u9700\u8981\u51E0\u5341\u79D2"),
2154
+ profileLabel: currentProfile?.label
2155
+ };
2156
+ };
2157
+
2158
+ // packages/ai/agent/persistMessageWithFixedId.ts
2159
+ async function persistMessageWithFixedId(dispatch, message) {
2160
+ dispatch(addUserMessage(message));
2161
+ const { controller, ...messageToWrite } = message;
2162
+ try {
2163
+ const writeRequest = dispatch(
2164
+ write({
2165
+ data: {
2166
+ ...messageToWrite,
2167
+ type: "msg" /* MSG */
2168
+ },
2169
+ customKey: message.dbKey
2170
+ })
2171
+ );
2172
+ if (writeRequest && typeof writeRequest.unwrap === "function") {
2173
+ await writeRequest.unwrap();
2174
+ return;
2175
+ }
2176
+ await writeRequest;
2177
+ } catch (error) {
2178
+ console.error(
2179
+ "[persistMessageWithFixedId] Failed to persist fixed-id message:",
2180
+ error
2181
+ );
2182
+ }
2183
+ }
2184
+
2185
+ // packages/ai/agent/serverOrigin.ts
2186
+ var normalizeServerOrigin = (base) => {
2187
+ try {
2188
+ return new URL(base).origin.replace(/\/+$/, "");
2189
+ } catch {
2190
+ return null;
2191
+ }
2192
+ };
2193
+
2194
+ // packages/app/utils/desktopAgentRuntimeTurnClient.ts
2195
+ var DESKTOP_AGENT_CONFIG_SNAPSHOT_BUILD_FAILED = "desktop_agent_config_snapshot_invalid";
2196
+ function buildDesktopAgentRuntimeTurnBody(args) {
2197
+ const continueDialogId = asTrimmedString(args.continueDialogId);
2198
+ let agentConfigSnapshot;
2199
+ if (args.agentConfigSnapshot && typeof args.agentConfigSnapshot === "object") {
2200
+ const built = buildDesktopAgentRuntimeAgentConfigSnapshot(
2201
+ args.agentConfigSnapshot,
2202
+ args.agentRef
2203
+ );
2204
+ if (!built) {
2205
+ throw new Error(DESKTOP_AGENT_CONFIG_SNAPSHOT_BUILD_FAILED);
2206
+ }
2207
+ agentConfigSnapshot = built;
2208
+ }
2209
+ let dialogHistorySnapshot;
2210
+ if (args.dialogHistorySnapshot && typeof args.dialogHistorySnapshot === "object") {
2211
+ dialogHistorySnapshot = args.dialogHistorySnapshot;
2212
+ } else if (Array.isArray(args.dialogMessages) && continueDialogId) {
2213
+ dialogHistorySnapshot = buildDesktopAgentRuntimeDialogHistorySnapshot({
2214
+ dialogId: continueDialogId,
2215
+ messages: args.dialogMessages,
2216
+ currentInput: args.input
2217
+ }) ?? void 0;
2218
+ }
2219
+ const body = {
2220
+ agentRef: args.agentRef,
2221
+ input: args.input,
2222
+ ...args.runtimeContext ? { runtimeContext: args.runtimeContext } : {},
2223
+ ...continueDialogId ? { continueDialogId } : {},
2224
+ ...continueDialogId && asTrimmedString(args.dialogKey) ? { dialogKey: asTrimmedString(args.dialogKey) } : {},
2225
+ ...args.cwd ? { cwd: args.cwd } : {},
2226
+ ...args.restrictShellToWorkspace ? { restrictShellToWorkspace: true } : {},
2227
+ ...args.workspaceToolsHint ? { workspaceToolsHint: true } : {},
2228
+ ...agentConfigSnapshot ? { agentConfigSnapshot } : {},
2229
+ ...dialogHistorySnapshot ? { dialogHistorySnapshot } : {}
2230
+ };
2231
+ assertDesktopAgentRuntimeTurnBodyHasNoRawSecrets(body);
2232
+ return body;
2233
+ }
2234
+ function normalizeDesktopAgentRuntimeTurnError(data) {
2235
+ return typeof data?.error === "string" ? data.error : "Failed to run desktop agent runtime turn";
2236
+ }
2237
+ async function* runDesktopAgentRuntimeTurnStream({
2238
+ fetchImpl = fetch,
2239
+ signal,
2240
+ ...args
2241
+ }) {
2242
+ try {
2243
+ if (signal?.aborted) {
2244
+ yield { type: "error", error: "The operation was aborted." };
2245
+ return;
2246
+ }
2247
+ const response = await fetchImpl("/api/desktop/agent-runtime/turn", {
2248
+ method: "POST",
2249
+ headers: { "Content-Type": "application/json" },
2250
+ body: JSON.stringify(buildDesktopAgentRuntimeTurnBody(args)),
2251
+ signal
2252
+ });
2253
+ if (!response.ok) {
2254
+ const data = await response.clone().json().catch(() => null);
2255
+ yield {
2256
+ type: "error",
2257
+ error: data ? normalizeDesktopAgentRuntimeTurnError(data) : `HTTP ${response.status}: ${response.statusText}`
2258
+ };
2259
+ return;
2260
+ }
2261
+ const contentType = response.headers.get("content-type") ?? "";
2262
+ if (!contentType.includes("text/event-stream")) {
2263
+ const data = await response.json().catch(() => ({}));
2264
+ if (data?.ok === false) {
2265
+ yield { type: "error", error: normalizeDesktopAgentRuntimeTurnError(data) };
2266
+ } else if (data?.result) {
2267
+ yield { type: "done", result: data.result };
2268
+ } else {
2269
+ yield { type: "error", error: "Desktop runtime response did not include a result" };
2270
+ }
2271
+ return;
2272
+ }
2273
+ const reader = response.body?.getReader();
2274
+ if (!reader) {
2275
+ yield { type: "error", error: "Response body reader not available" };
2276
+ return;
2277
+ }
2278
+ const decoder = new TextDecoder();
2279
+ let buffer = "";
2280
+ const readLine = (line) => {
2281
+ const trimmed = line.trim();
2282
+ if (!trimmed || !trimmed.startsWith("data: ")) return null;
2283
+ try {
2284
+ return JSON.parse(trimmed.slice(6));
2285
+ } catch (e) {
2286
+ console.error("[desktop-client] Failed to parse stream line:", trimmed, e);
2287
+ return null;
2288
+ }
2289
+ };
2290
+ try {
2291
+ while (true) {
2292
+ if (signal?.aborted) {
2293
+ yield { type: "error", error: "The operation was aborted." };
2294
+ return;
2295
+ }
2296
+ const { done, value } = await readStreamChunk(reader, { signal });
2297
+ if (done) break;
2298
+ buffer += decoder.decode(value, { stream: true });
2299
+ const lines = buffer.split("\n");
2300
+ buffer = lines.pop() || "";
2301
+ for (const line of lines) {
2302
+ const event2 = readLine(line);
2303
+ if (event2) yield event2;
2304
+ }
2305
+ }
2306
+ buffer += decoder.decode();
2307
+ const event = readLine(buffer);
2308
+ if (event) yield event;
2309
+ } catch (error) {
2310
+ if (isAbortError(error) || signal?.aborted) {
2311
+ yield { type: "error", error: "The operation was aborted." };
2312
+ return;
2313
+ }
2314
+ yield {
2315
+ type: "error",
2316
+ error: toErrorMessage(error)
2317
+ };
2318
+ } finally {
2319
+ try {
2320
+ await reader.cancel();
2321
+ } catch {
2322
+ }
2323
+ try {
2324
+ reader.releaseLock();
2325
+ } catch {
2326
+ }
2327
+ }
2328
+ } catch (error) {
2329
+ if (isAbortError(error) || signal?.aborted) {
2330
+ yield { type: "error", error: "The operation was aborted." };
2331
+ return;
2332
+ }
2333
+ yield {
2334
+ type: "error",
2335
+ error: toErrorMessage(error)
2336
+ };
2337
+ }
2338
+ }
2339
+
2340
+ // packages/ai/agent/streamTurnMessageBuild.ts
2341
+ var buildMessageMetadata = (agentConfig) => {
2342
+ const rawName = asTrimmedString(agentConfig?.name);
2343
+ return {
2344
+ agentKey: agentConfig.dbKey,
2345
+ cybotKey: agentConfig.dbKey,
2346
+ ...rawName ? { agentName: rawName } : {}
2347
+ };
2348
+ };
2349
+ var buildDesktopRuntimeToolMessagesForUi = ({
2350
+ dialogId,
2351
+ turnMessages
2352
+ }) => {
2353
+ if (!Array.isArray(turnMessages) || turnMessages.length === 0) return [];
2354
+ const toolNamesByCallId = /* @__PURE__ */ new Map();
2355
+ const activityByCallId = /* @__PURE__ */ new Map();
2356
+ const projected = [];
2357
+ for (const message of turnMessages) {
2358
+ if (Array.isArray(message?.tool_calls)) {
2359
+ for (const call of message.tool_calls) {
2360
+ const callId = asTrimmedString(call?.id);
2361
+ const toolName2 = asTrimmedString(call?.function?.name);
2362
+ if (callId && toolName2) toolNamesByCallId.set(callId, toolName2);
2363
+ if (callId) {
2364
+ try {
2365
+ const args = typeof call?.function?.arguments === "string" ? JSON.parse(call.function.arguments) : call?.function?.arguments;
2366
+ const rawActivity = isRecord(args) ? args._activity : void 0;
2367
+ const activity2 = isRecord(rawActivity) ? rawActivity : void 0;
2368
+ const legacyTitle = typeof activity2?.title === "string" && activity2.title.trim();
2369
+ const action = activity2?.action;
2370
+ const actionTitle = isRecord(action) && typeof action.title === "string" && action.title.trim();
2371
+ const plan = activity2?.plan;
2372
+ const hasPlan = isRecord(plan) && Array.isArray(plan.phases) && plan.phases.some((phase) => {
2373
+ if (!isRecord(phase)) return false;
2374
+ return typeof phase.title === "string" && !!phase.title.trim();
2375
+ });
2376
+ if (activity2 && (legacyTitle || actionTitle || hasPlan)) {
2377
+ activityByCallId.set(callId, args._activity);
2378
+ }
2379
+ } catch {
2380
+ }
2381
+ }
2382
+ }
2383
+ continue;
2384
+ }
2385
+ if (message?.role !== "tool") continue;
2386
+ const toolCallId = asTrimmedString(message.tool_call_id);
2387
+ const metadata = asRecordOrEmpty(message.tool_result_metadata);
2388
+ const metadataToolName = asTrimmedString(metadata.toolName);
2389
+ const toolName = metadataToolName || (toolCallId ? toolNamesByCallId.get(toolCallId) : "") || "tool";
2390
+ const { key: dbKey, messageId } = createDialogMessageKeyAndId(dialogId);
2391
+ const resultActivity = metadata.activity && typeof metadata.activity === "object" ? metadata.activity : void 0;
2392
+ const callActivity = toolCallId ? activityByCallId.get(toolCallId) : void 0;
2393
+ const activity = resultActivity || callActivity;
2394
+ const mergedMetadata = activity ? { ...metadata, activity } : metadata;
2395
+ projected.push({
2396
+ id: messageId,
2397
+ dialogId,
2398
+ dbKey,
2399
+ role: "tool",
2400
+ content: projectDesktopToolUiContent({
2401
+ toolName,
2402
+ content: typeof message.content === "string" ? message.content : "",
2403
+ metadata: mergedMetadata
2404
+ }),
2405
+ isStreaming: false,
2406
+ toolName,
2407
+ ...toolCallId ? { toolCallId } : {},
2408
+ ...Object.keys(mergedMetadata).length ? { metadata: mergedMetadata } : {}
2409
+ });
2410
+ }
2411
+ return projected;
2412
+ };
2413
+ var toolMessageWillPersist = (toolMsg) => {
2414
+ const content = toolMsg?.content;
2415
+ if (typeof content === "string") return content.trim().length > 0;
2416
+ return Array.isArray(content) && content.length > 0;
2417
+ };
2418
+ var shouldUseDesktopLocalRuntime = (agentConfig) => {
2419
+ if (!getIsDesktopApp()) return false;
2420
+ return agentConfig?.apiSource !== "cli";
2421
+ };
2422
+ var readCurrentDesktopMachineId = () => {
2423
+ const fromProcess = typeof process !== "undefined" ? (process.env?.NOLO_CURRENT_MACHINE_ID || process.env?.NOLO_MACHINE_ID || "").trim() : "";
2424
+ if (fromProcess) return fromProcess;
2425
+ const w = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
2426
+ const fromWindow = asTrimmedString(w?.__NOLO_CURRENT_MACHINE_ID__) || asTrimmedString(w?.__NOLO_MACHINE_ID__);
2427
+ return fromWindow;
2428
+ };
2429
+ var resolveRemoteBoundMachineId = (machineId) => {
2430
+ if (!machineId || !getIsDesktopApp()) return machineId;
2431
+ const currentMachineId = readCurrentDesktopMachineId();
2432
+ return currentMachineId && currentMachineId === machineId ? "" : machineId;
2433
+ };
2434
+ var resolveWebAgentRuntimeToolSurface = (agentConfig, state) => {
2435
+ const toolSurface = resolveRuntimeToolSurfaceForAgent({
2436
+ explicitToolNames: Array.isArray(agentConfig.tools) ? agentConfig.tools : [],
2437
+ currentUserId: selectIdentityUserId(state),
2438
+ agentOwnerId: typeof agentConfig.userId === "string" ? agentConfig.userId : null,
2439
+ agentKey: agentConfig.dbKey ?? agentConfig.agentKey,
2440
+ isPublic: agentConfig.isPublic === true,
2441
+ sharingLevel: typeof agentConfig.sharingLevel === "string" ? agentConfig.sharingLevel : null,
2442
+ runtimeHost: "web"
2443
+ });
2444
+ return {
2445
+ ...agentConfig,
2446
+ tools: toolSurface.finalToolNames,
2447
+ runtimeToolSurface: toolSurface
2448
+ };
2449
+ };
2450
+ var formatMachineAgentRunError = async (response) => {
2451
+ const errorText = await response.text();
2452
+ let payload = null;
2453
+ try {
2454
+ payload = errorText ? JSON.parse(errorText) : null;
2455
+ } catch {
2456
+ payload = null;
2457
+ }
2458
+ const reason = typeof payload?.reason === "string" ? payload.reason : "";
2459
+ if (response.status === 409) {
2460
+ if (reason === "bound_machine_unavailable") {
2461
+ return "\u7ED1\u5B9A\u7684\u7535\u8111\u4E0D\u5728\u7EBF\u3002\u8BF7\u786E\u8BA4\u8FD9\u53F0\u7535\u8111\u5DF2\u5F00\u673A\u5E76\u91CD\u65B0\u8FD0\u884C\u8FDE\u63A5\u547D\u4EE4\u3002";
2462
+ }
2463
+ if (reason === "bound_machine_owner_mismatch") {
2464
+ return "\u8FD9\u53F0\u7535\u8111\u662F\u5728\u7EBF\u7684\uFF0C\u4F46\u5F53\u524D\u8D26\u53F7\u548C Agent \u7ED1\u5B9A\u8D26\u53F7\u4E0D\u4E00\u81F4\u3002\u8BF7\u91CD\u65B0\u7ED1\u5B9A Agent\uFF0C\u6216\u5728\u7ED1\u5B9A\u8D26\u53F7\u4E0B\u91CD\u65B0\u8FDE\u63A5\u8FD9\u53F0\u7535\u8111\u3002";
2465
+ }
2466
+ if (reason === "connector_offline") {
2467
+ return "\u7535\u8111\u5728\u7EBF\uFF0C\u4F46\u8FDE\u63A5\u5668\u672A\u8FDE\u63A5\u3002\u8BF7\u5728\u8FD9\u53F0\u7535\u8111\u4E0A\u91CD\u65B0\u8FD0\u884C\u8FDE\u63A5\u547D\u4EE4\u540E\u518D\u8BD5\u3002";
2468
+ }
2469
+ if (reason === "missing_capability") {
2470
+ return "\u8FD9\u53F0\u7535\u8111\u6CA1\u6709\u5BF9\u5E94\u7684 CLI \u80FD\u529B\u3002\u8BF7\u5B89\u88C5\u5BF9\u5E94 CLI\uFF0C\u6216\u628A Agent \u7ED1\u5B9A\u5230\u53E6\u4E00\u53F0\u7535\u8111\u3002";
2471
+ }
2472
+ }
2473
+ const message = asOptionalTrimmedString(payload?.message) ?? asOptionalTrimmedString(payload?.error) ?? errorText.trim();
2474
+ return message || `Machine agent run failed (${response.status})`;
2475
+ };
2476
+ var normalizeThreadMetadataPatch = (value) => {
2477
+ if (!isRecord(value)) return null;
2478
+ const record = value;
2479
+ const changes = {};
2480
+ const threadKind = asOptionalTrimmedString(record.threadKind);
2481
+ if (threadKind) {
2482
+ changes.threadKind = threadKind;
2483
+ }
2484
+ const presentationIntent = asOptionalTrimmedString(record.presentationIntent);
2485
+ if (presentationIntent) {
2486
+ changes.presentationIntent = presentationIntent;
2487
+ }
2488
+ return Object.keys(changes).length > 0 ? changes : null;
2489
+ };
2490
+ var patchDialogThreadMetadata = async (dispatch, dialogKey, metadata) => {
2491
+ const changes = normalizeThreadMetadataPatch(metadata);
2492
+ if (!changes) return;
2493
+ await dispatch(
2494
+ patch({
2495
+ dbKey: dialogKey,
2496
+ changes
2497
+ })
2498
+ ).unwrap?.();
2499
+ };
2500
+ var patchDialogActiveAgent = async (dispatch, dialogKey, agentKey) => {
2501
+ if (typeof agentKey !== "string" || !agentKey.trim()) return;
2502
+ await dispatch(
2503
+ patch({
2504
+ dbKey: dialogKey,
2505
+ changes: {
2506
+ primaryAgentKey: agentKey.trim()
2507
+ }
2508
+ })
2509
+ ).unwrap?.();
2510
+ };
2511
+ function appendCliCapabilityWarnings(content, warnings) {
2512
+ if (!warnings.length) return content;
2513
+ const warningBlock = `
2514
+
2515
+ [CLI \u80FD\u529B\u63D0\u793A]
2516
+ ${warnings.map((warning) => `- ${warning}`).join("\n")}`;
2517
+ return `${content}${warningBlock}`;
2518
+ }
2519
+
2520
+ // packages/ai/agent/streamTurnStreamConsumer.ts
2521
+ async function readAgentRunStreamChunk(reader, signal, isAborted) {
2522
+ if (isAborted() || signal?.aborted) {
2523
+ void reader.cancel().catch(() => {
2524
+ });
2525
+ throw new DOMException("The operation was aborted.", "AbortError");
2526
+ }
2527
+ if (!signal) {
2528
+ return reader.read();
2529
+ }
2530
+ let settled = false;
2531
+ return new Promise((resolve, reject) => {
2532
+ const finish = (cb) => {
2533
+ if (settled) return;
2534
+ settled = true;
2535
+ signal.removeEventListener("abort", onAbort);
2536
+ cb();
2537
+ };
2538
+ const onAbort = () => {
2539
+ void reader.cancel().catch(() => {
2540
+ });
2541
+ finish(
2542
+ () => reject(new DOMException("The operation was aborted.", "AbortError"))
2543
+ );
2544
+ };
2545
+ signal.addEventListener("abort", onAbort);
2546
+ reader.read().then(
2547
+ (result) => finish(() => resolve(result)),
2548
+ (err) => finish(() => reject(err))
2549
+ );
2550
+ });
2551
+ }
2552
+ async function consumeAgentRunStream(handlers) {
2553
+ const {
2554
+ reader,
2555
+ decoder,
2556
+ parseChunk,
2557
+ onPayload,
2558
+ isDoneEvent,
2559
+ isAborted,
2560
+ signal,
2561
+ onAbort
2562
+ } = handlers;
2563
+ let sawDone = false;
2564
+ try {
2565
+ while (true) {
2566
+ let done;
2567
+ let value;
2568
+ try {
2569
+ ({ done, value } = await readAgentRunStreamChunk(
2570
+ reader,
2571
+ signal,
2572
+ isAborted
2573
+ ));
2574
+ } catch (error) {
2575
+ if (isAbortError(error) || isAborted() || signal?.aborted) {
2576
+ await onAbort();
2577
+ return { outcome: "aborted" };
2578
+ }
2579
+ throw error;
2580
+ }
2581
+ if (isAborted() || signal?.aborted) {
2582
+ await onAbort();
2583
+ return { outcome: "aborted" };
2584
+ }
2585
+ if (done) {
2586
+ return { outcome: "streamEnded", sawDone };
2587
+ }
2588
+ const payloads = parseChunk(
2589
+ decoder.decode(value, { stream: true })
2590
+ );
2591
+ for (const payload of payloads) {
2592
+ if (isAborted() || signal?.aborted) {
2593
+ await onAbort();
2594
+ return { outcome: "aborted" };
2595
+ }
2596
+ const directive = await onPayload(payload);
2597
+ if (directive?.reject !== void 0) {
2598
+ return { outcome: "rejected", message: directive.reject };
2599
+ }
2600
+ if (directive?.abort) {
2601
+ await onAbort();
2602
+ return { outcome: "aborted" };
2603
+ }
2604
+ if (isDoneEvent(payload)) {
2605
+ sawDone = true;
2606
+ }
2607
+ }
2608
+ }
2609
+ } catch (error) {
2610
+ if (isAbortError(error) || isAborted() || signal?.aborted) {
2611
+ await onAbort();
2612
+ return { outcome: "aborted" };
2613
+ }
2614
+ throw error;
2615
+ }
2616
+ }
2617
+
2618
+ // packages/ai/llm/isResponseAPIModel.ts
2619
+ var isResponseAPIModel = (agentConfig) => {
2620
+ if (agentConfig.provider !== "openai") return false;
2621
+ if (agentConfig.endpointKey === "responses") return true;
2622
+ if (!agentConfig.model) return false;
2623
+ try {
2624
+ return getModelConfig("openai", agentConfig.model).endpointKey === "responses";
2625
+ } catch {
2626
+ return false;
2627
+ }
2628
+ };
2629
+
2630
+ // packages/ai/agent/streamTurnQuickChat.ts
2631
+ var QUICK_CHAT_AGENT_CONFIG_READ_TIMEOUT_MS = 1e4;
2632
+ var QUICK_CHAT_DYNAMIC_CONTEXT_TIMEOUT_MS = 5e3;
2633
+ var EMPTY_DYNAMIC_CONTEXTS = {
2634
+ currentInputContext: null,
2635
+ historyContext: "",
2636
+ editingContext: null,
2637
+ appWorkingMemory: null,
2638
+ memoryOverlay: null,
2639
+ dialogSummary: null,
2640
+ referenceKeys: []
2641
+ };
2642
+ var logQuickChatPerfStage2 = (startedAt, stage, details = {}) => {
2643
+ if (!startedAt) return;
2644
+ const now = typeof performance !== "undefined" ? performance.now() : Date.now();
2645
+ console.info("[QuickChatPerf]", {
2646
+ stage,
2647
+ elapsedMs: now - startedAt,
2648
+ ...typeof performance !== "undefined" ? { atMs: now } : {},
2649
+ ...details
2650
+ });
2651
+ };
2652
+ var readAgentConfigForTurn = async (dispatch, agentKey, quickChatPerfStartedAt) => {
2653
+ const readPromise = dispatch(read({ dbKey: agentKey })).unwrap();
2654
+ if (!quickChatPerfStartedAt) return readPromise;
2655
+ let timeoutId;
2656
+ try {
2657
+ return await Promise.race([
2658
+ readPromise,
2659
+ new Promise((_, reject) => {
2660
+ timeoutId = setTimeout(() => {
2661
+ logQuickChatPerfStage2(
2662
+ quickChatPerfStartedAt,
2663
+ "quick-chat-agent-config-read-timeout",
2664
+ { agentKey, timeoutMs: QUICK_CHAT_AGENT_CONFIG_READ_TIMEOUT_MS }
2665
+ );
2666
+ reject(
2667
+ new Error("\u8BFB\u53D6 Agent \u914D\u7F6E\u8D85\u65F6\uFF0C\u672A\u80FD\u542F\u52A8\u6A21\u578B\u56DE\u590D\u3002")
2668
+ );
2669
+ }, QUICK_CHAT_AGENT_CONFIG_READ_TIMEOUT_MS);
2670
+ })
2671
+ ]);
2672
+ } finally {
2673
+ if (timeoutId) clearTimeout(timeoutId);
2674
+ }
2675
+ };
2676
+ var buildDynamicContextsForTurn = async (state, dispatch, agentConfig, userInput, runtimeOptions, mergedContentCache, dialogKey, quickChatPerfStartedAt) => {
2677
+ if (!quickChatPerfStartedAt) {
2678
+ return buildDynamicContexts(
2679
+ state,
2680
+ dispatch,
2681
+ agentConfig,
2682
+ userInput,
2683
+ runtimeOptions,
2684
+ mergedContentCache,
2685
+ dialogKey
2686
+ );
2687
+ }
2688
+ let timeoutId;
2689
+ try {
2690
+ const timeoutPromise = new Promise((resolve) => {
2691
+ timeoutId = setTimeout(() => {
2692
+ logQuickChatPerfStage2(
2693
+ quickChatPerfStartedAt,
2694
+ "quick-chat-dynamic-context-timeout",
2695
+ { agentKey: agentConfig.dbKey, dialogKey, timeoutMs: QUICK_CHAT_DYNAMIC_CONTEXT_TIMEOUT_MS }
2696
+ );
2697
+ resolve(EMPTY_DYNAMIC_CONTEXTS);
2698
+ }, QUICK_CHAT_DYNAMIC_CONTEXT_TIMEOUT_MS);
2699
+ });
2700
+ logQuickChatPerfStage2(
2701
+ quickChatPerfStartedAt,
2702
+ "stream-agent-dynamic-context-starting",
2703
+ { responseApi: isResponseAPIModel(agentConfig) }
2704
+ );
2705
+ const contextPromise = buildDynamicContexts(
2706
+ state,
2707
+ dispatch,
2708
+ agentConfig,
2709
+ userInput,
2710
+ runtimeOptions,
2711
+ mergedContentCache,
2712
+ dialogKey
2713
+ );
2714
+ return await Promise.race([
2715
+ contextPromise,
2716
+ timeoutPromise
2717
+ ]);
2718
+ } finally {
2719
+ if (timeoutId) clearTimeout(timeoutId);
2720
+ }
2721
+ };
2722
+ var finalizeQuickChatAgentTurnFailure = async (dispatch, dialogKey, agentKey, error) => {
2723
+ const dialogId = extractCustomId(dialogKey);
2724
+ const { key: msgKey, messageId } = createDialogMessageKeyAndId(dialogId);
2725
+ const reason = error instanceof Error && error.message.trim() ? error.message.trim() : typeof error === "string" && error.trim() ? error.trim() : error && typeof error === "object" && typeof error.message === "string" && error.message.trim() ? error.message.trim() : "\u672A\u80FD\u542F\u52A8\u6A21\u578B\u56DE\u590D\uFF0C\u8BF7\u91CD\u8BD5\u3002";
2726
+ await dispatch(
2727
+ messageStreamEnd({
2728
+ finalContentBuffer: [
2729
+ { type: "text", text: `[\u9519\u8BEF: ${reason}]` }
2730
+ ],
2731
+ totalUsage: null,
2732
+ msgKey,
2733
+ agentConfig: { dbKey: agentKey },
2734
+ dialogId,
2735
+ dialogKey,
2736
+ messageId,
2737
+ reasoningBuffer: ""
2738
+ })
2739
+ ).unwrap?.();
2740
+ };
2741
+ var normalizeAgentRunUserInput = (userInput) => {
2742
+ if (typeof userInput === "string") return userInput;
2743
+ if (!Array.isArray(userInput)) return "";
2744
+ return userInput.filter((part) => {
2745
+ if (!part || typeof part !== "object") return false;
2746
+ if (part.type === "text") return typeof part.text === "string";
2747
+ return part.type === "image_url" && typeof part.image_url?.url === "string" && !!part.image_url.url.trim();
2748
+ });
2749
+ };
2750
+ var isSimpleTextInput = (userInput) => {
2751
+ if (typeof userInput === "string") return true;
2752
+ if (!Array.isArray(userInput)) return false;
2753
+ return userInput.every(
2754
+ (part) => part && typeof part === "object" && part.type === "text" && typeof part.text === "string"
2755
+ );
2756
+ };
2757
+ var canUseQuickChatEmptyDynamicContexts = (quickChatPerfStartedAt, userInput, runtimeOptions, dialogConfig, agentConfig) => {
2758
+ if (!quickChatPerfStartedAt) return false;
2759
+ if (runtimeOptions) return false;
2760
+ if (agentConfig?.tools?.includes("rememberMemory")) return false;
2761
+ if (!isSimpleTextInput(userInput)) return false;
2762
+ if (dialogConfig?.referenceKeys?.length) return false;
2763
+ return true;
2764
+ };
2765
+ var QUICK_CHAT_DIRECT_ANSWER_PATTERN = /(只回复|只输出|只回答|直接回复|直接回答|不要解释|无需解释|不用解释|简短回答|一句话)/i;
2766
+ var QUICK_CHAT_TOOL_INTENT_PATTERN = /(调用|转交|agent|助手|应用|网页|页面|图表|图片|生成图|画图|删除|清理|空间|商品|链接|https?:\/\/|www\.|@)/i;
2767
+ var shouldDisableQuickChatToolsForDirectAnswer = (quickChatPerfStartedAt, userInput, runtimeOptions, dialogConfig) => {
2768
+ if (!canUseQuickChatEmptyDynamicContexts(
2769
+ quickChatPerfStartedAt,
2770
+ userInput,
2771
+ runtimeOptions,
2772
+ dialogConfig,
2773
+ void 0
2774
+ )) {
2775
+ return false;
2776
+ }
2777
+ const text = extractAgentRunUserText(userInput);
2778
+ if (!text || text.length > 500) return false;
2779
+ if (!QUICK_CHAT_DIRECT_ANSWER_PATTERN.test(text)) return false;
2780
+ return !QUICK_CHAT_TOOL_INTENT_PATTERN.test(text);
2781
+ };
2782
+ var classifyQuickChatAccessError = (accessError) => {
2783
+ if (accessError.includes("\u83B7\u53D6\u7528\u6237\u4F59\u989D")) return "balance-loading";
2784
+ if (accessError.includes("\u4F59\u989D")) return "balance";
2785
+ if (accessError.includes("\u767D\u540D\u5355")) return "whitelist";
2786
+ if (accessError.includes("\u5B9A\u4EF7")) return "pricing";
2787
+ return "unknown";
2788
+ };
2789
+ var isUsableAgentConfig = (value) => !!value && typeof value === "object" && value.__ssrPreviewOnly !== true && typeof value.dbKey === "string" && !!value.dbKey && typeof value.model === "string" && !!value.model && typeof value.provider === "string" && !!value.provider;
2790
+ var extractAgentRunUserText = (userInput) => {
2791
+ if (typeof userInput === "string") return userInput.trim();
2792
+ if (!Array.isArray(userInput)) return "";
2793
+ return userInput.filter((part) => part?.type === "text" && typeof part.text === "string").map((part) => part.text).join("").trim();
2794
+ };
2795
+ var hasAgentRunUserInputContent = (userInput) => {
2796
+ if (typeof userInput === "string") return userInput.trim().length > 0;
2797
+ return Array.isArray(userInput) && userInput.length > 0;
2798
+ };
2799
+ var isLastMessageMatchingUserInput = (visibleMessages, userInput) => {
2800
+ if (visibleMessages.length === 0) return false;
2801
+ const lastMsg = visibleMessages[visibleMessages.length - 1];
2802
+ if (lastMsg.role !== "user") return false;
2803
+ const content1 = lastMsg.content;
2804
+ const content2 = userInput;
2805
+ const normalize = (content) => {
2806
+ if (typeof content === "string") return content.trim();
2807
+ if (Array.isArray(content)) {
2808
+ if (content.length === 1 && content[0]?.type === "text") {
2809
+ return (content[0].text || "").trim();
2810
+ }
2811
+ return content.map((part) => {
2812
+ if (part?.type === "text") return { type: "text", text: part.text?.trim() };
2813
+ if (part?.type === "image_url") return { type: "image_url", url: part.image_url?.url };
2814
+ return part;
2815
+ });
2816
+ }
2817
+ return content;
2818
+ };
2819
+ const norm1 = normalize(content1);
2820
+ const norm2 = normalize(content2);
2821
+ if (typeof norm1 === "string" && typeof norm2 === "string") {
2822
+ return norm1 === norm2;
2823
+ }
2824
+ return JSON.stringify(norm1) === JSON.stringify(norm2);
2825
+ };
2826
+ var setLoopStopReason = (reason) => {
2827
+ const w = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
2828
+ if (w) w.__LOOP_STOP_REASON__ = reason;
2829
+ };
2830
+ var prewarmPreparedToolsForAgent = (agentConfig) => {
2831
+ const tools = agentConfig?.tools;
2832
+ if (!Array.isArray(tools) || tools.length === 0) return;
2833
+ try {
2834
+ prepareTools(tools, { provider: agentConfig.provider });
2835
+ } catch {
2836
+ }
2837
+ };
2838
+ var buildStaticContextsWithToolsPrewarm = async (state, dispatch, agentConfig, currentDialog, mergedContentCache) => {
2839
+ const [staticContexts] = await Promise.all([
2840
+ buildStaticContexts(
2841
+ state,
2842
+ dispatch,
2843
+ agentConfig,
2844
+ currentDialog ?? void 0,
2845
+ mergedContentCache
2846
+ ),
2847
+ Promise.resolve().then(() => prewarmPreparedToolsForAgent(agentConfig))
2848
+ ]);
2849
+ return staticContexts;
2850
+ };
2851
+
2852
+ // packages/ai/agent/streamAgentChatTurn.ts
2853
+ function hasInlineExecutedToolCalls(result) {
2854
+ const output = result?.output;
2855
+ return Array.isArray(output) && output.some((b) => b?.type === "toolCall" && b?.result != null);
2856
+ }
2857
+ var streamAgentChatTurnHandler = async (args, thunkApi) => {
2858
+ const {
2859
+ agentKey,
2860
+ userInput,
2861
+ dialogKey: explicitDialogKey,
2862
+ parentMessageId,
2863
+ runtimeOptions,
2864
+ quickChatPerfStartedAt
2865
+ } = args;
2866
+ const { getState, dispatch, rejectWithValue } = thunkApi;
2867
+ const state = getState();
2868
+ const loopController = new AbortController();
2869
+ const isTurnAborted = (error) => isAbortError(error) || loopController.signal.aborted || thunkApi.signal.aborted;
2870
+ const onAbort = () => loopController.abort();
2871
+ thunkApi.signal.addEventListener("abort", onAbort);
2872
+ let loopKey = null;
2873
+ let runtimeDialogKey = explicitDialogKey ?? null;
2874
+ let remoteTransientMessageId = null;
2875
+ let remoteTransientMessageFinalized = false;
2876
+ let modelRequestStarted = false;
2877
+ let turnAborted = false;
2878
+ if (explicitDialogKey) {
2879
+ const dialogId = extractCustomId(explicitDialogKey);
2880
+ const existingLoopKey = `loop:${dialogId}`;
2881
+ const activeControllers = selectActiveControllers(
2882
+ getState(),
2883
+ explicitDialogKey
2884
+ );
2885
+ if (activeControllers[existingLoopKey]) {
2886
+ console.warn(
2887
+ "[streamAgentChatTurn] Rejected concurrent turn for dialog",
2888
+ { dialogId, agentKey }
2889
+ );
2890
+ return rejectWithValue("Agent is already responding for this dialog");
2891
+ }
2892
+ }
2893
+ try {
2894
+ let totalTurnUsage = null;
2895
+ const agentRunUserInput = normalizeAgentRunUserInput(userInput);
2896
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-entered", {
2897
+ agentKey,
2898
+ dialogKey: explicitDialogKey ?? null
2899
+ });
2900
+ const cachedAgentConfig = selectById(
2901
+ getState(),
2902
+ agentKey
2903
+ );
2904
+ let rawAgentConfig = null;
2905
+ rawAgentConfig = isUsableAgentConfig(cachedAgentConfig) ? cachedAgentConfig : await readAgentConfigForTurn(
2906
+ dispatch,
2907
+ agentKey,
2908
+ quickChatPerfStartedAt
2909
+ );
2910
+ if (!rawAgentConfig) {
2911
+ return rejectWithValue(
2912
+ `Agent config not found for ID: ${agentKey}`
2913
+ );
2914
+ }
2915
+ if (runtimeOptions?.quickChatModelOverride) {
2916
+ rawAgentConfig = applyQuickChatModelOverride(
2917
+ rawAgentConfig,
2918
+ runtimeOptions.quickChatModelOverride
2919
+ );
2920
+ }
2921
+ if (isLiveAudioOnlyAgent(rawAgentConfig)) {
2922
+ return rejectWithValue(
2923
+ "\u6B64 Agent \u4EC5\u652F\u6301\u5B9E\u65F6\u8BED\u97F3\u6A21\u5F0F\uFF0C\u8BF7\u4F7F\u7528\u8BED\u97F3\u9762\u677F\u8FDB\u884C\u5BF9\u8BDD\u3002"
2924
+ );
2925
+ }
2926
+ const agentConfig = resolveWebAgentRuntimeToolSurface(
2927
+ rawAgentConfig,
2928
+ getState()
2929
+ );
2930
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-config-read", {
2931
+ agentKey,
2932
+ model: agentConfig.model,
2933
+ provider: agentConfig.provider,
2934
+ apiSource: agentConfig.apiSource,
2935
+ source: rawAgentConfig === cachedAgentConfig ? "cache" : "read"
2936
+ });
2937
+ const gptProCheck = shouldBlockForGptPro(
2938
+ agentConfig,
2939
+ selectIdentityUser(getState())?.gptProAccess?.status
2940
+ );
2941
+ if (gptProCheck.blocked) {
2942
+ return rejectWithValue(gptProCheck.message);
2943
+ }
2944
+ const configuredBoundMachineId = asTrimmedString(
2945
+ agentConfig.runtimeBinding?.machineId
2946
+ );
2947
+ const boundMachineId = resolveRemoteBoundMachineId(configuredBoundMachineId);
2948
+ if (agentConfig.apiSource === "cli" || boundMachineId && !getIsDesktopApp()) {
2949
+ console.info("[streamAgentChatTurn] Triggered CLI/machine route. apiSource:", agentConfig.apiSource, "boundMachineId:", boundMachineId, "agentKey:", agentKey);
2950
+ const currentState = getState();
2951
+ const w2 = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
2952
+ if (w2) w2.__LOOP_STOP_REASON__ = null;
2953
+ const userText = extractAgentRunUserText(userInput);
2954
+ const prompt = buildCliPrompt(agentConfig.prompt, userText);
2955
+ const dialogConfig = selectDialogConfigByKey(currentState, explicitDialogKey) ?? selectCurrentDialogConfig(currentState);
2956
+ if (!dialogConfig) {
2957
+ return rejectWithValue("Dialog config not found");
2958
+ }
2959
+ const dialogKey2 = explicitDialogKey || dialogConfig.dbKey;
2960
+ if (!dialogKey2) {
2961
+ return rejectWithValue("\u5F53\u524D\u5BF9\u8BDD\u4E0D\u5B58\u5728\uFF0C\u65E0\u6CD5\u53D1\u9001\u6D88\u606F\u3002");
2962
+ }
2963
+ runtimeDialogKey = dialogKey2;
2964
+ const dialogId2 = extractCustomId(dialogKey2);
2965
+ loopKey = `loop:${dialogId2}`;
2966
+ dispatch(addActiveController({ messageId: loopKey, controller: loopController, dialogKey: dialogKey2 }));
2967
+ const { key: msgKey, messageId } = createDialogMessageKeyAndId(dialogId2);
2968
+ const cliMessageMetadata = buildMessageMetadata(agentConfig);
2969
+ if (boundMachineId) {
2970
+ const token = selectIdentityToken(currentState);
2971
+ const authHeader = token ? `Bearer ${token}` : "";
2972
+ const rawMessages = selectAllMsgs(currentState, dialogId2);
2973
+ const visibleMessages = buildAgentViewMessages(
2974
+ rawMessages,
2975
+ agentConfig.dbKey
2976
+ );
2977
+ const cleanedMessages = filterAndCleanMessages(visibleMessages);
2978
+ const currentServer2 = selectCurrentServer(currentState);
2979
+ remoteTransientMessageId = messageId;
2980
+ let accumulated2 = "";
2981
+ let totalTurnUsage2 = void 0;
2982
+ const buildMachineAssistantMessage = () => ({
2983
+ id: messageId,
2984
+ dbKey: msgKey,
2985
+ role: "assistant",
2986
+ content: accumulated2,
2987
+ ...cliMessageMetadata,
2988
+ userId: selectIdentityUserId(getState())
2989
+ });
2990
+ dispatch(messageStreaming({
2991
+ id: messageId,
2992
+ dialogId: dialogId2,
2993
+ dbKey: msgKey,
2994
+ content: "",
2995
+ role: "assistant",
2996
+ ...cliMessageMetadata
2997
+ }));
2998
+ const rejectMachineStream = async (message) => {
2999
+ if (accumulated2.length > 0) {
3000
+ await persistMessageWithFixedId(dispatch, buildMachineAssistantMessage());
3001
+ } else {
3002
+ dispatch(removeTransientMessage(messageId));
3003
+ }
3004
+ setLoopStopReason("error");
3005
+ remoteTransientMessageFinalized = true;
3006
+ return rejectWithValue(message);
3007
+ };
3008
+ const machineResponse = await fetch(`${currentServer2.replace(/\/+$/, "")}/api/agent/run`, {
3009
+ method: "POST",
3010
+ headers: {
3011
+ "Content-Type": "application/json",
3012
+ Accept: "text/event-stream",
3013
+ ...authHeader ? { Authorization: authHeader } : {}
3014
+ },
3015
+ body: JSON.stringify({
3016
+ agentKey,
3017
+ userInput: agentRunUserInput,
3018
+ messages: cleanedMessages,
3019
+ stream: true,
3020
+ persistDialog: false,
3021
+ clientDialogId: dialogId2,
3022
+ runtimeContext: {
3023
+ surface: "web",
3024
+ host: "browser",
3025
+ runtime: "react",
3026
+ entrypoint: "chat-dialog",
3027
+ capabilities: ["streaming", "dialog-ui", "machine-bound-cli"]
3028
+ },
3029
+ ...dialogConfig?.spaceId ? { spaceId: dialogConfig.spaceId } : {}
3030
+ }),
3031
+ signal: loopController.signal
3032
+ });
3033
+ if (!machineResponse.ok) {
3034
+ return await rejectMachineStream(
3035
+ await formatMachineAgentRunError(machineResponse)
3036
+ );
3037
+ }
3038
+ const reader2 = machineResponse.body?.getReader();
3039
+ if (!reader2) {
3040
+ return await rejectMachineStream("\u65E0\u6CD5\u8BFB\u53D6\u7535\u8111\u7AEF Agent \u6D41\u5F0F\u54CD\u5E94");
3041
+ }
3042
+ const decoder2 = new TextDecoder();
3043
+ const parseSSE = createSSEParser();
3044
+ const abortMachineStream = async () => {
3045
+ if (w2) w2.__LOOP_STOP_REASON__ = "aborted";
3046
+ if (accumulated2.length <= 0) return;
3047
+ await persistMessageWithFixedId(dispatch, buildMachineAssistantMessage());
3048
+ };
3049
+ try {
3050
+ const result = await consumeAgentRunStream({
3051
+ reader: reader2,
3052
+ decoder: decoder2,
3053
+ parseChunk: (raw) => parseSSE(raw),
3054
+ isAborted: () => loopController.signal.aborted || thunkApi.signal.aborted,
3055
+ signal: loopController.signal,
3056
+ onAbort: abortMachineStream,
3057
+ isDoneEvent: (payload) => payload?.type === "done",
3058
+ onPayload: (payload) => {
3059
+ if (payload.type === "error") {
3060
+ return { reject: payload.message || "\u7535\u8111\u7AEF Agent \u6267\u884C\u5931\u8D25" };
3061
+ }
3062
+ if (payload.type === "text" && typeof payload.content === "string") {
3063
+ accumulated2 += payload.content;
3064
+ dispatch(messageStreaming({
3065
+ id: messageId,
3066
+ dialogId: dialogId2,
3067
+ dbKey: msgKey,
3068
+ content: accumulated2,
3069
+ role: "assistant",
3070
+ ...cliMessageMetadata
3071
+ }));
3072
+ }
3073
+ if (payload.type === "done") {
3074
+ totalTurnUsage2 = payload.usage;
3075
+ }
3076
+ }
3077
+ });
3078
+ if (result.outcome === "rejected") {
3079
+ return await rejectMachineStream(result.message);
3080
+ }
3081
+ if (result.outcome === "aborted") {
3082
+ return { aborted: true };
3083
+ }
3084
+ if (result.outcome === "streamEnded") {
3085
+ if (!result.sawDone) {
3086
+ dispatch(finalizeTransientMessageOnError({
3087
+ id: messageId,
3088
+ error: "\u7535\u8111\u7AEF Agent \u6D41\u5F0F\u54CD\u5E94\u88AB\u4E2D\u65AD,\u672A\u6536\u5230\u5B8C\u6210\u4FE1\u53F7"
3089
+ }));
3090
+ remoteTransientMessageFinalized = true;
3091
+ setLoopStopReason("error");
3092
+ return rejectWithValue(
3093
+ "\u7535\u8111\u7AEF Agent \u6D41\u5F0F\u54CD\u5E94\u88AB\u4E2D\u65AD,\u672A\u6536\u5230\u5B8C\u6210\u4FE1\u53F7"
3094
+ );
3095
+ }
3096
+ await persistMessageWithFixedId(dispatch, buildMachineAssistantMessage());
3097
+ remoteTransientMessageFinalized = true;
3098
+ }
3099
+ } finally {
3100
+ try {
3101
+ await reader2.cancel();
3102
+ } catch {
3103
+ }
3104
+ }
3105
+ return {
3106
+ usage: totalTurnUsage2 ?? void 0
3107
+ };
3108
+ }
3109
+ let cliSessionId = dialogConfig.cliSessionId ?? null;
3110
+ dispatch(messageStreaming({
3111
+ id: messageId,
3112
+ dialogId: dialogId2,
3113
+ dbKey: msgKey,
3114
+ content: "",
3115
+ role: "assistant",
3116
+ ...cliMessageMetadata
3117
+ }));
3118
+ remoteTransientMessageId = messageId;
3119
+ const ensureCliSession = async () => {
3120
+ if (cliSessionId) {
3121
+ const existing = await getCliChatSession(
3122
+ { getState },
3123
+ { sessionId: cliSessionId }
3124
+ ).catch(() => null);
3125
+ if (existing?.ok && existing?.session?.sessionId) {
3126
+ return cliSessionId;
3127
+ }
3128
+ }
3129
+ const started = await startCliChatSession(
3130
+ { getState },
3131
+ {
3132
+ cliProvider: agentConfig.cliProvider || "copilot",
3133
+ model: agentConfig.model || void 0,
3134
+ systemPrompt: agentConfig.prompt || void 0,
3135
+ reasoningEffort: agentConfig.reasoning_effort || agentConfig.reasoningEffort || void 0,
3136
+ temperature: agentConfig.temperature,
3137
+ topP: agentConfig.top_p,
3138
+ frequencyPenalty: agentConfig.frequency_penalty,
3139
+ presencePenalty: agentConfig.presence_penalty,
3140
+ maxTokens: agentConfig.max_tokens,
3141
+ enableThinking: agentConfig.enableThinking,
3142
+ thinkingBudget: agentConfig.thinkingBudget
3143
+ }
3144
+ );
3145
+ const newSessionId = typeof started?.sessionId === "string" ? started.sessionId : null;
3146
+ if (!newSessionId) {
3147
+ throw new Error("\u65E0\u6CD5\u521B\u5EFA CLI session\u3002");
3148
+ }
3149
+ cliSessionId = newSessionId;
3150
+ const patchResult = dispatch(
3151
+ patch({
3152
+ dbKey: dialogKey2,
3153
+ changes: {
3154
+ cliSessionId: newSessionId
3155
+ }
3156
+ })
3157
+ );
3158
+ try {
3159
+ if (typeof patchResult?.unwrap === "function") {
3160
+ await patchResult.unwrap();
3161
+ } else {
3162
+ await patchResult;
3163
+ }
3164
+ } catch {
3165
+ }
3166
+ return newSessionId;
3167
+ };
3168
+ const initialSessionId = await ensureCliSession();
3169
+ console.info("[streamAgentChatTurn] Calling CLI turn stream. Session ID:", initialSessionId);
3170
+ let resp = await createCliChatTurnStream(
3171
+ {
3172
+ getState
3173
+ },
3174
+ {
3175
+ sessionId: initialSessionId,
3176
+ prompt,
3177
+ model: agentConfig.model || void 0
3178
+ },
3179
+ loopController.signal
3180
+ );
3181
+ if (!resp.ok && resp.status === 404) {
3182
+ console.warn("[streamAgentChatTurn] CLI Session 404. Re-creating session...");
3183
+ cliSessionId = null;
3184
+ const renewedSessionId = await ensureCliSession();
3185
+ console.info("[streamAgentChatTurn] Retrying CLI turn stream. Session ID:", renewedSessionId);
3186
+ resp = await createCliChatTurnStream(
3187
+ {
3188
+ getState
3189
+ },
3190
+ {
3191
+ sessionId: renewedSessionId,
3192
+ prompt,
3193
+ model: agentConfig.model || void 0
3194
+ },
3195
+ loopController.signal
3196
+ );
3197
+ }
3198
+ if (!resp.ok) {
3199
+ const err = await resp.json().catch(() => ({ error: resp.statusText }));
3200
+ console.error("[streamAgentChatTurn] Local CLI fetch failed. Status:", resp.status, "Error details:", err);
3201
+ dispatch(removeTransientMessage(messageId));
3202
+ setLoopStopReason("error");
3203
+ remoteTransientMessageFinalized = true;
3204
+ return rejectWithValue(err.error || "CLI \u6267\u884C\u5931\u8D25");
3205
+ }
3206
+ const reader = resp.body?.getReader();
3207
+ if (!reader) {
3208
+ dispatch(removeTransientMessage(messageId));
3209
+ setLoopStopReason("error");
3210
+ remoteTransientMessageFinalized = true;
3211
+ return rejectWithValue("\u65E0\u6CD5\u8BFB\u53D6\u6D41\u5F0F\u54CD\u5E94");
3212
+ }
3213
+ let accumulated = "";
3214
+ let cliCapabilityWarnings = [];
3215
+ const decoder = new TextDecoder();
3216
+ const buildCliAssistantMessage = () => ({
3217
+ id: messageId,
3218
+ dbKey: msgKey,
3219
+ role: "assistant",
3220
+ content: accumulated,
3221
+ ...cliMessageMetadata,
3222
+ userId: selectIdentityUserId(getState())
3223
+ });
3224
+ const rejectCliStream = async (message) => {
3225
+ if (accumulated.length > 0) {
3226
+ await persistMessageWithFixedId(dispatch, buildCliAssistantMessage());
3227
+ } else {
3228
+ dispatch(removeTransientMessage(messageId));
3229
+ }
3230
+ setLoopStopReason("error");
3231
+ remoteTransientMessageFinalized = true;
3232
+ return rejectWithValue(message);
3233
+ };
3234
+ const abortCliStream = async () => {
3235
+ if (w2) w2.__LOOP_STOP_REASON__ = "aborted";
3236
+ if (accumulated.length <= 0) {
3237
+ return;
3238
+ }
3239
+ await persistMessageWithFixedId(dispatch, buildCliAssistantMessage());
3240
+ };
3241
+ try {
3242
+ const result = await consumeAgentRunStream({
3243
+ reader,
3244
+ decoder,
3245
+ parseChunk: (raw) => {
3246
+ const parsed = [];
3247
+ for (const line of raw.split("\n")) {
3248
+ if (!line.startsWith("data: ")) continue;
3249
+ try {
3250
+ parsed.push(JSON.parse(line.slice(6)));
3251
+ } catch {
3252
+ }
3253
+ }
3254
+ return parsed;
3255
+ },
3256
+ isAborted: () => loopController.signal.aborted || thunkApi.signal.aborted,
3257
+ signal: loopController.signal,
3258
+ onAbort: abortCliStream,
3259
+ isDoneEvent: (payload) => payload?.done === true,
3260
+ onPayload: (payload) => {
3261
+ if (payload.error) {
3262
+ return { reject: payload.error };
3263
+ }
3264
+ if (payload.chunk) {
3265
+ accumulated += payload.chunk;
3266
+ dispatch(messageStreaming({
3267
+ id: messageId,
3268
+ dialogId: dialogId2,
3269
+ dbKey: msgKey,
3270
+ content: accumulated,
3271
+ role: "assistant",
3272
+ ...cliMessageMetadata
3273
+ }));
3274
+ }
3275
+ if (payload.done && Array.isArray(payload.warnings)) {
3276
+ cliCapabilityWarnings = payload.warnings.filter(
3277
+ (warning) => typeof warning === "string" && warning.trim().length > 0
3278
+ );
3279
+ }
3280
+ }
3281
+ });
3282
+ if (result.outcome === "rejected") {
3283
+ return await rejectCliStream(result.message);
3284
+ }
3285
+ if (result.outcome === "aborted") {
3286
+ return { aborted: true };
3287
+ }
3288
+ if (result.outcome === "streamEnded") {
3289
+ if (!result.sawDone) {
3290
+ dispatch(finalizeTransientMessageOnError({
3291
+ id: messageId,
3292
+ error: "CLI \u6D41\u5F0F\u54CD\u5E94\u88AB\u4E2D\u65AD,\u672A\u6536\u5230\u5B8C\u6210\u4FE1\u53F7"
3293
+ }));
3294
+ remoteTransientMessageFinalized = true;
3295
+ setLoopStopReason("error");
3296
+ return rejectWithValue("CLI \u6D41\u5F0F\u54CD\u5E94\u88AB\u4E2D\u65AD,\u672A\u6536\u5230\u5B8C\u6210\u4FE1\u53F7");
3297
+ }
3298
+ if (cliCapabilityWarnings.length > 0) {
3299
+ accumulated = appendCliCapabilityWarnings(accumulated, cliCapabilityWarnings);
3300
+ dispatch(messageStreaming({
3301
+ id: messageId,
3302
+ dialogId: dialogId2,
3303
+ dbKey: msgKey,
3304
+ content: accumulated,
3305
+ role: "assistant",
3306
+ ...cliMessageMetadata
3307
+ }));
3308
+ }
3309
+ await persistMessageWithFixedId(dispatch, buildCliAssistantMessage());
3310
+ remoteTransientMessageFinalized = true;
3311
+ }
3312
+ } finally {
3313
+ try {
3314
+ await reader.cancel();
3315
+ } catch {
3316
+ }
3317
+ }
3318
+ return;
3319
+ }
3320
+ const currentDialog = selectDialogConfigByKey(state, explicitDialogKey) ?? selectCurrentDialogConfig(state);
3321
+ const activeDialogKey = currentDialog?.dbKey;
3322
+ const dialogKey = explicitDialogKey || activeDialogKey;
3323
+ if (!dialogKey) {
3324
+ return rejectWithValue("\u5F53\u524D\u5BF9\u8BDD\u4E0D\u5B58\u5728\uFF0C\u65E0\u6CD5\u53D1\u9001\u6D88\u606F\u3002");
3325
+ }
3326
+ runtimeDialogKey = dialogKey;
3327
+ const dialogId = extractCustomId(dialogKey);
3328
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-dialog-resolved", {
3329
+ dialogKey,
3330
+ dialogId
3331
+ });
3332
+ if (shouldUseDesktopLocalRuntime(agentConfig)) {
3333
+ const desktopMessageMetadata = buildMessageMetadata(agentConfig);
3334
+ const w2 = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
3335
+ loopKey = `loop:${dialogId}`;
3336
+ dispatch(addActiveController({ messageId: loopKey, controller: loopController, dialogKey }));
3337
+ let currentContent = "";
3338
+ const assistantSegments = [];
3339
+ let assistantMessageKeys = null;
3340
+ let streamResult = null;
3341
+ let streamError = null;
3342
+ let reasoningBuffer = "";
3343
+ const activeToolMessages = /* @__PURE__ */ new Map();
3344
+ const ensureAssistantMessageKeys = () => {
3345
+ if (!assistantMessageKeys) {
3346
+ assistantMessageKeys = createDialogMessageKeyAndId(dialogId);
3347
+ assistantSegments.push({
3348
+ key: assistantMessageKeys.key,
3349
+ messageId: assistantMessageKeys.messageId,
3350
+ content: "",
3351
+ finalized: false,
3352
+ toolCallIds: []
3353
+ });
3354
+ remoteTransientMessageId = assistantMessageKeys.messageId;
3355
+ }
3356
+ return assistantMessageKeys;
3357
+ };
3358
+ const streamDesktopAssistantText = (text) => {
3359
+ currentContent += text;
3360
+ const { key: msgKey2, messageId: messageId2 } = ensureAssistantMessageKeys();
3361
+ const segment2 = assistantSegments[assistantSegments.length - 1];
3362
+ segment2.content = currentContent;
3363
+ dispatch(messageStreaming({
3364
+ id: messageId2,
3365
+ dialogId,
3366
+ dbKey: msgKey2,
3367
+ content: currentContent,
3368
+ role: "assistant",
3369
+ isStreaming: true,
3370
+ ...desktopMessageMetadata
3371
+ }));
3372
+ };
3373
+ const finalizeCurrentAssistantSegmentForTool = () => {
3374
+ const segment2 = assistantSegments[assistantSegments.length - 1];
3375
+ if (segment2) {
3376
+ segment2.content = currentContent;
3377
+ segment2.finalized = true;
3378
+ }
3379
+ if (assistantMessageKeys && currentContent.length > 0) {
3380
+ dispatch(messageStreaming({
3381
+ id: assistantMessageKeys.messageId,
3382
+ dialogId,
3383
+ dbKey: assistantMessageKeys.key,
3384
+ content: currentContent,
3385
+ role: "assistant",
3386
+ isStreaming: false,
3387
+ ...desktopMessageMetadata
3388
+ }));
3389
+ }
3390
+ assistantMessageKeys = null;
3391
+ currentContent = "";
3392
+ };
3393
+ try {
3394
+ const desktopAgentRef = agentConfig.dbKey || agentKey;
3395
+ const eventStream = runDesktopAgentRuntimeTurnStream({
3396
+ agentRef: desktopAgentRef,
3397
+ input: userInput,
3398
+ continueDialogId: dialogId,
3399
+ dialogKey,
3400
+ cwd: runtimeOptions?.cwd,
3401
+ restrictShellToWorkspace: runtimeOptions?.restrictShellToWorkspace === true,
3402
+ workspaceToolsHint: runtimeOptions?.workspaceToolsHint === true,
3403
+ agentConfigSnapshot: agentConfig,
3404
+ dialogMessages: selectAllMsgs(getState(), dialogId),
3405
+ signal: loopController.signal
3406
+ });
3407
+ for await (const event of eventStream) {
3408
+ if (loopController.signal.aborted || thunkApi.signal.aborted) {
3409
+ if (w2) w2.__LOOP_STOP_REASON__ = "aborted";
3410
+ break;
3411
+ }
3412
+ if (event.type === "delta") {
3413
+ streamDesktopAssistantText(event.text);
3414
+ } else if (event.type === "thinking") {
3415
+ if (typeof event.content === "string") {
3416
+ reasoningBuffer += event.content;
3417
+ }
3418
+ } else if (event.type === "tool") {
3419
+ const toolEvent = event.event;
3420
+ const callId = toolEvent.toolCallId;
3421
+ if (!callId) continue;
3422
+ if (toolEvent.type === "tool-call") {
3423
+ attachToolCallIdToSegment(assistantSegments, callId);
3424
+ finalizeCurrentAssistantSegmentForTool();
3425
+ const { key: dbKey, messageId: toolMsgId } = createDialogMessageKeyAndId(dialogId);
3426
+ const toolMsg = {
3427
+ id: toolMsgId,
3428
+ dialogId,
3429
+ dbKey,
3430
+ role: "tool",
3431
+ content: "",
3432
+ isStreaming: true,
3433
+ toolName: toolEvent.toolName,
3434
+ toolCallId: callId,
3435
+ ...toolEvent.argumentsPreview ? {
3436
+ toolPayload: {
3437
+ input: {
3438
+ command: toolEvent.argumentsPreview,
3439
+ cmd: toolEvent.argumentsPreview
3440
+ }
3441
+ },
3442
+ metadata: {
3443
+ argumentsPreview: toolEvent.argumentsPreview
3444
+ }
3445
+ } : {}
3446
+ };
3447
+ activeToolMessages.set(callId, toolMsg);
3448
+ dispatch(messageStreaming(toolMsg));
3449
+ } else if (toolEvent.type === "tool-result" || toolEvent.type === "tool-error") {
3450
+ const existing = activeToolMessages.get(callId);
3451
+ if (existing) {
3452
+ const isError = toolEvent.type === "tool-error";
3453
+ const existingMeta = asRecordOrEmpty(existing.metadata);
3454
+ const existingInput = isRecord(existing.toolPayload?.input) ? existing.toolPayload.input : {};
3455
+ const mergedMeta = {
3456
+ ...existingMeta,
3457
+ ...toolEvent.metadata,
3458
+ ...isError ? { error: true, message: toolEvent.message } : {}
3459
+ };
3460
+ const toolResultMsg = {
3461
+ ...existing,
3462
+ isStreaming: false,
3463
+ content: projectDesktopToolUiContent({
3464
+ toolName: toolEvent.toolName || existing.toolName,
3465
+ content: toolEvent.content,
3466
+ summary: toolEvent.summary,
3467
+ message: toolEvent.message,
3468
+ metadata: mergedMeta,
3469
+ argumentsPreview: asOptionalTrimmedString(mergedMeta.argumentsPreview) || asOptionalTrimmedString(existingInput.command) || asOptionalTrimmedString(existingInput.cmd) || void 0
3470
+ }),
3471
+ metadata: mergedMeta
3472
+ };
3473
+ activeToolMessages.set(callId, toolResultMsg);
3474
+ dispatch(messageStreaming(toolResultMsg));
3475
+ }
3476
+ }
3477
+ } else if (event.type === "done") {
3478
+ streamResult = event.result;
3479
+ } else if (event.type === "error") {
3480
+ streamError = event.error;
3481
+ }
3482
+ }
3483
+ } catch (err) {
3484
+ if (isAbortError(err) || loopController.signal.aborted || thunkApi.signal.aborted) {
3485
+ if (w2) w2.__LOOP_STOP_REASON__ = "aborted";
3486
+ } else {
3487
+ streamError = err?.message || "Local turn read stream error";
3488
+ }
3489
+ }
3490
+ if (loopController.signal.aborted || thunkApi.signal.aborted || typeof streamError === "string" && /operation was aborted/i.test(streamError)) {
3491
+ if (w2) w2.__LOOP_STOP_REASON__ = "aborted";
3492
+ const stopKeys = assistantMessageKeys;
3493
+ if (stopKeys) {
3494
+ const last = assistantSegments[assistantSegments.length - 1];
3495
+ if (last && last.messageId === stopKeys.messageId) {
3496
+ last.content = currentContent;
3497
+ }
3498
+ }
3499
+ const stopToolNameById = /* @__PURE__ */ new Map();
3500
+ for (const [callId, toolMsg] of activeToolMessages) {
3501
+ if (!toolMessageWillPersist(toolMsg)) continue;
3502
+ const toolName = toolMsg?.toolName;
3503
+ stopToolNameById.set(
3504
+ callId,
3505
+ typeof toolName === "string" && toolName ? toolName : "tool"
3506
+ );
3507
+ }
3508
+ for (const segment2 of assistantSegments) {
3509
+ const hasContent = segment2.content.trim().length > 0;
3510
+ const hasToolCalls = segment2.toolCallIds && segment2.toolCallIds.length > 0;
3511
+ if (hasContent || hasToolCalls) {
3512
+ const stopToolCalls = buildMinimalToolCallsFromIds(
3513
+ segment2.toolCallIds,
3514
+ stopToolNameById
3515
+ );
3516
+ await persistMessageWithFixedId(dispatch, {
3517
+ id: segment2.messageId,
3518
+ dbKey: segment2.key,
3519
+ role: "assistant",
3520
+ content: segment2.content,
3521
+ ...stopToolCalls.length > 0 ? { tool_calls: stopToolCalls } : {},
3522
+ ...desktopMessageMetadata,
3523
+ userId: selectIdentityUserId(getState())
3524
+ });
3525
+ } else {
3526
+ dispatch(removeTransientMessage(segment2.messageId));
3527
+ }
3528
+ }
3529
+ const durableTools = [];
3530
+ for (const toolMsg of activeToolMessages.values()) {
3531
+ const content = toolMsg?.content;
3532
+ const hasContent = typeof content === "string" ? content.trim().length > 0 : Array.isArray(content) && content.length > 0;
3533
+ if (!hasContent) {
3534
+ dispatch(removeTransientMessage(toolMsg.id));
3535
+ continue;
3536
+ }
3537
+ const stopped = { ...toolMsg, isStreaming: false };
3538
+ dispatch(messageStreaming(stopped));
3539
+ durableTools.push(stopped);
3540
+ }
3541
+ await persistToolMessages(dispatch, durableTools, {
3542
+ isStreaming: false,
3543
+ soft: true
3544
+ });
3545
+ remoteTransientMessageFinalized = true;
3546
+ return { aborted: true };
3547
+ }
3548
+ const finalizeDesktopTurnOnError = async (errorText) => {
3549
+ const errorToolNameById = /* @__PURE__ */ new Map();
3550
+ for (const [callId, toolMsg] of activeToolMessages) {
3551
+ if (!toolMessageWillPersist(toolMsg)) continue;
3552
+ const toolName = toolMsg?.toolName;
3553
+ errorToolNameById.set(
3554
+ callId,
3555
+ typeof toolName === "string" && toolName ? toolName : "tool"
3556
+ );
3557
+ }
3558
+ for (const segment2 of assistantSegments) {
3559
+ const hasContent = segment2.content.trim().length > 0;
3560
+ const hasToolCalls = segment2.toolCallIds && segment2.toolCallIds.length > 0;
3561
+ if (hasContent || hasToolCalls) {
3562
+ const errorToolCalls = buildMinimalToolCallsFromIds(
3563
+ segment2.toolCallIds,
3564
+ errorToolNameById
3565
+ );
3566
+ await persistMessageWithFixedId(dispatch, {
3567
+ id: segment2.messageId,
3568
+ dbKey: segment2.key,
3569
+ role: "assistant",
3570
+ content: segment2.content,
3571
+ ...errorToolCalls.length > 0 ? { tool_calls: errorToolCalls } : {},
3572
+ ...desktopMessageMetadata,
3573
+ userId: selectIdentityUserId(getState())
3574
+ });
3575
+ if (hasContent) {
3576
+ dispatch(finalizeTransientMessageOnError({
3577
+ id: segment2.messageId,
3578
+ error: errorText
3579
+ }));
3580
+ }
3581
+ } else {
3582
+ dispatch(finalizeTransientMessageOnError({
3583
+ id: segment2.messageId,
3584
+ error: errorText
3585
+ }));
3586
+ }
3587
+ }
3588
+ const durableTools = [];
3589
+ for (const toolMsg of activeToolMessages.values()) {
3590
+ const content = toolMsg?.content;
3591
+ const hasContent = typeof content === "string" ? content.trim().length > 0 : Array.isArray(content) && content.length > 0;
3592
+ if (!hasContent) {
3593
+ dispatch(removeTransientMessage(toolMsg.id));
3594
+ continue;
3595
+ }
3596
+ const stopped = { ...toolMsg, isStreaming: false };
3597
+ dispatch(messageStreaming(stopped));
3598
+ durableTools.push(stopped);
3599
+ }
3600
+ await persistToolMessages(dispatch, durableTools, {
3601
+ isStreaming: false,
3602
+ soft: true
3603
+ });
3604
+ remoteTransientMessageFinalized = true;
3605
+ setLoopStopReason("error");
3606
+ };
3607
+ if (streamError) {
3608
+ await finalizeDesktopTurnOnError(streamError);
3609
+ return rejectWithValue(streamError);
3610
+ }
3611
+ if (!streamResult) {
3612
+ const message = "Local turn stream closed unexpectedly without result";
3613
+ await finalizeDesktopTurnOnError(message);
3614
+ return rejectWithValue(message);
3615
+ }
3616
+ const desktopTurnMessages = streamResult.turnMessages || [];
3617
+ const hasSegmentWithCallIds = assistantSegments.some(
3618
+ (s) => s.toolCallIds.length > 0
3619
+ );
3620
+ if (!hasSegmentWithCallIds) {
3621
+ const doneOnlyAssistantCalls = desktopTurnMessages.filter(
3622
+ (m) => m?.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0
3623
+ ).flatMap((m) => m.tool_calls.map((tc) => tc?.id)).filter((id) => typeof id === "string");
3624
+ if (doneOnlyAssistantCalls.length > 0) {
3625
+ ensureAssistantMessageKeys();
3626
+ for (const callId of doneOnlyAssistantCalls) {
3627
+ attachToolCallIdToSegment(assistantSegments, callId);
3628
+ }
3629
+ if (currentContent.length === 0) {
3630
+ finalizeCurrentAssistantSegmentForTool();
3631
+ }
3632
+ }
3633
+ }
3634
+ if (activeToolMessages.size === 0) {
3635
+ for (const toolMessage of buildDesktopRuntimeToolMessagesForUi({
3636
+ dialogId,
3637
+ turnMessages: desktopTurnMessages
3638
+ })) {
3639
+ dispatch(messageStreaming(toolMessage));
3640
+ activeToolMessages.set(
3641
+ asTrimmedString(toolMessage.toolCallId) || toolMessage.id,
3642
+ toolMessage
3643
+ );
3644
+ }
3645
+ }
3646
+ await persistToolMessages(
3647
+ dispatch,
3648
+ activeToolMessages.values(),
3649
+ { isStreaming: false, soft: true }
3650
+ );
3651
+ const earlierFinalizedSegments = selectPersistableFinalizedSegments(assistantSegments);
3652
+ for (const segment2 of earlierFinalizedSegments) {
3653
+ const segmentToolCalls = resolveSegmentToolCalls(
3654
+ segment2.toolCallIds,
3655
+ desktopTurnMessages
3656
+ );
3657
+ dispatch(write({
3658
+ data: {
3659
+ id: segment2.messageId,
3660
+ dbKey: segment2.key,
3661
+ dialogId,
3662
+ content: segment2.content,
3663
+ role: "assistant",
3664
+ isStreaming: false,
3665
+ type: "msg" /* MSG */,
3666
+ ...segmentToolCalls.length > 0 ? { tool_calls: segmentToolCalls } : {},
3667
+ ...desktopMessageMetadata
3668
+ },
3669
+ customKey: segment2.key
3670
+ }));
3671
+ }
3672
+ const { key: msgKey, messageId } = ensureAssistantMessageKeys();
3673
+ const lastSegmentContent = hasInlineExecutedToolCalls(streamResult) ? currentContent || "" : streamResult.content || currentContent || "";
3674
+ const segment = assistantSegments[assistantSegments.length - 1];
3675
+ segment.content = lastSegmentContent;
3676
+ dispatch(messageStreaming({
3677
+ id: messageId,
3678
+ dialogId,
3679
+ dbKey: msgKey,
3680
+ content: lastSegmentContent,
3681
+ role: "assistant",
3682
+ isStreaming: false,
3683
+ ...desktopMessageMetadata
3684
+ }));
3685
+ const lastSegmentToolCalls = segment ? resolveSegmentToolCalls(segment.toolCallIds, desktopTurnMessages) : [];
3686
+ await dispatch(messageStreamEnd({
3687
+ finalContentBuffer: [
3688
+ {
3689
+ type: "text",
3690
+ text: lastSegmentContent
3691
+ }
3692
+ ],
3693
+ totalUsage: streamResult.usage ?? void 0,
3694
+ messageId,
3695
+ msgKey,
3696
+ agentConfig,
3697
+ dialogId,
3698
+ dialogKey,
3699
+ // 优先用本 turn 累计的 thinking SSE;为空时兜底 streamResult.reasoning_content
3700
+ // (provider 在 SSE 流内累计返回的 reasoning_content)。
3701
+ reasoningBuffer: reasoningBuffer || (typeof streamResult?.reasoning_content === "string" ? streamResult.reasoning_content : ""),
3702
+ toolCalls: lastSegmentToolCalls,
3703
+ // 把 provider 报告的 finish_reason 透传给 messageStreamEnd,
3704
+ // 由 assembleFinalAssistantMessage 决定是否写进最终 Message。
3705
+ finishReason: streamResult.finish_reason ?? void 0,
3706
+ messageMetadata: desktopMessageMetadata
3707
+ })).unwrap();
3708
+ remoteTransientMessageFinalized = true;
3709
+ return {
3710
+ usage: streamResult.usage ?? void 0
3711
+ };
3712
+ }
3713
+ const userInputText = extractAgentRunUserText(userInput);
3714
+ const explicitServerBase = asOptionalTrimmedString(args.serverBase) ?? null;
3715
+ const currentServer = selectCurrentServer(state);
3716
+ const normalizedRequestedServerBase = explicitServerBase && normalizeServerOrigin(explicitServerBase);
3717
+ const normalizedCurrentServer = normalizeServerOrigin(
3718
+ currentServer
3719
+ );
3720
+ const canProxyToExplicitServerBase = !Array.isArray(userInput) && !runtimeOptions?.extraTools?.length && !runtimeOptions?.editingTarget && !runtimeOptions?.imageConfigOverride;
3721
+ if (explicitServerBase && canProxyToExplicitServerBase) {
3722
+ if (normalizedRequestedServerBase && normalizedCurrentServer && normalizedRequestedServerBase === normalizedCurrentServer) {
3723
+ } else {
3724
+ const token = selectIdentityToken(state);
3725
+ const authHeader = token ? `Bearer ${token}` : "";
3726
+ const rawMessages = selectAllMsgs(state, dialogId);
3727
+ const visibleMessages = buildAgentViewMessages(
3728
+ rawMessages,
3729
+ agentConfig.dbKey
3730
+ );
3731
+ const cleanedMessages = filterAndCleanMessages(visibleMessages);
3732
+ const { key: msgKey, messageId } = createDialogMessageKeyAndId(dialogId);
3733
+ remoteTransientMessageId = messageId;
3734
+ const remoteMessageMetadata = buildMessageMetadata(agentConfig);
3735
+ let accumulated = "";
3736
+ let totalTurnUsage2 = void 0;
3737
+ const buildRemoteAssistantMessage = () => ({
3738
+ id: messageId,
3739
+ dbKey: msgKey,
3740
+ role: "assistant",
3741
+ content: accumulated,
3742
+ ...remoteMessageMetadata,
3743
+ userId: selectIdentityUserId(getState())
3744
+ });
3745
+ loopKey = `loop:${dialogId}`;
3746
+ dispatch(addActiveController({ messageId: loopKey, controller: loopController, dialogKey }));
3747
+ dispatch(messageStreaming({
3748
+ id: messageId,
3749
+ dialogId,
3750
+ dbKey: msgKey,
3751
+ content: "",
3752
+ role: "assistant",
3753
+ ...remoteMessageMetadata
3754
+ }));
3755
+ const rejectRemoteStream = async (message) => {
3756
+ if (accumulated.length > 0) {
3757
+ await persistMessageWithFixedId(dispatch, buildRemoteAssistantMessage());
3758
+ } else {
3759
+ dispatch(removeTransientMessage(messageId));
3760
+ }
3761
+ setLoopStopReason("error");
3762
+ remoteTransientMessageFinalized = true;
3763
+ return rejectWithValue(message);
3764
+ };
3765
+ const remoteRequestBody = JSON.stringify({
3766
+ agentKey,
3767
+ userInput: agentRunUserInput,
3768
+ messages: cleanedMessages,
3769
+ stream: true,
3770
+ persistDialog: false,
3771
+ clientDialogId: dialogId,
3772
+ runtimeContext: {
3773
+ surface: "web",
3774
+ host: "browser",
3775
+ runtime: "react",
3776
+ entrypoint: "chat-dialog",
3777
+ capabilities: ["streaming", "dialog-ui", "tool-cards"]
3778
+ },
3779
+ ...currentDialog?.spaceId ? { spaceId: currentDialog.spaceId } : {}
3780
+ });
3781
+ const remoteRunUrl = `${explicitServerBase.replace(/\/+$/, "")}/api/agent/run`;
3782
+ const remoteResponse = await performServerProxyFetchWithRetry({
3783
+ execute: () => fetch(remoteRunUrl, {
3784
+ method: "POST",
3785
+ headers: {
3786
+ "Content-Type": "application/json",
3787
+ Accept: "text/event-stream",
3788
+ ...authHeader ? { Authorization: authHeader } : {}
3789
+ },
3790
+ body: remoteRequestBody,
3791
+ signal: loopController.signal
3792
+ }),
3793
+ signal: loopController.signal,
3794
+ logPrefix: "[streamAgentChatTurn.remoteRun]"
3795
+ });
3796
+ if (!remoteResponse.ok) {
3797
+ const errorText = await remoteResponse.text();
3798
+ return await rejectRemoteStream(
3799
+ errorText || `Remote agent run failed (${remoteResponse.status})`
3800
+ );
3801
+ }
3802
+ const reader = remoteResponse.body?.getReader();
3803
+ if (!reader) {
3804
+ return await rejectRemoteStream("\u65E0\u6CD5\u8BFB\u53D6\u8FDC\u7AEF\u6D41\u5F0F\u54CD\u5E94");
3805
+ }
3806
+ const decoder = new TextDecoder();
3807
+ const parseSSE = createSSEParser();
3808
+ const abortRemoteStream = async () => {
3809
+ if (accumulated.length <= 0) return;
3810
+ await persistMessageWithFixedId(dispatch, buildRemoteAssistantMessage());
3811
+ };
3812
+ try {
3813
+ const result = await consumeAgentRunStream({
3814
+ reader,
3815
+ decoder,
3816
+ parseChunk: (raw) => parseSSE(raw),
3817
+ isAborted: () => loopController.signal.aborted || thunkApi.signal.aborted,
3818
+ signal: loopController.signal,
3819
+ onAbort: abortRemoteStream,
3820
+ isDoneEvent: (payload) => payload?.type === "done",
3821
+ onPayload: async (payload) => {
3822
+ if (payload.type === "error") {
3823
+ return { reject: payload.message || "\u8FDC\u7AEF Agent \u6267\u884C\u5931\u8D25" };
3824
+ }
3825
+ if (payload.type === "agent_handoff") {
3826
+ await patchDialogThreadMetadata(
3827
+ dispatch,
3828
+ dialogKey,
3829
+ payload.threadMetadata
3830
+ );
3831
+ await patchDialogActiveAgent(
3832
+ dispatch,
3833
+ dialogKey,
3834
+ payload.agentKey
3835
+ );
3836
+ }
3837
+ if (payload.type === "text" && typeof payload.content === "string") {
3838
+ accumulated += payload.content;
3839
+ dispatch(messageStreaming({
3840
+ id: messageId,
3841
+ dialogId,
3842
+ dbKey: msgKey,
3843
+ content: accumulated,
3844
+ role: "assistant",
3845
+ ...remoteMessageMetadata
3846
+ }));
3847
+ }
3848
+ if (payload.type === "done") {
3849
+ totalTurnUsage2 = payload.usage;
3850
+ }
3851
+ }
3852
+ });
3853
+ if (result.outcome === "rejected") {
3854
+ return await rejectRemoteStream(result.message);
3855
+ }
3856
+ if (result.outcome === "aborted") {
3857
+ return { aborted: true };
3858
+ }
3859
+ if (result.outcome === "streamEnded") {
3860
+ if (!result.sawDone) {
3861
+ dispatch(finalizeTransientMessageOnError({
3862
+ id: messageId,
3863
+ error: "\u8FDC\u7AEF Agent \u6D41\u5F0F\u54CD\u5E94\u88AB\u4E2D\u65AD,\u672A\u6536\u5230\u5B8C\u6210\u4FE1\u53F7"
3864
+ }));
3865
+ remoteTransientMessageFinalized = true;
3866
+ setLoopStopReason("error");
3867
+ return rejectWithValue(
3868
+ "\u8FDC\u7AEF Agent \u6D41\u5F0F\u54CD\u5E94\u88AB\u4E2D\u65AD,\u672A\u6536\u5230\u5B8C\u6210\u4FE1\u53F7"
3869
+ );
3870
+ }
3871
+ await persistMessageWithFixedId(dispatch, buildRemoteAssistantMessage());
3872
+ remoteTransientMessageFinalized = true;
3873
+ }
3874
+ } finally {
3875
+ try {
3876
+ await reader.cancel();
3877
+ } catch {
3878
+ }
3879
+ }
3880
+ return {
3881
+ usage: totalTurnUsage2 ?? void 0
3882
+ };
3883
+ }
3884
+ }
3885
+ let extractedMentions;
3886
+ if (Array.isArray(userInput)) {
3887
+ extractedMentions = extractCategorizedMentions(userInput);
3888
+ }
3889
+ const mentionedTools = extractedMentions?.tools ?? [];
3890
+ const {
3891
+ references: normalizedReferences,
3892
+ contentByKey: referenceContentCache,
3893
+ referencedTools: referenceTools,
3894
+ recommendedSkillTools: referenceRecommendedSkillTools,
3895
+ recommendedSkillHints: referenceRecommendedSkillHints,
3896
+ skillPromptPatches: referenceSkillPromptPatches
3897
+ } = await resolveReferenceAssets(
3898
+ mergeReferences(agentConfig.references, (selectDialogConfigByKey(getState(), explicitDialogKey) ?? selectCurrentDialogConfig(getState()))?.extraReferences),
3899
+ dispatch
3900
+ );
3901
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-references-resolved", {
3902
+ referenceCount: normalizedReferences?.length ?? 0,
3903
+ referencedToolCount: referenceTools?.length ?? 0
3904
+ });
3905
+ const agentConfigWithReferences = {
3906
+ ...agentConfig,
3907
+ references: normalizedReferences,
3908
+ referencedTools: referenceTools,
3909
+ recommendedSkillTools: referenceRecommendedSkillTools,
3910
+ recommendedSkillHints: referenceRecommendedSkillHints,
3911
+ skillPromptPatches: referenceSkillPromptPatches
3912
+ };
3913
+ const initialRawMsgs = selectAllMsgs(state, dialogId);
3914
+ const initialHistoryIds = new Set(initialRawMsgs.map((m) => m.id));
3915
+ const keySets = await getFullChatContextKeys(
3916
+ state,
3917
+ dispatch,
3918
+ agentConfigWithReferences,
3919
+ userInput,
3920
+ currentDialog ?? void 0
3921
+ );
3922
+ const finalKeys = deduplicateContextKeys(keySets);
3923
+ const allContextKeys = /* @__PURE__ */ new Set([
3924
+ ...finalKeys.botInstructionsContext,
3925
+ ...finalKeys.currentInputContext,
3926
+ ...finalKeys.historyContext,
3927
+ ...finalKeys.botKnowledgeContext
3928
+ ]);
3929
+ const {
3930
+ tools: contextTools,
3931
+ contentByKey: contextContentCache,
3932
+ recommendedSkillTools: contextRecommendedSkillTools = [],
3933
+ recommendedSkillHints: contextRecommendedSkillHints = [],
3934
+ skillPromptPatches: contextSkillPromptPatches = []
3935
+ } = await resolveToolsFromKeys(
3936
+ Array.from(allContextKeys),
3937
+ dispatch,
3938
+ referenceContentCache
3939
+ );
3940
+ const mergedContentCache = new Map([
3941
+ ...referenceContentCache,
3942
+ ...contextContentCache
3943
+ ]);
3944
+ const agentConfigWithTools = mergeAgentToolsWithRuntime(
3945
+ {
3946
+ ...agentConfigWithReferences,
3947
+ recommendedSkillTools: [
3948
+ ...agentConfigWithReferences.recommendedSkillTools ?? [],
3949
+ ...contextRecommendedSkillTools
3950
+ ],
3951
+ recommendedSkillHints: [
3952
+ ...agentConfigWithReferences.recommendedSkillHints ?? [],
3953
+ ...contextRecommendedSkillHints
3954
+ ],
3955
+ skillPromptPatches: [
3956
+ ...agentConfigWithReferences.skillPromptPatches ?? [],
3957
+ ...contextSkillPromptPatches
3958
+ ]
3959
+ },
3960
+ contextTools,
3961
+ mentionedTools,
3962
+ runtimeOptions,
3963
+ state
3964
+ );
3965
+ const agentConfigForCall = applyImageConfigRuntimeOverride(
3966
+ agentConfigWithTools,
3967
+ runtimeOptions
3968
+ );
3969
+ const effectiveAgentConfig = agentConfigForCall;
3970
+ const initialImageGenerationState = resolveImageGenerationStreamingState(
3971
+ effectiveAgentConfig
3972
+ );
3973
+ const streamingMessageMetadata = {
3974
+ ...buildMessageMetadata(agentConfigForCall),
3975
+ ...initialImageGenerationState ? { imageGenerationState: initialImageGenerationState } : {}
3976
+ };
3977
+ const isRespModel = resolveClientWire(
3978
+ resolveAgentCallPlan(agentConfigForCall, {})
3979
+ ) === "responses";
3980
+ if (isRespModel) {
3981
+ const maxExecutionTime2 = selectMaxExecutionTime(state);
3982
+ const MAX_TIME_MS2 = maxExecutionTime2 > 0 ? maxExecutionTime2 : 24e4;
3983
+ const startTime2 = Date.now();
3984
+ const staticContexts2 = await buildStaticContextsWithToolsPrewarm(
3985
+ state,
3986
+ dispatch,
3987
+ agentConfigForCall,
3988
+ currentDialog ?? void 0,
3989
+ mergedContentCache
3990
+ );
3991
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-static-context-ready", {
3992
+ model: agentConfigForCall.model,
3993
+ responseApi: true
3994
+ });
3995
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-post-static-entered", {
3996
+ responseApi: true
3997
+ });
3998
+ let appendTempUserInput2 = true;
3999
+ let currentParentMessageId2 = parentMessageId ?? void 0;
4000
+ const w2 = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
4001
+ if (w2) w2.__LOOP_STOP_REASON__ = null;
4002
+ loopKey = `loop:${dialogId}`;
4003
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-active-controller-adding", {
4004
+ responseApi: true
4005
+ });
4006
+ dispatch(addActiveController({ messageId: loopKey, controller: loopController, dialogKey }));
4007
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-active-controller-added", {
4008
+ responseApi: true
4009
+ });
4010
+ for (; ; ) {
4011
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-loop-entered", {
4012
+ responseApi: true
4013
+ });
4014
+ const requestParentMessageId = currentParentMessageId2;
4015
+ if (loopController.signal.aborted || thunkApi.signal.aborted) {
4016
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-loop-aborted-before-context", {
4017
+ loopControllerAborted: loopController.signal.aborted,
4018
+ thunkSignalAborted: thunkApi.signal.aborted,
4019
+ responseApi: true
4020
+ });
4021
+ if (w2) w2.__LOOP_STOP_REASON__ = "aborted";
4022
+ return { aborted: true };
4023
+ }
4024
+ const loopState = getState();
4025
+ const now = Date.now();
4026
+ if (now - startTime2 > MAX_TIME_MS2) {
4027
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-loop-timeout-before-context", {
4028
+ maxTimeMs: MAX_TIME_MS2,
4029
+ elapsedMs: now - startTime2,
4030
+ responseApi: true
4031
+ });
4032
+ if (w2) w2.__LOOP_STOP_REASON__ = "timeout";
4033
+ break;
4034
+ }
4035
+ const accessError = validateAccessAndBalance(
4036
+ agentConfigForCall,
4037
+ loopState
4038
+ );
4039
+ if (accessError) {
4040
+ const accessErrorReason = classifyQuickChatAccessError(accessError);
4041
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-access-error-before-context", {
4042
+ hasAccessError: true,
4043
+ reason: accessErrorReason,
4044
+ responseApi: true
4045
+ });
4046
+ if (quickChatPerfStartedAt && runtimeDialogKey && !modelRequestStarted) {
4047
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-access-error-finalized", {
4048
+ reason: accessErrorReason,
4049
+ responseApi: true
4050
+ });
4051
+ await finalizeQuickChatAgentTurnFailure(
4052
+ dispatch,
4053
+ runtimeDialogKey,
4054
+ agentKey,
4055
+ new Error(accessError)
4056
+ );
4057
+ }
4058
+ setLoopStopReason("error");
4059
+ return rejectWithValue(accessError);
4060
+ }
4061
+ const willSkipDynamicContext = canUseQuickChatEmptyDynamicContexts(
4062
+ quickChatPerfStartedAt,
4063
+ userInput,
4064
+ runtimeOptions,
4065
+ currentDialog,
4066
+ agentConfigForCall
4067
+ );
4068
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-dynamic-context-decision", {
4069
+ hasRuntimeOptions: !!runtimeOptions,
4070
+ isSimpleTextInput: isSimpleTextInput(userInput),
4071
+ referenceKeyCount: currentDialog?.referenceKeys?.length ?? 0,
4072
+ willSkipDynamicContext,
4073
+ responseApi: true
4074
+ });
4075
+ const dynamicContexts = willSkipDynamicContext ? (logQuickChatPerfStage2(
4076
+ quickChatPerfStartedAt,
4077
+ "stream-agent-dynamic-context-skipped",
4078
+ {
4079
+ reason: "simple-quick-chat-first-turn",
4080
+ responseApi: true
4081
+ }
4082
+ ), EMPTY_DYNAMIC_CONTEXTS) : await buildDynamicContextsForTurn(
4083
+ loopState,
4084
+ dispatch,
4085
+ agentConfigForCall,
4086
+ userInput,
4087
+ runtimeOptions,
4088
+ mergedContentCache,
4089
+ dialogKey,
4090
+ quickChatPerfStartedAt
4091
+ );
4092
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-dynamic-context-ready", {
4093
+ responseApi: true
4094
+ });
4095
+ const contexts = mergeContexts(staticContexts2, dynamicContexts);
4096
+ const rawMessages = selectAllMsgs(loopState, dialogId);
4097
+ let visibleMessages = buildAgentViewMessages(
4098
+ rawMessages,
4099
+ agentConfigForCall.dbKey
4100
+ );
4101
+ if (appendTempUserInput2 && hasAgentRunUserInputContent(agentRunUserInput) && !isLastMessageMatchingUserInput(visibleMessages, agentRunUserInput)) {
4102
+ visibleMessages = [
4103
+ ...visibleMessages,
4104
+ {
4105
+ id: `__tmp_user_${Date.now()}`,
4106
+ dbKey: "",
4107
+ role: "user",
4108
+ content: agentRunUserInput,
4109
+ thinkContent: "",
4110
+ cybotKey: agentConfigForCall.dbKey,
4111
+ isStreaming: false
4112
+ }
4113
+ ];
4114
+ }
4115
+ const cleanedMessages = filterAndCleanMessages(visibleMessages);
4116
+ const ctxWindow = getModelContextWindow(agentConfigForCall.model) || 128e3;
4117
+ const summaryTokenCount = contexts.dialogSummary ? estimateTokenCount(contexts.dialogSummary) : 0;
4118
+ const processedMessages = trimMessagesWithSummary(
4119
+ compressOldToolResults(cleanedMessages),
4120
+ ctxWindow,
4121
+ summaryTokenCount
4122
+ );
4123
+ let firstDynamicIdx = processedMessages.findIndex(
4124
+ (m) => m.id && !initialHistoryIds.has(m.id)
4125
+ );
4126
+ if (firstDynamicIdx === -1) firstDynamicIdx = processedMessages.length;
4127
+ const stableMessages = processedMessages.slice(0, firstDynamicIdx);
4128
+ const dynamicMessages = processedMessages.slice(firstDynamicIdx);
4129
+ if (appendTempUserInput2) {
4130
+ const rejectReason = shouldRejectImageInputForAgent(
4131
+ agentConfigForCall,
4132
+ processedMessages
4133
+ );
4134
+ if (rejectReason) {
4135
+ setLoopStopReason("error");
4136
+ return rejectWithValue(rejectReason);
4137
+ }
4138
+ }
4139
+ const bodyData = generateRequestBody({
4140
+ agentConfig: effectiveAgentConfig,
4141
+ messages: dynamicMessages,
4142
+ stableMessages,
4143
+ userInput: userInputText,
4144
+ contexts
4145
+ });
4146
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-model-request-starting", {
4147
+ responseApi: true,
4148
+ dynamicMessageCount: dynamicMessages.length,
4149
+ stableMessageCount: stableMessages.length
4150
+ });
4151
+ modelRequestStarted = true;
4152
+ const meta = await sendOpenAIResponseRequest({
4153
+ bodyData,
4154
+ agentConfig: agentConfigForCall,
4155
+ thunkApi,
4156
+ dialogKey,
4157
+ parentMessageId: currentParentMessageId2,
4158
+ messageMetadata: streamingMessageMetadata,
4159
+ quickChatPerfStartedAt
4160
+ });
4161
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-model-request-finished", {
4162
+ responseApi: true,
4163
+ hasToolCalls: meta.hasToolCalls,
4164
+ hasHandedOff: meta.hasHandedOff,
4165
+ hasPendingInteraction: meta.hasPendingInteraction
4166
+ });
4167
+ appendTempUserInput2 = false;
4168
+ currentParentMessageId2 = void 0;
4169
+ totalTurnUsage = updateTotalUsage(totalTurnUsage, meta.usage);
4170
+ if (meta.hasHandedOff) {
4171
+ if (!requestParentMessageId && meta.messageId) {
4172
+ dispatch(removeTransientMessage(meta.messageId));
4173
+ }
4174
+ if (w2) w2.__LOOP_STOP_REASON__ = "handoff";
4175
+ break;
4176
+ }
4177
+ if (meta.hasPendingInteraction) {
4178
+ if (w2) w2.__LOOP_STOP_REASON__ = "pending";
4179
+ break;
4180
+ }
4181
+ const afterTurnState = getState();
4182
+ const queuedMessages = selectPendingUserInputQueue(afterTurnState, dialogKey);
4183
+ if (queuedMessages.length > 0) {
4184
+ const queuedText = queuedMessages[0];
4185
+ const currentDialogConfig = selectDialogConfigByKey(afterTurnState, dialogKey) ?? selectCurrentDialogConfig(afterTurnState);
4186
+ if (!currentDialogConfig) {
4187
+ dispatch(clearPendingUserInputQueue({ dialogKey }));
4188
+ break;
4189
+ }
4190
+ await dispatch(
4191
+ prepareAndPersistUserMessage({
4192
+ userInput: queuedText,
4193
+ dialogConfig: currentDialogConfig
4194
+ })
4195
+ ).unwrap();
4196
+ dispatch(dequeueUserInput({ dialogKey }));
4197
+ continue;
4198
+ }
4199
+ if (!meta.hasToolCalls) {
4200
+ if (w2) w2.__LOOP_STOP_REASON__ = "done";
4201
+ break;
4202
+ }
4203
+ }
4204
+ return {
4205
+ usage: totalTurnUsage ?? void 0
4206
+ };
4207
+ }
4208
+ const maxExecutionTime = selectMaxExecutionTime(state);
4209
+ const MAX_TIME_MS = maxExecutionTime > 0 ? maxExecutionTime : 24e4;
4210
+ const startTime = Date.now();
4211
+ const staticContexts = await buildStaticContextsWithToolsPrewarm(
4212
+ state,
4213
+ dispatch,
4214
+ agentConfigForCall,
4215
+ currentDialog ?? void 0,
4216
+ mergedContentCache
4217
+ );
4218
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-static-context-ready", {
4219
+ model: agentConfigForCall.model,
4220
+ responseApi: false
4221
+ });
4222
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-post-static-entered", {
4223
+ responseApi: false
4224
+ });
4225
+ let appendTempUserInput = true;
4226
+ let currentParentMessageId = parentMessageId ?? void 0;
4227
+ const w = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
4228
+ if (w) w.__LOOP_STOP_REASON__ = null;
4229
+ if (!isRespModel) {
4230
+ loopKey = `loop:${dialogId}`;
4231
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-active-controller-adding", {
4232
+ responseApi: false
4233
+ });
4234
+ dispatch(addActiveController({ messageId: loopKey, controller: loopController, dialogKey }));
4235
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-active-controller-added", {
4236
+ responseApi: false
4237
+ });
4238
+ }
4239
+ for (; ; ) {
4240
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-loop-entered", {
4241
+ responseApi: false
4242
+ });
4243
+ const requestParentMessageId = currentParentMessageId;
4244
+ if (loopController.signal.aborted || thunkApi.signal.aborted) {
4245
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-loop-aborted-before-context", {
4246
+ loopControllerAborted: loopController.signal.aborted,
4247
+ thunkSignalAborted: thunkApi.signal.aborted,
4248
+ responseApi: false
4249
+ });
4250
+ if (w) w.__LOOP_STOP_REASON__ = "aborted";
4251
+ return { aborted: true };
4252
+ }
4253
+ const loopState = getState();
4254
+ const now = Date.now();
4255
+ if (now - startTime > MAX_TIME_MS) {
4256
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-loop-timeout-before-context", {
4257
+ maxTimeMs: MAX_TIME_MS,
4258
+ elapsedMs: now - startTime,
4259
+ responseApi: false
4260
+ });
4261
+ if (w) w.__LOOP_STOP_REASON__ = "timeout";
4262
+ break;
4263
+ }
4264
+ const accessError = validateAccessAndBalance(
4265
+ agentConfigForCall,
4266
+ loopState
4267
+ );
4268
+ if (accessError) {
4269
+ const accessErrorReason = classifyQuickChatAccessError(accessError);
4270
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-access-error-before-context", {
4271
+ hasAccessError: true,
4272
+ reason: accessErrorReason,
4273
+ responseApi: false
4274
+ });
4275
+ if (quickChatPerfStartedAt && runtimeDialogKey && !modelRequestStarted) {
4276
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-access-error-finalized", {
4277
+ reason: accessErrorReason,
4278
+ responseApi: false
4279
+ });
4280
+ await finalizeQuickChatAgentTurnFailure(
4281
+ dispatch,
4282
+ runtimeDialogKey,
4283
+ agentKey,
4284
+ new Error(accessError)
4285
+ );
4286
+ }
4287
+ setLoopStopReason("error");
4288
+ return rejectWithValue(accessError);
4289
+ }
4290
+ const willSkipDynamicContext = canUseQuickChatEmptyDynamicContexts(
4291
+ quickChatPerfStartedAt,
4292
+ userInput,
4293
+ runtimeOptions,
4294
+ currentDialog,
4295
+ agentConfigForCall
4296
+ );
4297
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-dynamic-context-decision", {
4298
+ hasRuntimeOptions: !!runtimeOptions,
4299
+ isSimpleTextInput: isSimpleTextInput(userInput),
4300
+ referenceKeyCount: currentDialog?.referenceKeys?.length ?? 0,
4301
+ willSkipDynamicContext,
4302
+ responseApi: false
4303
+ });
4304
+ const dynamicContexts = willSkipDynamicContext ? (logQuickChatPerfStage2(
4305
+ quickChatPerfStartedAt,
4306
+ "stream-agent-dynamic-context-skipped",
4307
+ {
4308
+ reason: "simple-quick-chat-first-turn",
4309
+ responseApi: false
4310
+ }
4311
+ ), EMPTY_DYNAMIC_CONTEXTS) : await buildDynamicContextsForTurn(
4312
+ loopState,
4313
+ dispatch,
4314
+ agentConfigForCall,
4315
+ userInput,
4316
+ runtimeOptions,
4317
+ mergedContentCache,
4318
+ dialogKey,
4319
+ quickChatPerfStartedAt
4320
+ );
4321
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-dynamic-context-ready", {
4322
+ responseApi: false
4323
+ });
4324
+ const contexts = mergeContexts(staticContexts, dynamicContexts);
4325
+ const rawMessages = selectAllMsgs(loopState, dialogId);
4326
+ let visibleMessages = buildAgentViewMessages(
4327
+ rawMessages,
4328
+ agentConfigForCall.dbKey
4329
+ );
4330
+ if (appendTempUserInput && hasAgentRunUserInputContent(agentRunUserInput) && !isLastMessageMatchingUserInput(visibleMessages, agentRunUserInput)) {
4331
+ visibleMessages = [
4332
+ ...visibleMessages,
4333
+ {
4334
+ id: `__tmp_user_${Date.now()}`,
4335
+ dbKey: "",
4336
+ role: "user",
4337
+ content: agentRunUserInput,
4338
+ thinkContent: "",
4339
+ cybotKey: agentConfigForCall.dbKey,
4340
+ isStreaming: false
4341
+ }
4342
+ ];
4343
+ }
4344
+ const cleanedMessages = filterAndCleanMessages(visibleMessages);
4345
+ const ctxWindow = getModelContextWindow(agentConfigForCall.model) || 128e3;
4346
+ const summaryTokenCount = contexts.dialogSummary ? estimateTokenCount(contexts.dialogSummary) : 0;
4347
+ const processedMessages = trimMessagesWithSummary(
4348
+ compressOldToolResults(cleanedMessages),
4349
+ ctxWindow,
4350
+ summaryTokenCount
4351
+ );
4352
+ let firstDynamicIdx = processedMessages.findIndex(
4353
+ (m) => m.id && !initialHistoryIds.has(m.id)
4354
+ );
4355
+ if (firstDynamicIdx === -1) firstDynamicIdx = processedMessages.length;
4356
+ const stableMessages = processedMessages.slice(0, firstDynamicIdx);
4357
+ const dynamicMessages = processedMessages.slice(firstDynamicIdx);
4358
+ if (appendTempUserInput) {
4359
+ const rejectReason = shouldRejectImageInputForAgent(
4360
+ agentConfigForCall,
4361
+ processedMessages
4362
+ );
4363
+ if (rejectReason) {
4364
+ setLoopStopReason("error");
4365
+ return rejectWithValue(rejectReason);
4366
+ }
4367
+ }
4368
+ const bodyData = generateRequestBody({
4369
+ agentConfig: effectiveAgentConfig,
4370
+ messages: dynamicMessages,
4371
+ stableMessages,
4372
+ userInput: userInputText,
4373
+ contexts
4374
+ });
4375
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-model-request-starting", {
4376
+ responseApi: false,
4377
+ dynamicMessageCount: dynamicMessages.length,
4378
+ stableMessageCount: stableMessages.length
4379
+ });
4380
+ modelRequestStarted = true;
4381
+ const disableToolsForThisRequest = shouldDisableQuickChatToolsForDirectAnswer(
4382
+ quickChatPerfStartedAt,
4383
+ userInput,
4384
+ runtimeOptions,
4385
+ currentDialog
4386
+ );
4387
+ if (disableToolsForThisRequest) {
4388
+ logQuickChatPerfStage2(
4389
+ quickChatPerfStartedAt,
4390
+ "stream-agent-tools-disabled-for-direct-answer",
4391
+ {
4392
+ responseApi: false,
4393
+ toolCount: Array.isArray(agentConfigForCall.tools) ? agentConfigForCall.tools.length : 0
4394
+ }
4395
+ );
4396
+ }
4397
+ const meta = await sendOpenAICompletionsRequest({
4398
+ bodyData,
4399
+ agentConfig: agentConfigForCall,
4400
+ thunkApi,
4401
+ dialogKey,
4402
+ parentMessageId: currentParentMessageId,
4403
+ messageMetadata: streamingMessageMetadata,
4404
+ disableToolsForThisRequest,
4405
+ quickChatPerfStartedAt
4406
+ });
4407
+ logQuickChatPerfStage2(quickChatPerfStartedAt, "stream-agent-model-request-finished", {
4408
+ responseApi: false,
4409
+ hasToolCalls: meta.hasToolCalls,
4410
+ hasHandedOff: meta.hasHandedOff,
4411
+ hasPendingInteraction: meta.hasPendingInteraction
4412
+ });
4413
+ appendTempUserInput = false;
4414
+ currentParentMessageId = void 0;
4415
+ totalTurnUsage = updateTotalUsage(totalTurnUsage, meta.usage);
4416
+ if (meta.hasHandedOff) {
4417
+ if (!requestParentMessageId && meta.messageId) {
4418
+ dispatch(removeTransientMessage(meta.messageId));
4419
+ }
4420
+ if (w) w.__LOOP_STOP_REASON__ = "handoff";
4421
+ break;
4422
+ }
4423
+ if (meta.hasPendingInteraction) {
4424
+ if (w) w.__LOOP_STOP_REASON__ = "pending";
4425
+ break;
4426
+ }
4427
+ const afterTurnState = getState();
4428
+ const queuedMessages = selectPendingUserInputQueue(afterTurnState, dialogKey);
4429
+ if (queuedMessages.length > 0) {
4430
+ const queuedText = queuedMessages[0];
4431
+ const currentDialogConfig = selectDialogConfigByKey(afterTurnState, dialogKey) ?? selectCurrentDialogConfig(afterTurnState);
4432
+ if (!currentDialogConfig) {
4433
+ dispatch(clearPendingUserInputQueue({ dialogKey }));
4434
+ break;
4435
+ }
4436
+ await dispatch(
4437
+ prepareAndPersistUserMessage({
4438
+ userInput: queuedText,
4439
+ dialogConfig: currentDialogConfig
4440
+ })
4441
+ ).unwrap();
4442
+ dispatch(dequeueUserInput({ dialogKey }));
4443
+ continue;
4444
+ }
4445
+ if (!meta.hasToolCalls) {
4446
+ if (w) w.__LOOP_STOP_REASON__ = "done";
4447
+ break;
4448
+ }
4449
+ }
4450
+ return {
4451
+ usage: totalTurnUsage ?? void 0
4452
+ };
4453
+ } catch (error) {
4454
+ if (isTurnAborted(error)) {
4455
+ turnAborted = true;
4456
+ if (remoteTransientMessageId && !remoteTransientMessageFinalized) {
4457
+ dispatch(removeTransientMessage(remoteTransientMessageId));
4458
+ remoteTransientMessageFinalized = true;
4459
+ }
4460
+ const w = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
4461
+ if (w) w.__LOOP_STOP_REASON__ = "aborted";
4462
+ return { aborted: true };
4463
+ }
4464
+ console.error(
4465
+ `Error in streamAgentChatTurn for [${agentKey}]:`,
4466
+ error
4467
+ );
4468
+ if (remoteTransientMessageId && !remoteTransientMessageFinalized) {
4469
+ dispatch(finalizeTransientMessageOnError({
4470
+ id: remoteTransientMessageId,
4471
+ error: toErrorMessage(error)
4472
+ }));
4473
+ remoteTransientMessageFinalized = true;
4474
+ setLoopStopReason("error");
4475
+ }
4476
+ if (quickChatPerfStartedAt && runtimeDialogKey && !modelRequestStarted && !remoteTransientMessageId) {
4477
+ await finalizeQuickChatAgentTurnFailure(
4478
+ dispatch,
4479
+ runtimeDialogKey,
4480
+ agentKey,
4481
+ error
4482
+ );
4483
+ } else if (!isTurnAborted(error)) {
4484
+ setLoopStopReason("error");
4485
+ }
4486
+ return rejectWithValue(
4487
+ error?.message || "An unexpected error occurred in streamAgentChatTurn."
4488
+ );
4489
+ } finally {
4490
+ if (loopKey && runtimeDialogKey) {
4491
+ dispatch(removeActiveController({ messageId: loopKey, dialogKey: runtimeDialogKey }));
4492
+ } else if (loopKey) {
4493
+ dispatch(removeActiveController(loopKey));
4494
+ }
4495
+ if (turnAborted) {
4496
+ dispatch(clearPendingUserInputQueue(runtimeDialogKey ? { dialogKey: runtimeDialogKey } : void 0));
4497
+ }
4498
+ if (runtimeDialogKey) {
4499
+ dispatch(runChatQueueTurnEnd({
4500
+ dialogKey: runtimeDialogKey,
4501
+ ok: !turnAborted,
4502
+ aborted: turnAborted
4503
+ }));
4504
+ }
4505
+ thunkApi.signal.removeEventListener("abort", onAbort);
4506
+ }
4507
+ };
4508
+ export {
4509
+ streamAgentChatTurnHandler
4510
+ };