nolo-cli 0.1.40 → 0.1.42

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 (482) hide show
  1. package/README.md +27 -12
  2. package/agent-runtime/agentThread.ts +222 -0
  3. package/agent-runtime/agentThreadAdmission.ts +74 -0
  4. package/agent-runtime/dialogWritePlan.ts +42 -0
  5. package/agent-runtime/hostAdapter.ts +1 -0
  6. package/agent-runtime/hybridRecordStore.ts +5 -3
  7. package/agent-runtime/index.ts +43 -0
  8. package/agent-runtime/localLoop.ts +31 -2
  9. package/agent-runtime/localToolPolicy.ts +1 -0
  10. package/agent-runtime/localWorkspaceTools.ts +1258 -78
  11. package/agent-runtime/noloWorkspaceTools.ts +20 -1
  12. package/agent-runtime/runtimeToolPolicy.ts +1 -5
  13. package/agent-runtime/runtimeToolSurface.ts +1 -0
  14. package/agentAliases.ts +29 -9
  15. package/agentInternalCommandEntries.ts +11 -3
  16. package/agentMachineCommands.ts +1 -0
  17. package/agentRecordCommands.ts +2 -2
  18. package/agentRecordHelpers.ts +59 -6
  19. package/agentRunCommand.ts +84 -19
  20. package/ai/agent/_executeModel.ts +146 -0
  21. package/ai/agent/agentSlice.ts +556 -1
  22. package/ai/agent/appWorkingMemory.ts +126 -0
  23. package/ai/agent/buildEditingContext.ts +378 -0
  24. package/ai/agent/buildSystemPrompt.ts +599 -0
  25. package/ai/agent/canvasEditingContext.ts +49 -0
  26. package/ai/agent/cleanAgentMessages.ts +140 -0
  27. package/ai/agent/cliChatClient.ts +153 -0
  28. package/ai/agent/cliExecutor.ts +264 -46
  29. package/ai/agent/contextCompiler.ts +107 -0
  30. package/ai/agent/contextLayerContract.ts +44 -0
  31. package/ai/agent/createAgentSchema.ts +272 -0
  32. package/ai/agent/currentTimeContext.ts +65 -0
  33. package/ai/agent/executeToolCall.ts +58 -0
  34. package/ai/agent/fetchAgentContexts.ts +42 -0
  35. package/ai/agent/generatePrompt.ts +3 -0
  36. package/ai/agent/getFullChatContextKeys.ts +168 -0
  37. package/ai/agent/guidedCreation/capabilities.ts +84 -0
  38. package/ai/agent/guidedCreation/types.ts +38 -0
  39. package/ai/agent/isLiveAudioOnlyAgent.ts +26 -0
  40. package/ai/agent/liveAudioModel.ts +2 -0
  41. package/ai/agent/pageBuilderHandoffRules.ts +75 -0
  42. package/ai/agent/persistMessageWithFixedId.ts +37 -0
  43. package/ai/agent/planSlice.ts +259 -0
  44. package/ai/agent/referenceUtils.ts +229 -0
  45. package/ai/agent/runAgentBackground.ts +310 -0
  46. package/ai/agent/runAgentClientLoop.ts +164 -0
  47. package/ai/agent/runtimeGuidance.ts +116 -0
  48. package/ai/agent/serverOrigin.ts +7 -0
  49. package/ai/agent/startParallelAgentStreams.ts +424 -0
  50. package/ai/agent/startupProtocol.ts +53 -0
  51. package/ai/agent/streamAgentChatTurn.ts +2135 -0
  52. package/ai/agent/streamAgentChatTurnUtils.ts +923 -0
  53. package/ai/agent/toolFailureGuard.ts +99 -0
  54. package/ai/agent/types.ts +73 -0
  55. package/ai/agent/utils/imageOutput.ts +37 -0
  56. package/ai/agent/utils/publicImageAgentMode.ts +26 -0
  57. package/ai/ai.locale.ts +1165 -0
  58. package/ai/chat/accumulateToolCallChunks.ts +126 -0
  59. package/ai/chat/fetchUtils.ts +143 -0
  60. package/ai/chat/inlineImageUrlsForCustomProvider.ts +122 -0
  61. package/ai/chat/parseApiError.ts +67 -0
  62. package/ai/chat/parseMultilineSSE.ts +95 -0
  63. package/ai/chat/sendOpenAICompletionsRequest.ts +921 -0
  64. package/ai/chat/sendOpenAIResponseRequest.ts +720 -0
  65. package/ai/chat/serverProxyRetry.ts +102 -0
  66. package/ai/chat/shouldUseServerProxy.ts +18 -0
  67. package/ai/chat/streamRetry.ts +46 -0
  68. package/ai/chat/updateTotalUsage.ts +89 -0
  69. package/ai/context/buildReferenceContext.ts +437 -0
  70. package/ai/context/retention.ts +165 -0
  71. package/ai/context/tokenUtils.ts +78 -0
  72. package/ai/llm/agentCapabilities.ts +74 -0
  73. package/ai/llm/deepinfra.ts +79 -0
  74. package/ai/llm/fireworks.ts +68 -0
  75. package/ai/llm/generateRequestBody.ts +165 -0
  76. package/ai/llm/getModelContextWindow.ts +93 -0
  77. package/ai/llm/getPricing.ts +252 -0
  78. package/ai/llm/imagePricing.ts +66 -0
  79. package/ai/llm/isResponseAPIModel.ts +13 -0
  80. package/ai/llm/kimi.ts +22 -0
  81. package/ai/llm/mimo.ts +99 -0
  82. package/ai/llm/mistral.ts +21 -0
  83. package/ai/llm/models.ts +45 -0
  84. package/ai/llm/openrouterModels.ts +31 -0
  85. package/ai/llm/providers.ts +313 -0
  86. package/ai/llm/reasoningModels.ts +27 -0
  87. package/ai/llm/types.ts +82 -0
  88. package/ai/llm/usageRequestOptions.ts +59 -0
  89. package/ai/memory/policy.ts +49 -0
  90. package/ai/memory/queryShared.ts +167 -0
  91. package/ai/memory/recentRelationshipRecap.ts +251 -0
  92. package/ai/memory/remember.ts +111 -0
  93. package/ai/memory/scope.ts +74 -0
  94. package/ai/memory/store.ts +20 -0
  95. package/ai/memory/storeShared.ts +76 -0
  96. package/ai/memory/types.ts +52 -0
  97. package/ai/memory/understanding.ts +341 -0
  98. package/ai/memory/understandingGreeting.ts +264 -0
  99. package/ai/policy/personalizationDialog.ts +333 -0
  100. package/ai/policy/runtimePolicy.ts +526 -0
  101. package/ai/policy/selfUpdateFields.ts +48 -0
  102. package/ai/policy/types.ts +64 -0
  103. package/ai/skills/referenceRuntime.ts +274 -0
  104. package/ai/skills/skillDiagnostics.ts +251 -0
  105. package/ai/skills/skillDocBuilder.ts +139 -0
  106. package/ai/skills/skillSummaryMarker.ts +26 -0
  107. package/ai/token/calculatePrice.ts +576 -0
  108. package/ai/token/missingUsageEstimate.ts +42 -0
  109. package/ai/token/normalizeUsage.ts +124 -0
  110. package/ai/token/openaiImageGenerationUsage.ts +56 -0
  111. package/ai/token/prepareTokenUsageData.ts +93 -0
  112. package/ai/token/resolveBillingTarget.ts +52 -0
  113. package/ai/token/saveTokenRecord.ts +53 -0
  114. package/ai/token/types.ts +103 -0
  115. package/ai/tools/agent/agentTools.ts +214 -0
  116. package/ai/tools/agent/agentUpdateShared.ts +311 -0
  117. package/ai/tools/agent/callAgentTool.ts +139 -0
  118. package/ai/tools/agent/createAgentTool.ts +512 -0
  119. package/ai/tools/agent/createDialogTool.ts +69 -0
  120. package/ai/tools/agent/createSkillAgentTool.ts +62 -0
  121. package/ai/tools/agent/parallelBudget.ts +221 -0
  122. package/ai/tools/agent/prepareAgentDraftTool.ts +159 -0
  123. package/ai/tools/agent/presets/appBuilderPreset.ts +154 -0
  124. package/ai/tools/agent/runLlmTool.ts +96 -0
  125. package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
  126. package/ai/tools/agent/skillAgentArgs.ts +106 -0
  127. package/ai/tools/agent/startAgentDialogTool.ts +54 -0
  128. package/ai/tools/agent/streamParallelAgentsTool.ts +123 -0
  129. package/ai/tools/agent/updateAgentTool.ts +96 -0
  130. package/ai/tools/agent/updateSelfTool.ts +113 -0
  131. package/ai/tools/amazonProductScraperTool.ts +86 -0
  132. package/ai/tools/apifyActorClient.ts +45 -0
  133. package/ai/tools/appEditGuard.ts +372 -0
  134. package/ai/tools/appReadSnapshot.ts +153 -0
  135. package/ai/tools/appTools.ts +1549 -0
  136. package/ai/tools/applyEditTool.ts +259 -0
  137. package/ai/tools/applyLineEditsTool.ts +315 -0
  138. package/ai/tools/browserTools/click.ts +33 -0
  139. package/ai/tools/browserTools/closeSession.ts +29 -0
  140. package/ai/tools/browserTools/common.ts +27 -0
  141. package/ai/tools/browserTools/openSession.ts +48 -0
  142. package/ai/tools/browserTools/readContent.ts +38 -0
  143. package/ai/tools/browserTools/selectOption.ts +46 -0
  144. package/ai/tools/browserTools/typeText.ts +42 -0
  145. package/ai/tools/category/createCategoryTool.ts +66 -0
  146. package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
  147. package/ai/tools/category/updateContentCategoryTool.ts +75 -0
  148. package/ai/tools/cfBrowserTools.ts +319 -0
  149. package/ai/tools/cfSpeechToTextTool.ts +49 -0
  150. package/ai/tools/checkEnvTool.ts +102 -0
  151. package/ai/tools/cloudflareCrawlTool.ts +289 -0
  152. package/ai/tools/codeSearchTool.ts +123 -0
  153. package/ai/tools/codeTools.ts +101 -0
  154. package/ai/tools/convertMarxistsBookTool.ts +103 -0
  155. package/ai/tools/createDocTool.ts +132 -0
  156. package/ai/tools/createSkillDocTool.ts +155 -0
  157. package/ai/tools/createWorkflowTool.ts +154 -0
  158. package/ai/tools/delayTool.ts +31 -0
  159. package/ai/tools/deleteSpacesTool.ts +325 -0
  160. package/ai/tools/deleteSpacesToolModel.ts +159 -0
  161. package/ai/tools/devReloadUtils.ts +29 -0
  162. package/ai/tools/dialogMessageSearch.ts +137 -0
  163. package/ai/tools/doctorSkillTool.ts +72 -0
  164. package/ai/tools/ecommerceScraperTool.ts +86 -0
  165. package/ai/tools/emailTools.ts +549 -0
  166. package/ai/tools/evalSkillTool.ts +92 -0
  167. package/ai/tools/exaSearchTool.ts +63 -0
  168. package/ai/tools/execShellTool.ts +266 -0
  169. package/ai/tools/executeSqlTool.ts +192 -0
  170. package/ai/tools/fetchWebpageSupport.ts +333 -0
  171. package/ai/tools/fetchWebpageTool.ts +97 -0
  172. package/ai/tools/geminiImagePreviewTool.ts +386 -0
  173. package/ai/tools/generateDocxTool.ts +215 -0
  174. package/ai/tools/googleSearchScraperTool.ts +106 -0
  175. package/ai/tools/importDataTool.ts +133 -0
  176. package/ai/tools/importSkillTool.ts +162 -0
  177. package/ai/tools/index.ts +2290 -0
  178. package/ai/tools/jdProductScraperTool.ts +821 -0
  179. package/ai/tools/listUserSpacesTool.ts +113 -0
  180. package/ai/tools/localFilesTool.ts +276 -0
  181. package/ai/tools/marxistsOfflineBook.ts +253 -0
  182. package/ai/tools/modelUsageTools.ts +206 -0
  183. package/ai/tools/noloWorkspaceReadTools.ts +467 -0
  184. package/ai/tools/olmOcrTool.ts +33 -0
  185. package/ai/tools/openaiImageTool.ts +267 -0
  186. package/ai/tools/prepareTools.ts +193 -0
  187. package/ai/tools/readDocTool.ts +88 -0
  188. package/ai/tools/readFileTool.ts +214 -0
  189. package/ai/tools/readTool.ts +194 -0
  190. package/ai/tools/readXPostTool.ts +229 -0
  191. package/ai/tools/readXhsProfileTool.ts +638 -0
  192. package/ai/tools/rememberMemoryTool.ts +84 -0
  193. package/ai/tools/remotionVideoTool.ts +151 -0
  194. package/ai/tools/searchDialogMessagesTool.ts +222 -0
  195. package/ai/tools/searchWorkspaceTool.ts +259 -0
  196. package/ai/tools/skillFollowup.ts +86 -0
  197. package/ai/tools/surfWeatherTool.ts +169 -0
  198. package/ai/tools/table/addTableRowTool.ts +217 -0
  199. package/ai/tools/table/createTableTool.ts +326 -0
  200. package/ai/tools/table/rowTools.ts +386 -0
  201. package/ai/tools/table/schemaTools.ts +244 -0
  202. package/ai/tools/table/shareTableTool.ts +148 -0
  203. package/ai/tools/table/toolShared.ts +129 -0
  204. package/ai/tools/taobaoTmallProductScraperTool.ts +49 -0
  205. package/ai/tools/toolApiClient.ts +279 -0
  206. package/ai/tools/toolPacks.ts +19 -0
  207. package/ai/tools/toolResultError.ts +42 -0
  208. package/ai/tools/toolRunSlice.ts +303 -0
  209. package/ai/tools/toolSchemaCompatibility.ts +53 -0
  210. package/ai/tools/uiAskChoiceTool.ts +104 -0
  211. package/ai/tools/updateContentTitleTool.ts +84 -0
  212. package/ai/tools/updateDocTool.ts +105 -0
  213. package/ai/tools/updateUserPreferenceProfileTool.ts +153 -0
  214. package/ai/tools/wereadGatewayTool.ts +152 -0
  215. package/ai/tools/whisperTool.ts +76 -0
  216. package/ai/tools/writeFileTool.ts +213 -0
  217. package/ai/tools/youtubeScraperTool.ts +116 -0
  218. package/ai/tools/ziweiChartTool.ts +678 -0
  219. package/ai/types.ts +58 -0
  220. package/ai/workflow/workflowExecutor.ts +323 -0
  221. package/ai/workflow/workflowSlice.ts +73 -0
  222. package/ai/workflow/workflowTypes.ts +106 -0
  223. package/app/actions/syncAppRecord.ts +73 -0
  224. package/app/constants/animationSets.ts +21 -0
  225. package/app/constants/appEditor.ts +99 -0
  226. package/app/favorite/deletedFavoriteProjection.ts +31 -0
  227. package/app/favorite/favoriteSlice.ts +690 -0
  228. package/app/favorite/type.ts +43 -0
  229. package/app/hooks/deleteDbKey.ts +254 -0
  230. package/app/i18n/client.ts +13 -0
  231. package/app/i18n/i18n.base.ts +14 -0
  232. package/app/i18n/i18n.config.ts +77 -0
  233. package/app/i18n/index.ts +15 -0
  234. package/app/i18n/mapLanguage.ts +11 -0
  235. package/app/i18n/translations/appBuilder.locale.ts +453 -0
  236. package/app/i18n/translations/error.locale.ts +246 -0
  237. package/app/i18n/translations/interface.locale.ts +2206 -0
  238. package/app/i18n/translations/pricing.locale.ts +397 -0
  239. package/app/i18n/translations/privacy.locale.ts +168 -0
  240. package/app/i18n/translations/seo.locale.ts +129 -0
  241. package/app/i18n/translations/terms.locale.ts +124 -0
  242. package/app/i18n/types.ts +6 -0
  243. package/app/notifications/model.ts +77 -0
  244. package/app/notifications/notificationSlice.ts +141 -0
  245. package/app/reducer.ts +36 -0
  246. package/app/settings/dbActionThunks.ts +34 -0
  247. package/app/settings/defaultSpacePreference.ts +87 -0
  248. package/app/settings/settingSlice.tsx +1212 -0
  249. package/app/settings/settingsRecord.ts +8 -0
  250. package/app/stateViews/runtime.ts +90 -0
  251. package/app/store.ts +55 -0
  252. package/app/theme/colors.ts +280 -0
  253. package/app/theme/fontPreference.ts +77 -0
  254. package/app/theme/theme.config.ts +120 -0
  255. package/app/theme/themeModeBootstrap.ts +123 -0
  256. package/app/types/appSummary.ts +118 -0
  257. package/app/types.ts +358 -0
  258. package/app/utils/appKeys.ts +55 -0
  259. package/app/utils/async.ts +28 -0
  260. package/app/utils/desktopAgentRuntimeTurnClient.ts +75 -0
  261. package/app/utils/env.ts +17 -0
  262. package/app/utils/fileUtils.ts +229 -0
  263. package/app/utils/imageUtils.ts +274 -0
  264. package/app/utils/myContentItems.ts +289 -0
  265. package/app/utils/retryAfter.ts +36 -0
  266. package/app/utils/retryFetch.ts +61 -0
  267. package/app/utils/toast.ts +3 -0
  268. package/auth/action/signUpAction.ts +227 -0
  269. package/auth/adminPermissions.ts +78 -0
  270. package/auth/authSlice.ts +531 -0
  271. package/auth/client/loginRequest.ts +14 -0
  272. package/auth/resetAuthScopedClientState.ts +27 -0
  273. package/auth/routes.ts +183 -0
  274. package/auth/token.ts +63 -0
  275. package/auth/types.ts +40 -0
  276. package/chat/chat.locale.ts +817 -0
  277. package/chat/dialog/actions/addCybotAction.ts +52 -0
  278. package/chat/dialog/actions/addReferenceKeysAction.ts +62 -0
  279. package/chat/dialog/actions/builtinDialogLlm.ts +35 -0
  280. package/chat/dialog/actions/cleanupCliSession.ts +40 -0
  281. package/chat/dialog/actions/createDialogAction.ts +379 -0
  282. package/chat/dialog/actions/createScheduledTaskAction.ts +78 -0
  283. package/chat/dialog/actions/handleSendMessageAction.ts +202 -0
  284. package/chat/dialog/actions/handleSendMessageResolver.ts +27 -0
  285. package/chat/dialog/actions/removeCybotAction.ts +6 -0
  286. package/chat/dialog/actions/removeDialogAgentAction.ts +44 -0
  287. package/chat/dialog/actions/replacePrimaryCybotAction.ts +6 -0
  288. package/chat/dialog/actions/setPrimaryDialogAgentAction.ts +52 -0
  289. package/chat/dialog/actions/updateDialogSummaryAction.ts +430 -0
  290. package/chat/dialog/actions/updateDialogTitleAction.ts +151 -0
  291. package/chat/dialog/actions/updateDialogTitlePolicy.ts +30 -0
  292. package/chat/dialog/actions/updateTokensAction.ts +233 -0
  293. package/chat/dialog/dialogAgents.ts +72 -0
  294. package/chat/dialog/dialogAttachmentCleanup.ts +135 -0
  295. package/chat/dialog/dialogSlice.ts +985 -0
  296. package/chat/dialog/dialogTitle.ts +81 -0
  297. package/chat/dialog/dialogTokenStats.ts +12 -0
  298. package/chat/dialog/dialogUrl.ts +6 -0
  299. package/chat/dialog/goal.ts +108 -0
  300. package/chat/dialog/objectAssistantRegistry.ts +286 -0
  301. package/chat/dialog/schedule.ts +17 -0
  302. package/chat/messages/activityCompletion.ts +97 -0
  303. package/chat/messages/fetchAndCacheMessages.ts +119 -0
  304. package/chat/messages/fetchConvMsgs.ts +51 -0
  305. package/chat/messages/fileUrl.ts +13 -0
  306. package/chat/messages/imagePayloadPersistence.ts +22 -0
  307. package/chat/messages/messageAgent.ts +8 -0
  308. package/chat/messages/messageContent.ts +203 -0
  309. package/chat/messages/messageContract.ts +88 -0
  310. package/chat/messages/messageSlice.ts +1386 -0
  311. package/chat/messages/toolThunks.ts +646 -0
  312. package/chat/messages/types.ts +8 -1
  313. package/chat/messages/web/toolDisplayName.ts +686 -0
  314. package/cli/agentAliases.ts +29 -9
  315. package/cli/agentInternalCommandEntries.ts +11 -3
  316. package/cli/agentMachineCommands.ts +1 -0
  317. package/cli/agentRecordCommands.ts +2 -2
  318. package/cli/agentRecordHelpers.ts +59 -6
  319. package/cli/agentRunCommand.ts +84 -19
  320. package/cli/client/agentRun.ts +92 -261
  321. package/cli/client/localRuntimeAdapter.ts +292 -50
  322. package/cli/commandRegistry.ts +7 -4
  323. package/cli/dialogAttachmentCleanup.ts +151 -0
  324. package/cli/dialogCommands.ts +163 -61
  325. package/cli/dialogInternalCommandEntries.ts +1 -1
  326. package/cli/docCreateCommands.ts +345 -0
  327. package/cli/docInternalCommandEntries.ts +11 -0
  328. package/cli/docPageHelpers.ts +80 -0
  329. package/cli/docSkillHelpers.ts +67 -0
  330. package/cli/docSpaceHelpers.ts +46 -0
  331. package/cli/internalCommandEntries.ts +4 -0
  332. package/cli/machineCommands.ts +18 -34
  333. package/cli/memoryCommands.ts +253 -0
  334. package/cli/memoryInternalCommandEntries.ts +9 -0
  335. package/cli/qoderUsageProbe.ts +252 -0
  336. package/cli/scriptCommandEntries.ts +0 -3
  337. package/cli/secretScan.ts +31 -0
  338. package/cli/tableCommands.ts +248 -13
  339. package/cli/workflowInternalCommandEntries.ts +2 -3
  340. package/client/agentRun.test.ts +119 -83
  341. package/client/agentRun.ts +92 -261
  342. package/client/localRuntimeAdapter.test.ts +894 -32
  343. package/client/localRuntimeAdapter.ts +292 -50
  344. package/commandRegistry.ts +7 -4
  345. package/connector-experimental/capabilities.ts +10 -9
  346. package/core/builtinAgents.ts +209 -0
  347. package/core/config.ts +15 -0
  348. package/core/crypto.ts +51 -0
  349. package/core/generateKeyPairFromSeedV1.ts +15 -0
  350. package/core/generateMainKey.ts +22 -0
  351. package/core/init.ts +41 -0
  352. package/core/localOrigins.ts +8 -0
  353. package/core/password.ts +13 -0
  354. package/core/prefix.ts +23 -0
  355. package/create/editor/transforms/fromMarkdown/index.ts +260 -0
  356. package/create/editor/transforms/fromMarkdown/inline.ts +285 -0
  357. package/create/editor/transforms/fromMarkdown/table.ts +130 -0
  358. package/create/editor/transforms/markdownToSlate.ts +24 -0
  359. package/create/editor/transforms/slateToRenderMarkdown.ts +218 -0
  360. package/create/editor/transforms/slateToSimplifiedMarkdown.ts +224 -0
  361. package/create/editor/transforms/slateToText.ts +33 -0
  362. package/create/editor/utils/slateUtils.ts +233 -0
  363. package/create/space/addSpaceAction.ts +193 -0
  364. package/create/space/category/categoryActions.ts +427 -0
  365. package/create/space/changeSpaceAction.ts +36 -0
  366. package/create/space/constants.ts +8 -0
  367. package/create/space/content/addContentAction.ts +116 -0
  368. package/create/space/content/contentThunks.ts +90 -0
  369. package/create/space/content/deleteContentFromSpaceAction.ts +187 -0
  370. package/create/space/content/deleteMultipleContentAction.ts +112 -0
  371. package/create/space/content/moveContentAction.ts +285 -0
  372. package/create/space/content/updateContentCategoryAction.ts +154 -0
  373. package/create/space/content/updateContentTitleAction.ts +151 -0
  374. package/create/space/content/uploadAndAddFileToSpaceAction.ts +98 -0
  375. package/create/space/contentKeyUtils.ts +117 -0
  376. package/create/space/deleteSpaceAction.ts +276 -0
  377. package/create/space/fetchSpaceAction.ts +70 -0
  378. package/create/space/fetchSpaceSidebarStateAction.ts +26 -0
  379. package/create/space/loadDefaultSpaceAction.ts +57 -0
  380. package/create/space/member/addMemberAction.ts +79 -0
  381. package/create/space/member/fetchUserSpaceMembershipsAction.ts +386 -0
  382. package/create/space/member/memberThunks.ts +47 -0
  383. package/create/space/member/removeMemberAction.ts +67 -0
  384. package/create/space/resolvePreferredSpaceId.ts +113 -0
  385. package/create/space/sidebarVisibleTypes.ts +260 -0
  386. package/create/space/space.locale.ts +1087 -0
  387. package/create/space/spaceAccess.ts +182 -0
  388. package/create/space/spaceCollapsedState.ts +54 -0
  389. package/create/space/spaceKeys.ts +65 -0
  390. package/create/space/spaceSlice.ts +328 -0
  391. package/create/space/spaceThunks.ts +410 -0
  392. package/create/space/types.ts +27 -0
  393. package/create/space/updateSpaceAction.ts +107 -0
  394. package/create/space/utils/permissions.ts +47 -0
  395. package/create/types.ts +21 -0
  396. package/database/actions/agentReadResolution.ts +33 -0
  397. package/database/actions/common.ts +243 -0
  398. package/database/actions/deleteFile.ts +40 -0
  399. package/database/actions/fileContent.ts +125 -0
  400. package/database/actions/patch.ts +155 -0
  401. package/database/actions/read.ts +358 -0
  402. package/database/actions/readAndWait.ts +260 -0
  403. package/database/actions/readRequestManager.ts +120 -0
  404. package/database/actions/readResolution.ts +125 -0
  405. package/database/actions/remove.ts +94 -0
  406. package/database/actions/replication.ts +477 -0
  407. package/database/actions/upload.ts +186 -0
  408. package/database/actions/upsert.ts +56 -0
  409. package/database/actions/write.ts +146 -0
  410. package/database/authority/ownerKey.ts +80 -0
  411. package/database/authority/recordAuthority.ts +67 -0
  412. package/database/authority/userAuthorityRegistry.ts +54 -0
  413. package/database/client/fetchUserData.ts +61 -0
  414. package/database/dbActionThunks.ts +1 -0
  415. package/database/dbSlice.ts +149 -0
  416. package/database/fileRing.ts +51 -0
  417. package/database/fileStorage.ts +232 -0
  418. package/database/fileUrl.ts +34 -0
  419. package/database/keys.ts +767 -0
  420. package/database/queryPrefixes.ts +14 -0
  421. package/database/requests.ts +443 -0
  422. package/database/runtimeServerContext.ts +54 -0
  423. package/database/tenantPlacement.ts +57 -0
  424. package/database/userPreferenceRegister.ts +131 -0
  425. package/database/utils/ulid.ts +1 -0
  426. package/dialogAttachmentCleanup.ts +151 -0
  427. package/dialogCommands.ts +163 -61
  428. package/dialogInternalCommandEntries.ts +1 -1
  429. package/docCreateCommands.ts +345 -0
  430. package/docInternalCommandEntries.ts +11 -0
  431. package/docPageHelpers.ts +80 -0
  432. package/docSkillHelpers.ts +67 -0
  433. package/docSpaceHelpers.ts +46 -0
  434. package/integrations/anthropic/anthropicModels.ts +47 -0
  435. package/integrations/deepseek/models.ts +37 -0
  436. package/integrations/google/models.ts +341 -0
  437. package/integrations/openai/chatCompletionStreamMode.ts +10 -0
  438. package/integrations/openai/filterAndCleanMessages.ts +284 -0
  439. package/integrations/openai/flexTier.ts +102 -0
  440. package/integrations/openai/generateOpenAIRequestBody.ts +271 -0
  441. package/integrations/openai/generateResponseRequestBody.ts +77 -0
  442. package/integrations/openai/models.ts +271 -0
  443. package/integrations/openai/providerBodyCompatibility.ts +23 -0
  444. package/integrations/openai/responsesHelpers.ts +297 -0
  445. package/integrations/x-reader/types.ts +109 -0
  446. package/integrations/xai/models.ts +13 -0
  447. package/integrations/xhs-reader/redaction.ts +68 -0
  448. package/integrations/xhs-reader/types.ts +277 -0
  449. package/integrations/xhs-reader/url.ts +80 -0
  450. package/internalCommandEntries.ts +4 -0
  451. package/machineCommands.ts +18 -34
  452. package/memoryCommands.ts +253 -0
  453. package/memoryInternalCommandEntries.ts +9 -0
  454. package/package.json +454 -9
  455. package/qoderUsageProbe.ts +252 -0
  456. package/render/contentIcon/types.ts +167 -0
  457. package/render/page/createPageAction.ts +183 -0
  458. package/render/page/docSlice.ts +495 -0
  459. package/render/page/types.ts +19 -0
  460. package/render/table/createTableAction.ts +274 -0
  461. package/render/table/deleteTableAction.ts +193 -0
  462. package/render/table/fetchAndCacheTableRows.ts +174 -0
  463. package/render/table/tableSlice.ts +1167 -0
  464. package/render/table/toolValueUtils.ts +363 -0
  465. package/render/table/types.ts +262 -0
  466. package/render/table/utils/tableSerialization.ts +50 -0
  467. package/scriptCommandEntries.ts +0 -3
  468. package/secretScan.ts +31 -0
  469. package/server/handlers/agentRun/types.ts +105 -0
  470. package/share/action.ts +225 -0
  471. package/share/helpers.ts +302 -0
  472. package/share/keys.ts +243 -0
  473. package/share/publicSharePolicy.ts +27 -0
  474. package/share/shareSlice.ts +53 -0
  475. package/share/types.ts +100 -0
  476. package/tableCommands.ts +248 -13
  477. package/workflowInternalCommandEntries.ts +2 -3
  478. package/ai/tools/agent/taskRunTool.ts +0 -112
  479. package/cli/client/taskRunPrompt.ts +0 -27
  480. package/cli/taskRunCommand.ts +0 -265
  481. package/client/taskRunPrompt.ts +0 -27
  482. package/taskRunCommand.ts +0 -265
@@ -0,0 +1,985 @@
1
+ // 文件路径: chat/dialog/dialogSlice.ts
2
+
3
+ import {
4
+ type PayloadAction,
5
+ asyncThunkCreator,
6
+ buildCreateSlice,
7
+ createSelector,
8
+ } from "@reduxjs/toolkit";
9
+ import type { RootState } from "../../app/store";
10
+ import { getRuntimeServerContext } from "../../database/runtimeServerContext";
11
+ import type { Descendant } from "slate";
12
+ import { resetMsgs, clearAllStreaming } from "../messages/messageSlice";
13
+ import { extractCustomId } from "../../core/prefix";
14
+ import { patch, read, remove, selectById } from "../../database/dbSlice";
15
+
16
+ import type { DialogConfig, DialogGoalState } from "../../app/types";
17
+ import { clearPlan } from "../../ai/agent/planSlice";
18
+ import { clearWorkflow } from "../../ai/workflow/workflowSlice";
19
+
20
+ import { scheduleDeleteReplication } from "../../database/actions/replication";
21
+ import {
22
+ buildDialogAttachmentPlan,
23
+ extractFileContentIds,
24
+ type DialogAttachmentMessage,
25
+ } from "./dialogAttachmentCleanup";
26
+
27
+ // 外部 Actions
28
+ import { updateTokensAction } from "./actions/updateTokensAction";
29
+ import { cleanupCliSessionForDialog } from "./actions/cleanupCliSession";
30
+
31
+ import { createKey } from "../../database/keys";
32
+ import { mergeDialogTokenStats } from "./dialogTokenStats";
33
+ import { getDialogAgentIds, getPrimaryDialogAgentId } from "./dialogAgents";
34
+ import { buildDialogGoal, getDialogGoalReport } from "./goal";
35
+
36
+ const collectKeys = async (prefix: string, db: any): Promise<string[]> => {
37
+ const keys: string[] = [];
38
+ let iterator = db.iterator({
39
+ gte: prefix,
40
+ lte: prefix + "\uffff",
41
+ });
42
+
43
+ if (iterator && typeof iterator.then === 'function') {
44
+ iterator = await iterator;
45
+ }
46
+
47
+ for await (const [key] of iterator) {
48
+ keys.push(key as string);
49
+ }
50
+
51
+ return keys;
52
+ };
53
+
54
+ const collectEntries = async (prefix: string, db: any): Promise<Array<[string, any]>> => {
55
+ const entries: Array<[string, any]> = [];
56
+ let iterator = db.iterator({
57
+ gte: prefix,
58
+ lte: prefix + "\uffff",
59
+ });
60
+
61
+ if (iterator && typeof iterator.then === "function") {
62
+ iterator = await iterator;
63
+ }
64
+
65
+ for await (const [key, value] of iterator) {
66
+ entries.push([key as string, value]);
67
+ }
68
+
69
+ return entries;
70
+ };
71
+
72
+ const dbGetOrNull = async (db: any, key: string) => {
73
+ if (!db || typeof db.get !== "function") return null;
74
+ try {
75
+ return await db.get(key);
76
+ } catch {
77
+ return null;
78
+ }
79
+ };
80
+
81
+ const readLocalFileMetadata = async (db: any, fileId: string) => {
82
+ const direct = await dbGetOrNull(db, fileId);
83
+ if (direct) return direct;
84
+ const index = await dbGetOrNull(db, createKey("file", "id", fileId));
85
+ const mainKey =
86
+ typeof index?.mainKey === "string" && index.mainKey.trim()
87
+ ? index.mainKey.trim()
88
+ : null;
89
+ return mainKey ? await dbGetOrNull(db, mainKey) : null;
90
+ };
91
+
92
+ type DeleteDialogPayload =
93
+ | string
94
+ | {
95
+ dialogKey: string;
96
+ includeAttachments?: boolean;
97
+ };
98
+
99
+ const normalizeDeleteDialogPayload = (payload: DeleteDialogPayload) =>
100
+ typeof payload === "string"
101
+ ? { dialogKey: payload, includeAttachments: false }
102
+ : {
103
+ dialogKey: payload.dialogKey,
104
+ includeAttachments: payload.includeAttachments === true,
105
+ };
106
+
107
+ const deleteOwnedDialogAttachments = async (args: {
108
+ db: any;
109
+ dialogId: string;
110
+ entries: Array<[string, any]>;
111
+ thunkApi: any;
112
+ }) => {
113
+ const messages: DialogAttachmentMessage[] = args.entries.map(([dbKey, value]) => ({
114
+ ...(value && typeof value === "object" ? value : {}),
115
+ dbKey,
116
+ }));
117
+ const fileIds = [...new Set(messages.flatMap((message) => extractFileContentIds(message)))];
118
+ const metadataByFileId: Record<string, any> = {};
119
+ const metadataReadFailures: Array<{ fileId: string; error: string }> = [];
120
+
121
+ for (const fileId of fileIds) {
122
+ const metadata = await readLocalFileMetadata(args.db, fileId);
123
+ if (metadata) {
124
+ metadataByFileId[fileId] = metadata;
125
+ } else {
126
+ metadataReadFailures.push({ fileId, error: "local file metadata not found" });
127
+ }
128
+ }
129
+
130
+ const plan = buildDialogAttachmentPlan({
131
+ dialogId: args.dialogId,
132
+ messages,
133
+ metadataByFileId,
134
+ metadataReadFailures,
135
+ });
136
+ if (!plan.deleteCandidates.length) return plan;
137
+
138
+ const { deleteFileAction } = await import("../../database/actions/deleteFile");
139
+ for (const candidate of plan.deleteCandidates) {
140
+ if (candidate.fileDbKey) {
141
+ await deleteFileAction(candidate.fileDbKey, args.thunkApi);
142
+ }
143
+ }
144
+ return plan;
145
+ };
146
+
147
+ const createSliceWithThunks = buildCreateSlice({
148
+ creators: { asyncThunk: asyncThunkCreator },
149
+ });
150
+
151
+ const runCreateDialogAction = async (args: any, thunkApi: any) => {
152
+ const { createDialogAction } = await import("./actions/createDialogAction");
153
+ return createDialogAction(args, thunkApi);
154
+ };
155
+
156
+ const runCreateScheduledTaskAction = async (args: any, thunkApi: any) => {
157
+ const { createScheduledTaskAction } = await import("./actions/createScheduledTaskAction");
158
+ return createScheduledTaskAction(args, thunkApi);
159
+ };
160
+
161
+ const runUpdateDialogTitleAction = async (args: any, thunkApi: any) => {
162
+ const { updateDialogTitleAction } = await import("./actions/updateDialogTitleAction");
163
+ return updateDialogTitleAction(args, thunkApi);
164
+ };
165
+
166
+ const runAddCybotAction = async (args: any, thunkApi: any) => {
167
+ const { addCybotAction } = await import("./actions/addCybotAction");
168
+ return addCybotAction(args, thunkApi);
169
+ };
170
+
171
+ const runRemoveCybotAction = async (args: any, thunkApi: any) => {
172
+ const { removeCybotAction } = await import("./actions/removeCybotAction");
173
+ return removeCybotAction(args, thunkApi);
174
+ };
175
+
176
+ const runReplacePrimaryCybotAction = async (args: any, thunkApi: any) => {
177
+ const { replacePrimaryCybotAction } = await import("./actions/replacePrimaryCybotAction");
178
+ return replacePrimaryCybotAction(args, thunkApi);
179
+ };
180
+
181
+ const runRemoveDialogAgentAction = async (args: any, thunkApi: any) => {
182
+ const { removeDialogAgentAction } = await import("./actions/removeDialogAgentAction");
183
+ return removeDialogAgentAction(args, thunkApi);
184
+ };
185
+
186
+ const runSetPrimaryDialogAgentAction = async (args: any, thunkApi: any) => {
187
+ const { setPrimaryDialogAgentAction } = await import("./actions/setPrimaryDialogAgentAction");
188
+ return setPrimaryDialogAgentAction(args, thunkApi);
189
+ };
190
+
191
+ const runHandleSendMessageAction = async (args: any, thunkApi: any) => {
192
+ const { handleSendMessageAction } = await import("./actions/handleSendMessageAction");
193
+ return handleSendMessageAction(args, thunkApi);
194
+ };
195
+
196
+ // --- Interfaces ---
197
+
198
+ export interface PendingFile {
199
+ id: string;
200
+ name: string;
201
+ /** Source content key included in the message attachment. */
202
+ pageKey?: string;
203
+ /** Source dialog key included in the message attachment. Prefer sourceDialogKey in new code. */
204
+ dialogKey?: string;
205
+ sourceDialogKey?: string;
206
+ /** Target dialog runtime that should receive this pending attachment. */
207
+ targetDialogKey?: string;
208
+ /** @deprecated Use targetDialogKey. Kept for older pending attachment payloads. */
209
+ runtimeDialogKey?: string;
210
+ type:
211
+ | "excel"
212
+ | "docx"
213
+ | "pdf"
214
+ | "page"
215
+ | "txt"
216
+ | "dialog"
217
+ | "table"
218
+ | "image"
219
+ | "file"
220
+ | "agent"
221
+ | "cybot"
222
+ | "app"
223
+ | "ocr_text";
224
+ groupId?: string;
225
+ ocrText?: string; // ← 新增:OCR 识别结果
226
+ }
227
+
228
+ export interface CreatePagePayload {
229
+ slateData: Descendant[];
230
+ jsonData?: Record<string, any>[];
231
+ title: string;
232
+ type: "excel" | "docx" | "pdf" | "txt" | "table";
233
+ fileId: string;
234
+ size: number;
235
+ groupId?: string;
236
+ dialogKey?: string;
237
+ }
238
+
239
+ export interface PendingRawData {
240
+ pageKey: string;
241
+ jsonData: Record<string, any>[];
242
+ }
243
+
244
+ export interface TokenStats {
245
+ inputTokens: number;
246
+ outputTokens: number;
247
+ totalCost: number;
248
+ }
249
+
250
+ type LiveTokenUsagePayload = {
251
+ input_tokens: number;
252
+ output_tokens: number;
253
+ cost?: number;
254
+ dialogKey?: string;
255
+ };
256
+
257
+ type CreateDialogGoalPayload = {
258
+ objective: string;
259
+ tokenBudget?: number;
260
+ dialogKey?: string;
261
+ now?: number;
262
+ };
263
+
264
+ type CompleteDialogGoalPayload = {
265
+ dialogKey?: string;
266
+ now?: number;
267
+ };
268
+
269
+ export type LoopStopReason =
270
+ | "done" // 模型主动结束,无工具调用
271
+ | "handoff" // 移交给子 Agent
272
+ | "pending" // 等待用户确认
273
+ | "timeout" // 超时
274
+ | "error"; // 异常
275
+
276
+ interface DialogState {
277
+ currentDialogKey: string | null;
278
+ /**
279
+ * 多对话运行态桶:
280
+ * - 现阶段先服务“网页端切换对话不停止”
281
+ * - token / controller / queue /附件等按 dialogKey 隔离
282
+ * - 未来桌面端若支持多窗口/多 tab,还需要补跨窗口 stop 语义与同步策略
283
+ */
284
+ dialogRuntimeByKey: Record<string, DialogRuntimeState>;
285
+ isUpdatingMode: boolean;
286
+ }
287
+
288
+ interface DialogRuntimeState {
289
+ tokens: TokenStats;
290
+ goal?: DialogGoalState;
291
+ pendingFiles: PendingFile[];
292
+ activeControllers: Record<string, AbortController>;
293
+ pendingRawData: Record<string, PendingRawData>;
294
+ loopStopReason: LoopStopReason | null;
295
+ /** 用户在 agent loop 运行期间发送的消息队列,loop 每轮结束后依次注入 */
296
+ pendingUserInputQueue: string[];
297
+ }
298
+
299
+ // --- Initial State ---
300
+
301
+ const GLOBAL_DIALOG_RUNTIME_KEY = "__global__";
302
+
303
+ const createEmptyTokenStats = (): TokenStats => ({
304
+ inputTokens: 0,
305
+ outputTokens: 0,
306
+ totalCost: 0,
307
+ });
308
+
309
+ const createEmptyDialogRuntimeState = (): DialogRuntimeState => ({
310
+ tokens: createEmptyTokenStats(),
311
+ pendingFiles: [],
312
+ activeControllers: {},
313
+ pendingRawData: {},
314
+ loopStopReason: null,
315
+ pendingUserInputQueue: [],
316
+ });
317
+
318
+ const resetDialogRuntimeSessionState = (runtime: DialogRuntimeState) => {
319
+ runtime.tokens = createEmptyTokenStats();
320
+ runtime.loopStopReason = null;
321
+ };
322
+
323
+ const resolveDialogRuntimeKey = (
324
+ state: Pick<DialogState, "currentDialogKey">,
325
+ dialogKey?: string | null
326
+ ) => dialogKey ?? state.currentDialogKey ?? GLOBAL_DIALOG_RUNTIME_KEY;
327
+
328
+ const ensureDialogRuntimeState = (
329
+ state: DialogState,
330
+ dialogKey?: string | null
331
+ ): DialogRuntimeState => {
332
+ const runtimeKey = resolveDialogRuntimeKey(state, dialogKey);
333
+ if (!state.dialogRuntimeByKey[runtimeKey]) {
334
+ state.dialogRuntimeByKey[runtimeKey] = createEmptyDialogRuntimeState();
335
+ }
336
+ return state.dialogRuntimeByKey[runtimeKey];
337
+ };
338
+
339
+ const getDialogRuntimeState = (
340
+ state: DialogState,
341
+ dialogKey?: string | null
342
+ ): DialogRuntimeState =>
343
+ state.dialogRuntimeByKey[resolveDialogRuntimeKey(state, dialogKey)] ??
344
+ createEmptyDialogRuntimeState();
345
+
346
+ const initialState: DialogState = {
347
+ currentDialogKey: null,
348
+ dialogRuntimeByKey: {
349
+ [GLOBAL_DIALOG_RUNTIME_KEY]: createEmptyDialogRuntimeState(),
350
+ },
351
+ isUpdatingMode: false,
352
+ };
353
+
354
+ // --- Slice Definition ---
355
+
356
+ const dialogSlice = createSliceWithThunks({
357
+ name: "dialog",
358
+ initialState,
359
+ reducers: (create) => ({
360
+ // --- Thunks ---
361
+ createPageAndAddReference: create.asyncThunk(
362
+ async (payload: CreatePagePayload, { dispatch, rejectWithValue }) => {
363
+ const { slateData, jsonData, title, type, fileId, groupId, dialogKey } = payload;
364
+ try {
365
+ const { createDoc } = await import("../../render/page/docSlice");
366
+ const pageKey = await (dispatch as any)(
367
+ createDoc({ slateData, title })
368
+ ).unwrap();
369
+
370
+ const newReference: PendingFile = {
371
+ id: fileId,
372
+ name: title,
373
+ pageKey,
374
+ dialogKey,
375
+ type,
376
+ groupId,
377
+ };
378
+ const newRawData = jsonData ? { pageKey, jsonData } : null;
379
+
380
+ return { reference: newReference, rawData: newRawData, dialogKey };
381
+ } catch (error) {
382
+ console.error("创建页面或引用失败:", error);
383
+ return rejectWithValue((error as Error).message);
384
+ }
385
+ },
386
+ {
387
+ fulfilled: (state, action) => {
388
+ const runtime = ensureDialogRuntimeState(
389
+ state,
390
+ action.payload.dialogKey ?? action.meta.arg.dialogKey
391
+ );
392
+ runtime.pendingFiles.push(action.payload.reference);
393
+ if (action.payload.rawData && action.payload.rawData.pageKey) {
394
+ runtime.pendingRawData[action.payload.rawData.pageKey] =
395
+ action.payload.rawData;
396
+ }
397
+ },
398
+ }
399
+ ),
400
+
401
+ deleteDialog: create.asyncThunk(
402
+ async (payload: DeleteDialogPayload, thunkApi) => {
403
+ const { dialogKey, includeAttachments } = normalizeDeleteDialogPayload(payload);
404
+ const { dispatch, getState, extra } = thunkApi;
405
+ const { db } = extra;
406
+ const state = getState() as RootState;
407
+ const { currentServer, syncServers } = getRuntimeServerContext(state);
408
+ const currentDialogKey = state.dialog.currentDialogKey;
409
+ const currentDialogId = currentDialogKey
410
+ ? extractCustomId(currentDialogKey)
411
+ : null;
412
+ const targetDialogId = extractCustomId(dialogKey);
413
+ const targetDialogConfig = selectById(state, dialogKey) as DialogConfig | null;
414
+
415
+ const isCurrentDialog =
416
+ currentDialogId !== null && currentDialogId === targetDialogId;
417
+ await cleanupCliSessionForDialog({ dispatch, getState }, targetDialogConfig);
418
+ // --- 无论是否是当前对话,都从当前空间删除该内容 ---
419
+ await (dispatch as any)(remove(dialogKey));
420
+ const prefix = createKey("dialog", targetDialogId, "msg");
421
+ const deletedEntries = includeAttachments
422
+ ? await collectEntries(prefix, db)
423
+ : [];
424
+ const attachmentPlan =
425
+ includeAttachments && targetDialogId
426
+ ? await deleteOwnedDialogAttachments({
427
+ db,
428
+ dialogId: targetDialogId,
429
+ entries: deletedEntries,
430
+ thunkApi,
431
+ })
432
+ : null;
433
+ const deletedIds = includeAttachments
434
+ ? deletedEntries.map(([key]) => key)
435
+ : await collectKeys(prefix, db);
436
+ if (!deletedIds.length) return { dialogKey, isCurrentDialog, attachmentPlan };
437
+
438
+ const ops = deletedIds.map((key) => ({ type: "del" as const, key }));
439
+
440
+ await db.batch(ops);
441
+
442
+ scheduleDeleteReplication({
443
+ currentServer,
444
+ syncServers,
445
+ dbKey: targetDialogId,
446
+ deleteOptions: { type: "messages" },
447
+ state,
448
+ });
449
+ // --- 如果是当前对话,清理当前相关状态 ---
450
+ if (isCurrentDialog) {
451
+ await thunkApi.dispatch(resetMsgs());
452
+ dispatch(dialogSlice.actions.clearPendingAttachments());
453
+ dispatch(clearPlan());
454
+ dispatch(clearWorkflow());
455
+ }
456
+
457
+ return { dialogKey, isCurrentDialog, attachmentPlan };
458
+ },
459
+ {
460
+ fulfilled: (state, action) => {
461
+ delete state.dialogRuntimeByKey[action.payload.dialogKey];
462
+ if (action.payload.isCurrentDialog) {
463
+ state.currentDialogKey = null;
464
+ }
465
+ },
466
+ }
467
+ ),
468
+
469
+ initDialog: create.asyncThunk(
470
+ async (id: string, { dispatch, signal, getState }) => {
471
+ dispatch(dialogSlice.actions.clearPendingAttachments());
472
+ dispatch(clearPlan());
473
+ dispatch(clearWorkflow());
474
+ const { currentServer: preferredServerOrigin } = getRuntimeServerContext(
475
+ getState() as RootState
476
+ );
477
+ return await (dispatch as any)(
478
+ read({
479
+ dbKey: id,
480
+ signal,
481
+ preferredServerOrigin,
482
+ })
483
+ ).unwrap();
484
+ },
485
+ {
486
+ pending: (state, action) => {
487
+ state.currentDialogKey = action.meta.arg;
488
+ const runtime = ensureDialogRuntimeState(state, action.meta.arg);
489
+ resetDialogRuntimeSessionState(runtime);
490
+ },
491
+ fulfilled: (state, action) => {
492
+ if (state.currentDialogKey === action.meta.arg) {
493
+ // No-op
494
+ }
495
+ },
496
+ rejected: (state, action) => {
497
+ const isAborted =
498
+ action.error.name === "AbortError" ||
499
+ action.error.message === "Aborted";
500
+ const isCurrentDialog = state.currentDialogKey === action.meta.arg;
501
+
502
+ if (!isAborted && isCurrentDialog) {
503
+ // Log the error but keep currentDialogKey set — the dialog key is
504
+ // valid (it came from the space content list), we just couldn't load
505
+ // the config doc (e.g. not synced to server yet or network error).
506
+ // Keeping the key allows MessageInput to send and MessageList to
507
+ // display messages independently.
508
+ console.info("Failed to load dialog config:", action.error.message);
509
+ }
510
+ },
511
+ }
512
+ ),
513
+
514
+ handleSendMessage: create.asyncThunk(runHandleSendMessageAction),
515
+
516
+ abortAllMessages: create.asyncThunk(
517
+ async (
518
+ args: { dialogKey?: string; all?: boolean } | undefined,
519
+ { getState, dispatch }
520
+ ) => {
521
+ /**
522
+ * 产品约束说明:
523
+ * - 当前网页端 stop 默认只停“当前对话”,避免切换对话时把后台任务一起杀掉
524
+ * - `all: true` 仅用于 logout / 全局 reset 这类明确的系统级清理
525
+ * - 未来桌面端若要支持“从任务中心停任意 dialog”,应在 UI 层显式传 dialogKey
526
+ */
527
+ const dialogState = (getState() as RootState).dialog;
528
+ const runtimeStates = args?.all
529
+ ? Object.values(dialogState.dialogRuntimeByKey)
530
+ : [getDialogRuntimeState(dialogState, args?.dialogKey)];
531
+
532
+ runtimeStates.forEach((runtimeState) => {
533
+ Object.values(runtimeState.activeControllers).forEach((controller) =>
534
+ controller.abort()
535
+ );
536
+ });
537
+ dispatch(clearAllStreaming(args));
538
+ dispatch(dialogSlice.actions.clearActiveControllers(args));
539
+ }
540
+ ),
541
+
542
+ // Passthrough thunks for external actions
543
+ updateTokens: create.asyncThunk(updateTokensAction, {
544
+ fulfilled: (state, action) => {
545
+ const dialogKey = action.meta.arg.dialogKey;
546
+ if (!dialogKey) return;
547
+
548
+ const runtime = state.dialogRuntimeByKey[dialogKey];
549
+ if (!runtime) return;
550
+
551
+ runtime.tokens.inputTokens = Math.max(
552
+ 0,
553
+ runtime.tokens.inputTokens - (action.payload.input_tokens ?? 0)
554
+ );
555
+ runtime.tokens.outputTokens = Math.max(
556
+ 0,
557
+ runtime.tokens.outputTokens - (action.payload.output_tokens ?? 0)
558
+ );
559
+ runtime.tokens.totalCost = Math.max(
560
+ 0,
561
+ runtime.tokens.totalCost - (action.payload.cost ?? 0)
562
+ );
563
+ },
564
+ }),
565
+ saveDialogGoal: create.asyncThunk(
566
+ async (
567
+ payload: CreateDialogGoalPayload,
568
+ { dispatch, getState }
569
+ ) => {
570
+ const state = getState() as RootState;
571
+ const dialogKey = payload.dialogKey ?? state.dialog.currentDialogKey;
572
+ if (!dialogKey) {
573
+ throw new Error("Cannot save dialog goal without a dialog key.");
574
+ }
575
+
576
+ const goal = buildDialogGoal(payload);
577
+ await (dispatch as any)(
578
+ patch({
579
+ dbKey: dialogKey,
580
+ changes: { goal },
581
+ })
582
+ ).unwrap();
583
+
584
+ return { dialogKey, goal };
585
+ },
586
+ {
587
+ fulfilled: (state, action) => {
588
+ const runtime = ensureDialogRuntimeState(state, action.payload.dialogKey);
589
+ runtime.goal = action.payload.goal;
590
+ },
591
+ }
592
+ ),
593
+ saveCompletedDialogGoal: create.asyncThunk(
594
+ async (
595
+ payload: CompleteDialogGoalPayload | undefined,
596
+ { dispatch, getState }
597
+ ) => {
598
+ const state = getState() as RootState;
599
+ const dialogKey = payload?.dialogKey ?? state.dialog.currentDialogKey;
600
+ if (!dialogKey) {
601
+ throw new Error("Cannot complete dialog goal without a dialog key.");
602
+ }
603
+
604
+ const runtimeGoal =
605
+ state.dialog.dialogRuntimeByKey[dialogKey]?.goal ?? null;
606
+ const persistedDialog = selectById(state, dialogKey) as DialogConfig | null;
607
+ const goal = runtimeGoal ?? persistedDialog?.goal ?? null;
608
+ if (!goal) {
609
+ throw new Error("Cannot complete dialog goal before one is created.");
610
+ }
611
+
612
+ const completedGoal: DialogGoalState = {
613
+ ...goal,
614
+ status: "complete",
615
+ completedAt: payload?.now ?? Date.now(),
616
+ };
617
+ await (dispatch as any)(
618
+ patch({
619
+ dbKey: dialogKey,
620
+ changes: { goal: completedGoal },
621
+ })
622
+ ).unwrap();
623
+
624
+ return { dialogKey, goal: completedGoal };
625
+ },
626
+ {
627
+ fulfilled: (state, action) => {
628
+ const runtime = ensureDialogRuntimeState(state, action.payload.dialogKey);
629
+ runtime.goal = action.payload.goal;
630
+ },
631
+ }
632
+ ),
633
+ createDialog: create.asyncThunk(runCreateDialogAction),
634
+ createScheduledTask: create.asyncThunk(runCreateScheduledTaskAction),
635
+ updateDialogTitle: create.asyncThunk(runUpdateDialogTitleAction),
636
+ addCybot: create.asyncThunk(runAddCybotAction),
637
+ removeCybot: create.asyncThunk(runRemoveCybotAction),
638
+ replacePrimaryCybot: create.asyncThunk(runReplacePrimaryCybotAction),
639
+ addDialogAgent: create.asyncThunk(runAddCybotAction),
640
+ removeDialogAgent: create.asyncThunk(runRemoveDialogAgentAction),
641
+ setPrimaryDialogAgent: create.asyncThunk(runSetPrimaryDialogAgentAction),
642
+
643
+ // --- Reducers ---
644
+ addPendingFile: create.reducer(
645
+ (state, action: PayloadAction<PendingFile>) => {
646
+ const targetRuntimeKey =
647
+ action.payload.targetDialogKey ??
648
+ action.payload.runtimeDialogKey ??
649
+ (action.payload.type === "dialog" ? state.currentDialogKey : action.payload.dialogKey);
650
+ const runtime = ensureDialogRuntimeState(state, targetRuntimeKey);
651
+ if (!runtime.pendingFiles.some((f) => f.id === action.payload.id)) {
652
+ runtime.pendingFiles.push(action.payload);
653
+ }
654
+ }
655
+ ),
656
+
657
+ removePendingFile: create.reducer(
658
+ (state, action: PayloadAction<string>) => {
659
+ const runtime = ensureDialogRuntimeState(state);
660
+ const fileToRemove = runtime.pendingFiles.find(
661
+ (f) => f.id === action.payload
662
+ );
663
+ if (fileToRemove) {
664
+ if (fileToRemove.pageKey) {
665
+ delete runtime.pendingRawData[fileToRemove.pageKey];
666
+ }
667
+ runtime.pendingFiles = runtime.pendingFiles.filter(
668
+ (file) => file.id !== action.payload
669
+ );
670
+ }
671
+ }
672
+ ),
673
+
674
+ clearPendingAttachments: create.reducer(
675
+ (state, action: PayloadAction<{ dialogKey?: string; all?: boolean } | undefined>) => {
676
+ if (action.payload?.all) {
677
+ Object.values(state.dialogRuntimeByKey).forEach((runtime) => {
678
+ runtime.pendingFiles = [];
679
+ runtime.pendingRawData = {};
680
+ });
681
+ return;
682
+ }
683
+ const runtime = ensureDialogRuntimeState(state, action.payload?.dialogKey);
684
+ runtime.pendingFiles = [];
685
+ runtime.pendingRawData = {};
686
+ }
687
+ ),
688
+
689
+ setLoopStopReason: create.reducer(
690
+ (
691
+ state,
692
+ action: PayloadAction<{ reason: LoopStopReason | null; dialogKey?: string }>
693
+ ) => {
694
+ const runtime = ensureDialogRuntimeState(state, action.payload.dialogKey);
695
+ runtime.loopStopReason = action.payload.reason;
696
+ }
697
+ ),
698
+
699
+ clearDialogRuntimeState: create.reducer(
700
+ (state, action: PayloadAction<{ dialogKey: string }>) => {
701
+ delete state.dialogRuntimeByKey[action.payload.dialogKey];
702
+ }
703
+ ),
704
+
705
+ createDialogGoal: create.reducer(
706
+ (state, action: PayloadAction<CreateDialogGoalPayload>) => {
707
+ const objective = action.payload.objective.trim();
708
+ if (!objective) return;
709
+ const runtime = ensureDialogRuntimeState(state, action.payload.dialogKey);
710
+ const tokenBudget =
711
+ typeof action.payload.tokenBudget === "number" &&
712
+ Number.isFinite(action.payload.tokenBudget) &&
713
+ action.payload.tokenBudget > 0
714
+ ? Math.floor(action.payload.tokenBudget)
715
+ : undefined;
716
+ runtime.goal = {
717
+ objective,
718
+ status: "active",
719
+ ...(tokenBudget ? { tokenBudget } : {}),
720
+ createdAt: action.payload.now ?? Date.now(),
721
+ };
722
+ }
723
+ ),
724
+
725
+ completeDialogGoal: create.reducer(
726
+ (state, action: PayloadAction<CompleteDialogGoalPayload | undefined>) => {
727
+ const runtime = ensureDialogRuntimeState(state, action.payload?.dialogKey);
728
+ if (!runtime.goal) return;
729
+ runtime.goal = {
730
+ ...runtime.goal,
731
+ status: "complete",
732
+ completedAt: action.payload?.now ?? Date.now(),
733
+ };
734
+ }
735
+ ),
736
+
737
+ addActiveController: create.reducer(
738
+ (
739
+ state,
740
+ action: PayloadAction<{
741
+ messageId: string;
742
+ controller: AbortController;
743
+ dialogKey?: string;
744
+ }>
745
+ ) => {
746
+ const runtime = ensureDialogRuntimeState(state, action.payload.dialogKey);
747
+ runtime.activeControllers[action.payload.messageId] =
748
+ action.payload.controller;
749
+ }
750
+ ),
751
+
752
+ removeActiveController: create.reducer(
753
+ (
754
+ state,
755
+ action: PayloadAction<{ messageId: string; dialogKey?: string } | string>
756
+ ) => {
757
+ const payload =
758
+ typeof action.payload === "string"
759
+ ? { messageId: action.payload }
760
+ : action.payload;
761
+ const runtime = ensureDialogRuntimeState(state, payload.dialogKey);
762
+ delete runtime.activeControllers[payload.messageId];
763
+ }
764
+ ),
765
+
766
+ clearActiveControllers: create.reducer(
767
+ (state, action: PayloadAction<{ dialogKey?: string; all?: boolean } | undefined>) => {
768
+ if (action.payload?.all) {
769
+ Object.values(state.dialogRuntimeByKey).forEach((runtime) => {
770
+ runtime.activeControllers = {};
771
+ });
772
+ return;
773
+ }
774
+ const runtime = ensureDialogRuntimeState(state, action.payload?.dialogKey);
775
+ runtime.activeControllers = {};
776
+ }
777
+ ),
778
+
779
+ enqueueUserInput: create.reducer(
780
+ (state, action: PayloadAction<string | { text: string; dialogKey?: string }>) => {
781
+ const payload =
782
+ typeof action.payload === "string"
783
+ ? { text: action.payload }
784
+ : action.payload;
785
+ const runtime = ensureDialogRuntimeState(state, payload.dialogKey);
786
+ runtime.pendingUserInputQueue.push(payload.text);
787
+ }
788
+ ),
789
+
790
+ dequeueUserInput: create.reducer(
791
+ (state, action: PayloadAction<{ dialogKey?: string } | undefined>) => {
792
+ const runtime = ensureDialogRuntimeState(state, action.payload?.dialogKey);
793
+ runtime.pendingUserInputQueue.shift();
794
+ }
795
+ ),
796
+
797
+ clearPendingUserInputQueue: create.reducer(
798
+ (state, action: PayloadAction<{ dialogKey?: string; all?: boolean } | undefined>) => {
799
+ if (action.payload?.all) {
800
+ Object.values(state.dialogRuntimeByKey).forEach((runtime) => {
801
+ runtime.pendingUserInputQueue = [];
802
+ });
803
+ return;
804
+ }
805
+ const runtime = ensureDialogRuntimeState(state, action.payload?.dialogKey);
806
+ runtime.pendingUserInputQueue = [];
807
+ }
808
+ ),
809
+
810
+ tokenUsageLiveUpdate: create.reducer(
811
+ (
812
+ state,
813
+ action: PayloadAction<LiveTokenUsagePayload>
814
+ ) => {
815
+ const runtime = ensureDialogRuntimeState(state, action.payload.dialogKey);
816
+ runtime.tokens.inputTokens += action.payload.input_tokens;
817
+ runtime.tokens.outputTokens += action.payload.output_tokens;
818
+ runtime.tokens.totalCost += action.payload.cost ?? 0;
819
+ }
820
+ ),
821
+
822
+ clearDialogState: create.reducer((state) => {
823
+ const previousDialogKey = state.currentDialogKey;
824
+ const previousRuntime = previousDialogKey
825
+ ? state.dialogRuntimeByKey[previousDialogKey]
826
+ : null;
827
+ const globalRuntime = ensureDialogRuntimeState(state, GLOBAL_DIALOG_RUNTIME_KEY);
828
+
829
+ if (previousRuntime) {
830
+ if (previousRuntime.pendingFiles.length > 0) {
831
+ globalRuntime.pendingFiles = previousRuntime.pendingFiles;
832
+ previousRuntime.pendingFiles = [];
833
+ }
834
+ previousRuntime.pendingRawData = {};
835
+ previousRuntime.pendingUserInputQueue = [];
836
+ }
837
+ state.currentDialogKey = null;
838
+ globalRuntime.pendingRawData = {};
839
+ globalRuntime.pendingUserInputQueue = [];
840
+ }),
841
+ }),
842
+ selectors: {
843
+ selectCurrentDialogKey: (state) => state.currentDialogKey,
844
+ selectIsUpdatingMode: (state) => state.isUpdatingMode,
845
+ selectDialogRuntimeByKey: (state, dialogKey?: string) =>
846
+ getDialogRuntimeState(state, dialogKey),
847
+ selectPendingFiles: (state, dialogKey?: string) =>
848
+ getDialogRuntimeState(state, dialogKey).pendingFiles,
849
+ selectActiveControllers: (state, dialogKey?: string) =>
850
+ getDialogRuntimeState(state, dialogKey).activeControllers,
851
+ selectPendingRawData: (state, dialogKey?: string) =>
852
+ getDialogRuntimeState(state, dialogKey).pendingRawData,
853
+ selectDialogRuntimeTokens: (state, dialogKey?: string) =>
854
+ getDialogRuntimeState(state, dialogKey).tokens,
855
+ selectDialogRuntimeGoal: (state, dialogKey?: string) =>
856
+ getDialogRuntimeState(state, dialogKey).goal ?? null,
857
+ selectTotalDialogTokens: (state, dialogKey?: string) =>
858
+ getDialogRuntimeState(state, dialogKey).tokens,
859
+ selectPendingRawDataByPageKey: (state, pageKey: string) =>
860
+ getDialogRuntimeState(state).pendingRawData[pageKey],
861
+ selectPendingUserInputQueue: (state, dialogKey?: string) =>
862
+ getDialogRuntimeState(state, dialogKey).pendingUserInputQueue,
863
+ selectLoopStopReason: (state, dialogKey?: string) =>
864
+ getDialogRuntimeState(state, dialogKey).loopStopReason,
865
+ },
866
+ });
867
+
868
+ // --- Actions and Reducer Exports ---
869
+ export const {
870
+ createPageAndAddReference,
871
+ addPendingFile,
872
+ removePendingFile,
873
+ clearPendingAttachments,
874
+ clearDialogRuntimeState,
875
+ initDialog,
876
+ deleteDialog,
877
+ updateTokens,
878
+ saveDialogGoal,
879
+ saveCompletedDialogGoal,
880
+ clearDialogState,
881
+ createDialog,
882
+ createScheduledTask,
883
+ createDialogGoal,
884
+ completeDialogGoal,
885
+ updateDialogTitle,
886
+ addCybot,
887
+ addDialogAgent,
888
+ removeCybot,
889
+ removeDialogAgent,
890
+ replacePrimaryCybot,
891
+ setPrimaryDialogAgent,
892
+ handleSendMessage,
893
+ addActiveController,
894
+ removeActiveController,
895
+ abortAllMessages,
896
+ clearActiveControllers,
897
+ tokenUsageLiveUpdate,
898
+ setLoopStopReason,
899
+ enqueueUserInput,
900
+ dequeueUserInput,
901
+ clearPendingUserInputQueue,
902
+ } = dialogSlice.actions;
903
+
904
+ export default dialogSlice.reducer;
905
+
906
+ // --- Selectors Exports ---
907
+ export const {
908
+ selectCurrentDialogKey,
909
+ selectIsUpdatingMode,
910
+ selectPendingFiles,
911
+ selectActiveControllers,
912
+ selectDialogRuntimeByKey,
913
+ selectLoopStopReason,
914
+ selectPendingRawData,
915
+ selectDialogRuntimeTokens,
916
+ selectDialogRuntimeGoal,
917
+ selectPendingRawDataByPageKey,
918
+ selectPendingUserInputQueue,
919
+ } = dialogSlice.selectors;
920
+
921
+ export const selectCurrentDialogConfig = createSelector(
922
+ (state: RootState) => state,
923
+ selectCurrentDialogKey,
924
+ (state, currentDialogKey) =>
925
+ currentDialogKey
926
+ ? (selectById(state, currentDialogKey) as DialogConfig | null)
927
+ : null
928
+ );
929
+
930
+ export const selectCurrentDialogAgentIds = createSelector(
931
+ selectCurrentDialogConfig,
932
+ (dialogConfig) => getDialogAgentIds(dialogConfig)
933
+ );
934
+
935
+ export const selectCurrentPrimaryAgentId = createSelector(
936
+ selectCurrentDialogConfig,
937
+ (dialogConfig) => getPrimaryDialogAgentId(dialogConfig)
938
+ );
939
+
940
+ export const selectDialogConfigByKey = createSelector(
941
+ (state: RootState) => state,
942
+ (_: RootState, dialogKey?: string | null) => dialogKey,
943
+ (state, dialogKey) =>
944
+ dialogKey ? (selectById(state, dialogKey) as DialogConfig | null) : null
945
+ );
946
+
947
+ export const selectCurrentDialogTokens = createSelector(
948
+ (state: RootState) => state,
949
+ selectCurrentDialogConfig,
950
+ (state: RootState) => selectDialogRuntimeTokens(state),
951
+ (_state: RootState, dialogKey?: string) => dialogKey,
952
+ (state, currentDialog, currentRuntimeTokens, dialogKey) => {
953
+ if (dialogKey) {
954
+ const dialogConfig = selectById(state, dialogKey) as DialogConfig | null;
955
+ const runtimeTokens = selectDialogRuntimeTokens(state, dialogKey);
956
+ return mergeDialogTokenStats(dialogConfig, runtimeTokens);
957
+ }
958
+
959
+ return mergeDialogTokenStats(currentDialog, currentRuntimeTokens);
960
+ }
961
+ );
962
+
963
+ export const selectTotalDialogTokens = selectCurrentDialogTokens;
964
+
965
+ export const selectCurrentDialogGoalReport = createSelector(
966
+ (state: RootState) => state,
967
+ selectCurrentDialogConfig,
968
+ (state: RootState) => selectDialogRuntimeTokens(state),
969
+ (state: RootState) => selectDialogRuntimeGoal(state),
970
+ (_state: RootState, dialogKey?: string) => dialogKey,
971
+ (state, currentDialog, currentRuntimeTokens, currentRuntimeGoal, dialogKey) => {
972
+ if (dialogKey) {
973
+ const dialogConfig = selectById(state, dialogKey) as DialogConfig | null;
974
+ const runtimeTokens = selectDialogRuntimeTokens(state, dialogKey);
975
+ const runtimeGoal = selectDialogRuntimeGoal(state, dialogKey);
976
+ return getDialogGoalReport(dialogConfig, runtimeTokens, runtimeGoal);
977
+ }
978
+
979
+ return getDialogGoalReport(
980
+ currentDialog,
981
+ currentRuntimeTokens,
982
+ currentRuntimeGoal
983
+ );
984
+ }
985
+ );