nolo-cli 0.1.39 → 0.1.41

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 (438) hide show
  1. package/README.md +4 -4
  2. package/agent-runtime/dialogWritePlan.ts +39 -0
  3. package/agent-runtime/hostAdapter.ts +4 -0
  4. package/agent-runtime/hybridRecordStore.ts +5 -3
  5. package/agent-runtime/index.ts +15 -0
  6. package/agent-runtime/localLoop.ts +87 -7
  7. package/agent-runtime/localToolPolicy.ts +2 -13
  8. package/agent-runtime/localWorkspaceTools.ts +42 -110
  9. package/agent-runtime/runtimeToolPolicy.ts +2 -11
  10. package/agent-runtime/runtimeToolSurface.ts +198 -0
  11. package/agent-runtime/types.ts +1 -0
  12. package/agentAliases.ts +2 -1
  13. package/agentRunCommand.ts +10 -32
  14. package/agentRuntimeLocal.ts +1 -0
  15. package/ai/agent/_executeModel.ts +146 -0
  16. package/ai/agent/agentSlice.ts +556 -1
  17. package/ai/agent/appWorkingMemory.ts +126 -0
  18. package/ai/agent/buildEditingContext.ts +378 -0
  19. package/ai/agent/buildSystemPrompt.ts +585 -0
  20. package/ai/agent/canvasEditingContext.ts +49 -0
  21. package/ai/agent/cleanAgentMessages.ts +140 -0
  22. package/ai/agent/cliChatClient.ts +153 -0
  23. package/ai/agent/cliExecutor.ts +314 -40
  24. package/ai/agent/contextCompiler.ts +107 -0
  25. package/ai/agent/contextLayerContract.ts +44 -0
  26. package/ai/agent/createAgentSchema.ts +272 -0
  27. package/ai/agent/currentTimeContext.ts +65 -0
  28. package/ai/agent/executeToolCall.ts +58 -0
  29. package/ai/agent/fetchAgentContexts.ts +42 -0
  30. package/ai/agent/generatePrompt.ts +3 -0
  31. package/ai/agent/getFullChatContextKeys.ts +168 -0
  32. package/ai/agent/guidedCreation/capabilities.ts +84 -0
  33. package/ai/agent/guidedCreation/types.ts +38 -0
  34. package/ai/agent/isLiveAudioOnlyAgent.ts +26 -0
  35. package/ai/agent/liveAudioModel.ts +2 -0
  36. package/ai/agent/pageBuilderHandoffRules.ts +75 -0
  37. package/ai/agent/persistMessageWithFixedId.ts +37 -0
  38. package/ai/agent/planSlice.ts +259 -0
  39. package/ai/agent/referenceUtils.ts +229 -0
  40. package/ai/agent/runAgentBackground.ts +310 -0
  41. package/ai/agent/runAgentClientLoop.ts +164 -0
  42. package/ai/agent/runtimeGuidance.ts +116 -0
  43. package/ai/agent/serverOrigin.ts +7 -0
  44. package/ai/agent/startParallelAgentStreams.ts +424 -0
  45. package/ai/agent/startupProtocol.ts +53 -0
  46. package/ai/agent/streamAgentChatTurn.ts +2001 -0
  47. package/ai/agent/streamAgentChatTurnUtils.ts +860 -0
  48. package/ai/agent/toolFailureGuard.ts +99 -0
  49. package/ai/agent/types.ts +73 -0
  50. package/ai/agent/utils/imageOutput.ts +37 -0
  51. package/ai/agent/utils/publicImageAgentMode.ts +26 -0
  52. package/ai/ai.locale.ts +1095 -0
  53. package/ai/chat/accumulateToolCallChunks.ts +126 -0
  54. package/ai/chat/fetchUtils.ts +143 -0
  55. package/ai/chat/inlineImageUrlsForCustomProvider.ts +117 -0
  56. package/ai/chat/parseApiError.ts +67 -0
  57. package/ai/chat/parseMultilineSSE.ts +95 -0
  58. package/ai/chat/sendOpenAICompletionsRequest.ts +897 -0
  59. package/ai/chat/sendOpenAIResponseRequest.ts +720 -0
  60. package/ai/chat/serverProxyRetry.ts +102 -0
  61. package/ai/chat/shouldUseServerProxy.ts +18 -0
  62. package/ai/chat/streamRetry.ts +46 -0
  63. package/ai/chat/updateTotalUsage.ts +89 -0
  64. package/ai/context/buildReferenceContext.ts +437 -0
  65. package/ai/context/retention.ts +165 -0
  66. package/ai/context/tokenUtils.ts +78 -0
  67. package/ai/llm/agentCapabilities.ts +74 -0
  68. package/ai/llm/deepinfra.ts +79 -0
  69. package/ai/llm/fireworks.ts +68 -0
  70. package/ai/llm/generateRequestBody.ts +165 -0
  71. package/ai/llm/getModelContextWindow.ts +93 -0
  72. package/ai/llm/getPricing.ts +252 -0
  73. package/ai/llm/imagePricing.ts +66 -0
  74. package/ai/llm/isResponseAPIModel.ts +13 -0
  75. package/ai/llm/kimi.ts +23 -0
  76. package/ai/llm/mimo.ts +99 -0
  77. package/ai/llm/mistral.ts +21 -0
  78. package/ai/llm/models.ts +45 -0
  79. package/ai/llm/openrouterModels.ts +6 -0
  80. package/ai/llm/providers.ts +313 -0
  81. package/ai/llm/reasoningModels.ts +27 -0
  82. package/ai/llm/types.ts +82 -0
  83. package/ai/llm/usageRequestOptions.ts +59 -0
  84. package/ai/memory/queryShared.ts +161 -0
  85. package/ai/memory/recentRelationshipRecap.ts +247 -0
  86. package/ai/memory/remember.ts +167 -0
  87. package/ai/memory/store.ts +20 -0
  88. package/ai/memory/storeShared.ts +76 -0
  89. package/ai/memory/types.ts +46 -0
  90. package/ai/memory/understanding.ts +349 -0
  91. package/ai/memory/understandingGreeting.ts +264 -0
  92. package/ai/policy/personalizationDialog.ts +333 -0
  93. package/ai/policy/runtimePolicy.ts +454 -0
  94. package/ai/policy/selfUpdateFields.ts +48 -0
  95. package/ai/policy/types.ts +64 -0
  96. package/ai/skills/referenceRuntime.ts +274 -0
  97. package/ai/skills/skillDiagnostics.ts +251 -0
  98. package/ai/skills/skillDocBuilder.ts +139 -0
  99. package/ai/skills/skillSummaryMarker.ts +26 -0
  100. package/ai/token/calculatePrice.ts +576 -0
  101. package/ai/token/missingUsageEstimate.ts +42 -0
  102. package/ai/token/normalizeUsage.ts +124 -0
  103. package/ai/token/openaiImageGenerationUsage.ts +56 -0
  104. package/ai/token/prepareTokenUsageData.ts +93 -0
  105. package/ai/token/resolveBillingTarget.ts +52 -0
  106. package/ai/token/saveTokenRecord.ts +53 -0
  107. package/ai/token/types.ts +103 -0
  108. package/ai/tools/agent/agentTools.ts +235 -0
  109. package/ai/tools/agent/agentUpdateShared.ts +311 -0
  110. package/ai/tools/agent/callAgentTool.ts +139 -0
  111. package/ai/tools/agent/createAgentTool.ts +512 -0
  112. package/ai/tools/agent/createDialogTool.ts +69 -0
  113. package/ai/tools/agent/createSkillAgentTool.ts +62 -0
  114. package/ai/tools/agent/parallelBudget.ts +221 -0
  115. package/ai/tools/agent/prepareAgentDraftTool.ts +159 -0
  116. package/ai/tools/agent/presets/appBuilderPreset.ts +154 -0
  117. package/ai/tools/agent/runLlmTool.ts +96 -0
  118. package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
  119. package/ai/tools/agent/skillAgentArgs.ts +106 -0
  120. package/ai/tools/agent/startAgentDialogTool.ts +53 -0
  121. package/ai/tools/agent/streamParallelAgentsTool.ts +123 -0
  122. package/ai/tools/agent/updateAgentTool.ts +96 -0
  123. package/ai/tools/agent/updateSelfTool.ts +113 -0
  124. package/ai/tools/amazonProductScraperTool.ts +86 -0
  125. package/ai/tools/apifyActorClient.ts +45 -0
  126. package/ai/tools/appEditGuard.ts +372 -0
  127. package/ai/tools/appReadSnapshot.ts +153 -0
  128. package/ai/tools/appTools.ts +1549 -0
  129. package/ai/tools/applyEditTool.ts +259 -0
  130. package/ai/tools/applyLineEditsTool.ts +315 -0
  131. package/ai/tools/browserTools/click.ts +33 -0
  132. package/ai/tools/browserTools/closeSession.ts +29 -0
  133. package/ai/tools/browserTools/common.ts +27 -0
  134. package/ai/tools/browserTools/openSession.ts +48 -0
  135. package/ai/tools/browserTools/readContent.ts +38 -0
  136. package/ai/tools/browserTools/selectOption.ts +46 -0
  137. package/ai/tools/browserTools/typeText.ts +42 -0
  138. package/ai/tools/category/createCategoryTool.ts +66 -0
  139. package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
  140. package/ai/tools/category/updateContentCategoryTool.ts +75 -0
  141. package/ai/tools/cfBrowserTools.ts +319 -0
  142. package/ai/tools/cfSpeechToTextTool.ts +49 -0
  143. package/ai/tools/checkEnvTool.ts +102 -0
  144. package/ai/tools/cloudflareCrawlTool.ts +289 -0
  145. package/ai/tools/codeSearchTool.ts +123 -0
  146. package/ai/tools/codeTools.ts +101 -0
  147. package/ai/tools/convertMarxistsBookTool.ts +103 -0
  148. package/ai/tools/createDocTool.ts +132 -0
  149. package/ai/tools/createSkillDocTool.ts +155 -0
  150. package/ai/tools/createWorkflowTool.ts +154 -0
  151. package/ai/tools/delayTool.ts +31 -0
  152. package/ai/tools/deleteSpacesTool.ts +325 -0
  153. package/ai/tools/deleteSpacesToolModel.ts +159 -0
  154. package/ai/tools/devReloadUtils.ts +29 -0
  155. package/ai/tools/dialogMessageSearch.ts +137 -0
  156. package/ai/tools/doctorSkillTool.ts +72 -0
  157. package/ai/tools/ecommerceScraperTool.ts +86 -0
  158. package/ai/tools/emailTools.ts +549 -0
  159. package/ai/tools/evalSkillTool.ts +92 -0
  160. package/ai/tools/exaSearchTool.ts +63 -0
  161. package/ai/tools/execShellTool.ts +266 -0
  162. package/ai/tools/executeSqlTool.ts +192 -0
  163. package/ai/tools/fetchWebpageSupport.ts +333 -0
  164. package/ai/tools/fetchWebpageTool.ts +97 -0
  165. package/ai/tools/geminiImagePreviewTool.ts +386 -0
  166. package/ai/tools/generateDocxTool.ts +215 -0
  167. package/ai/tools/googleSearchScraperTool.ts +106 -0
  168. package/ai/tools/importDataTool.ts +133 -0
  169. package/ai/tools/importSkillTool.ts +162 -0
  170. package/ai/tools/index.ts +2308 -0
  171. package/ai/tools/jdProductScraperTool.ts +821 -0
  172. package/ai/tools/listUserSpacesTool.ts +113 -0
  173. package/ai/tools/localFilesTool.ts +276 -0
  174. package/ai/tools/marxistsOfflineBook.ts +253 -0
  175. package/ai/tools/modelUsageTools.ts +206 -0
  176. package/ai/tools/noloWorkspaceReadTools.ts +467 -0
  177. package/ai/tools/olmOcrTool.ts +33 -0
  178. package/ai/tools/openaiImageTool.ts +267 -0
  179. package/ai/tools/prepareTools.ts +23 -0
  180. package/ai/tools/readDocTool.ts +88 -0
  181. package/ai/tools/readFileTool.ts +214 -0
  182. package/ai/tools/readTool.ts +194 -0
  183. package/ai/tools/readXPostTool.ts +229 -0
  184. package/ai/tools/readXhsProfileTool.ts +627 -0
  185. package/ai/tools/rememberMemoryTool.ts +84 -0
  186. package/ai/tools/remotionVideoTool.ts +151 -0
  187. package/ai/tools/searchDialogMessagesTool.ts +222 -0
  188. package/ai/tools/searchWorkspaceTool.ts +259 -0
  189. package/ai/tools/skillFollowup.ts +86 -0
  190. package/ai/tools/surfWeatherTool.ts +169 -0
  191. package/ai/tools/table/addTableRowTool.ts +217 -0
  192. package/ai/tools/table/createTableTool.ts +315 -0
  193. package/ai/tools/table/rowTools.ts +386 -0
  194. package/ai/tools/table/schemaTools.ts +244 -0
  195. package/ai/tools/table/shareTableTool.ts +148 -0
  196. package/ai/tools/table/toolShared.ts +129 -0
  197. package/ai/tools/taobaoTmallProductScraperTool.ts +49 -0
  198. package/ai/tools/toolApiClient.ts +279 -0
  199. package/ai/tools/toolResultError.ts +42 -0
  200. package/ai/tools/toolRunSlice.ts +303 -0
  201. package/ai/tools/toolSchemaCompatibility.ts +53 -0
  202. package/ai/tools/uiAskChoiceTool.ts +104 -0
  203. package/ai/tools/updateContentTitleTool.ts +84 -0
  204. package/ai/tools/updateDocTool.ts +105 -0
  205. package/ai/tools/updateUserPreferenceProfileTool.ts +153 -0
  206. package/ai/tools/wereadGatewayTool.ts +152 -0
  207. package/ai/tools/whisperTool.ts +76 -0
  208. package/ai/tools/writeFileTool.ts +213 -0
  209. package/ai/tools/youtubeScraperTool.ts +116 -0
  210. package/ai/tools/ziweiChartTool.ts +678 -0
  211. package/ai/types.ts +55 -0
  212. package/ai/workflow/workflowExecutor.ts +323 -0
  213. package/ai/workflow/workflowSlice.ts +73 -0
  214. package/ai/workflow/workflowTypes.ts +106 -0
  215. package/app/actions/syncAppRecord.ts +73 -0
  216. package/app/constants/animationSets.ts +21 -0
  217. package/app/constants/appEditor.ts +99 -0
  218. package/app/favorite/favoriteSlice.ts +690 -0
  219. package/app/favorite/type.ts +43 -0
  220. package/app/hooks/deleteDbKey.ts +233 -0
  221. package/app/i18n/client.ts +13 -0
  222. package/app/i18n/i18n.base.ts +14 -0
  223. package/app/i18n/i18n.config.ts +77 -0
  224. package/app/i18n/index.ts +15 -0
  225. package/app/i18n/mapLanguage.ts +11 -0
  226. package/app/i18n/translations/appBuilder.locale.ts +453 -0
  227. package/app/i18n/translations/error.locale.ts +246 -0
  228. package/app/i18n/translations/interface.locale.ts +2174 -0
  229. package/app/i18n/translations/pricing.locale.ts +397 -0
  230. package/app/i18n/translations/privacy.locale.ts +168 -0
  231. package/app/i18n/translations/seo.locale.ts +129 -0
  232. package/app/i18n/translations/terms.locale.ts +124 -0
  233. package/app/i18n/types.ts +6 -0
  234. package/app/notifications/model.ts +77 -0
  235. package/app/notifications/notificationSlice.ts +141 -0
  236. package/app/reducer.ts +36 -0
  237. package/app/settings/dbActionThunks.ts +34 -0
  238. package/app/settings/defaultSpacePreference.ts +87 -0
  239. package/app/settings/settingSlice.tsx +1212 -0
  240. package/app/settings/settingsRecord.ts +8 -0
  241. package/app/stateViews/runtime.ts +90 -0
  242. package/app/store.ts +55 -0
  243. package/app/theme/colors.ts +280 -0
  244. package/app/theme/fontPreference.ts +77 -0
  245. package/app/theme/theme.config.ts +120 -0
  246. package/app/theme/themeModeBootstrap.ts +123 -0
  247. package/app/types/appSummary.ts +114 -0
  248. package/app/types.ts +358 -0
  249. package/app/utils/appKeys.ts +55 -0
  250. package/app/utils/async.ts +28 -0
  251. package/app/utils/desktopAgentRuntimeTurnClient.ts +73 -0
  252. package/app/utils/env.ts +17 -0
  253. package/app/utils/fileUtils.ts +229 -0
  254. package/app/utils/imageUtils.ts +274 -0
  255. package/app/utils/myContentItems.ts +289 -0
  256. package/app/utils/retryAfter.ts +36 -0
  257. package/app/utils/retryFetch.ts +61 -0
  258. package/app/utils/toast.ts +3 -0
  259. package/auth/action/signUpAction.ts +227 -0
  260. package/auth/adminPermissions.ts +18 -0
  261. package/auth/authSlice.ts +531 -0
  262. package/auth/client/loginRequest.ts +14 -0
  263. package/auth/resetAuthScopedClientState.ts +27 -0
  264. package/auth/routes.ts +178 -0
  265. package/auth/token.ts +63 -0
  266. package/auth/types.ts +40 -0
  267. package/chat/chat.locale.ts +813 -0
  268. package/chat/dialog/actions/addCybotAction.ts +52 -0
  269. package/chat/dialog/actions/addReferenceKeysAction.ts +62 -0
  270. package/chat/dialog/actions/builtinDialogLlm.ts +35 -0
  271. package/chat/dialog/actions/cleanupCliSession.ts +40 -0
  272. package/chat/dialog/actions/createDialogAction.ts +379 -0
  273. package/chat/dialog/actions/createScheduledTaskAction.ts +78 -0
  274. package/chat/dialog/actions/handleSendMessageAction.ts +197 -0
  275. package/chat/dialog/actions/handleSendMessageResolver.ts +27 -0
  276. package/chat/dialog/actions/removeCybotAction.ts +6 -0
  277. package/chat/dialog/actions/removeDialogAgentAction.ts +44 -0
  278. package/chat/dialog/actions/replacePrimaryCybotAction.ts +6 -0
  279. package/chat/dialog/actions/setPrimaryDialogAgentAction.ts +52 -0
  280. package/chat/dialog/actions/updateDialogSummaryAction.ts +430 -0
  281. package/chat/dialog/actions/updateDialogTitleAction.ts +151 -0
  282. package/chat/dialog/actions/updateDialogTitlePolicy.ts +30 -0
  283. package/chat/dialog/actions/updateTokensAction.ts +233 -0
  284. package/chat/dialog/dialogAgents.ts +72 -0
  285. package/chat/dialog/dialogSlice.ts +872 -0
  286. package/chat/dialog/dialogTitle.ts +81 -0
  287. package/chat/dialog/dialogTokenStats.ts +12 -0
  288. package/chat/dialog/dialogUrl.ts +6 -0
  289. package/chat/dialog/goal.ts +108 -0
  290. package/chat/dialog/objectAssistantRegistry.ts +286 -0
  291. package/chat/dialog/schedule.ts +17 -0
  292. package/chat/messages/fetchAndCacheMessages.ts +119 -0
  293. package/chat/messages/fetchConvMsgs.ts +51 -0
  294. package/chat/messages/fileUrl.ts +13 -0
  295. package/chat/messages/messageAgent.ts +8 -0
  296. package/chat/messages/messageContent.ts +199 -0
  297. package/chat/messages/messageContract.ts +88 -0
  298. package/chat/messages/messageSlice.ts +1367 -0
  299. package/chat/messages/toolThunks.ts +625 -0
  300. package/cli/agentAliases.ts +2 -1
  301. package/cli/agentRunCommand.ts +10 -32
  302. package/cli/agentRuntimeLocal.ts +1 -0
  303. package/cli/client/agentRun.ts +67 -95
  304. package/cli/client/localRuntimeAdapter.ts +323 -54
  305. package/cli/commandRegistry.ts +2 -2
  306. package/cli/machineWsRunDispatch.ts +51 -6
  307. package/cli/offlineMarxistsAgentCommand.ts +6 -4
  308. package/client/agentConfigResolver.test.ts +2 -2
  309. package/client/agentRun.test.ts +175 -57
  310. package/client/agentRun.ts +67 -95
  311. package/client/localRuntimeAdapter.test.ts +682 -37
  312. package/client/localRuntimeAdapter.ts +323 -54
  313. package/client/localRuntimeDryRun.test.ts +23 -9
  314. package/client/localToolPolicy.test.ts +4 -4
  315. package/commandRegistry.ts +2 -2
  316. package/core/builtinAgents.ts +209 -0
  317. package/core/config.ts +15 -0
  318. package/core/crypto.ts +51 -0
  319. package/core/generateKeyPairFromSeedV1.ts +15 -0
  320. package/core/generateMainKey.ts +22 -0
  321. package/core/init.ts +41 -0
  322. package/core/localOrigins.ts +8 -0
  323. package/core/password.ts +13 -0
  324. package/core/prefix.ts +23 -0
  325. package/create/editor/transforms/fromMarkdown/index.ts +260 -0
  326. package/create/editor/transforms/fromMarkdown/inline.ts +285 -0
  327. package/create/editor/transforms/fromMarkdown/table.ts +130 -0
  328. package/create/editor/transforms/markdownToSlate.ts +24 -0
  329. package/create/editor/transforms/slateToRenderMarkdown.ts +218 -0
  330. package/create/editor/transforms/slateToSimplifiedMarkdown.ts +224 -0
  331. package/create/editor/transforms/slateToText.ts +33 -0
  332. package/create/editor/utils/slateUtils.ts +233 -0
  333. package/create/space/addSpaceAction.ts +193 -0
  334. package/create/space/category/categoryActions.ts +427 -0
  335. package/create/space/changeSpaceAction.ts +36 -0
  336. package/create/space/constants.ts +8 -0
  337. package/create/space/content/addContentAction.ts +116 -0
  338. package/create/space/content/contentThunks.ts +90 -0
  339. package/create/space/content/deleteContentFromSpaceAction.ts +187 -0
  340. package/create/space/content/deleteMultipleContentAction.ts +112 -0
  341. package/create/space/content/moveContentAction.ts +285 -0
  342. package/create/space/content/updateContentCategoryAction.ts +154 -0
  343. package/create/space/content/updateContentTitleAction.ts +151 -0
  344. package/create/space/content/uploadAndAddFileToSpaceAction.ts +98 -0
  345. package/create/space/contentKeyUtils.ts +117 -0
  346. package/create/space/deleteSpaceAction.ts +276 -0
  347. package/create/space/fetchSpaceAction.ts +70 -0
  348. package/create/space/fetchSpaceSidebarStateAction.ts +26 -0
  349. package/create/space/loadDefaultSpaceAction.ts +57 -0
  350. package/create/space/member/addMemberAction.ts +79 -0
  351. package/create/space/member/fetchUserSpaceMembershipsAction.ts +386 -0
  352. package/create/space/member/memberThunks.ts +47 -0
  353. package/create/space/member/removeMemberAction.ts +67 -0
  354. package/create/space/resolvePreferredSpaceId.ts +113 -0
  355. package/create/space/sidebarVisibleTypes.ts +241 -0
  356. package/create/space/space.locale.ts +1087 -0
  357. package/create/space/spaceAccess.ts +182 -0
  358. package/create/space/spaceCollapsedState.ts +54 -0
  359. package/create/space/spaceKeys.ts +65 -0
  360. package/create/space/spaceSlice.ts +328 -0
  361. package/create/space/spaceThunks.ts +410 -0
  362. package/create/space/types.ts +27 -0
  363. package/create/space/updateSpaceAction.ts +107 -0
  364. package/create/space/utils/permissions.ts +47 -0
  365. package/create/types.ts +21 -0
  366. package/database/actions/agentReadResolution.ts +33 -0
  367. package/database/actions/common.ts +243 -0
  368. package/database/actions/deleteFile.ts +40 -0
  369. package/database/actions/fileContent.ts +125 -0
  370. package/database/actions/patch.ts +155 -0
  371. package/database/actions/read.ts +358 -0
  372. package/database/actions/readAndWait.ts +260 -0
  373. package/database/actions/readRequestManager.ts +120 -0
  374. package/database/actions/readResolution.ts +125 -0
  375. package/database/actions/remove.ts +94 -0
  376. package/database/actions/replication.ts +477 -0
  377. package/database/actions/upload.ts +186 -0
  378. package/database/actions/upsert.ts +56 -0
  379. package/database/actions/write.ts +146 -0
  380. package/database/authority/ownerKey.ts +80 -0
  381. package/database/authority/recordAuthority.ts +67 -0
  382. package/database/authority/userAuthorityRegistry.ts +54 -0
  383. package/database/client/fetchUserData.ts +61 -0
  384. package/database/dbActionThunks.ts +1 -0
  385. package/database/dbSlice.ts +149 -0
  386. package/database/fileRing.ts +51 -0
  387. package/database/fileStorage.ts +232 -0
  388. package/database/fileUrl.ts +34 -0
  389. package/database/keys.ts +767 -0
  390. package/database/queryPrefixes.ts +14 -0
  391. package/database/requests.ts +443 -0
  392. package/database/runtimeServerContext.ts +54 -0
  393. package/database/server/levelAuthorityStore.ts +20 -1
  394. package/database/tenantPlacement.ts +57 -0
  395. package/database/userPreferenceRegister.ts +131 -0
  396. package/database/utils/ulid.ts +1 -0
  397. package/integrations/anthropic/anthropicModels.ts +47 -0
  398. package/integrations/deepseek/models.ts +37 -0
  399. package/integrations/google/models.ts +341 -0
  400. package/integrations/openai/chatCompletionStreamMode.ts +10 -0
  401. package/integrations/openai/filterAndCleanMessages.ts +284 -0
  402. package/integrations/openai/flexTier.ts +102 -0
  403. package/integrations/openai/generateOpenAIRequestBody.ts +274 -0
  404. package/integrations/openai/generateResponseRequestBody.ts +77 -0
  405. package/integrations/openai/models.ts +271 -0
  406. package/integrations/openai/providerBodyCompatibility.ts +23 -0
  407. package/integrations/openai/responsesHelpers.ts +297 -0
  408. package/integrations/x-reader/types.ts +109 -0
  409. package/integrations/xai/models.ts +13 -0
  410. package/integrations/xhs-reader/analyze/profileAnalyzer.ts +205 -0
  411. package/integrations/xhs-reader/backends/playwrightProfileCollector.ts +624 -0
  412. package/integrations/xhs-reader/bridge/readXhsProfileWithBridge.ts +227 -0
  413. package/integrations/xhs-reader/client/xhsWebApiClient.ts +229 -0
  414. package/integrations/xhs-reader/normalize.ts +390 -0
  415. package/integrations/xhs-reader/orchestrator.ts +178 -0
  416. package/integrations/xhs-reader/redaction.ts +68 -0
  417. package/integrations/xhs-reader/types.ts +244 -0
  418. package/integrations/xhs-reader/url.ts +57 -0
  419. package/machineWsRunDispatch.ts +51 -6
  420. package/offlineMarxistsAgentCommand.ts +6 -4
  421. package/package.json +430 -3
  422. package/render/page/createPageAction.ts +183 -0
  423. package/render/page/docSlice.ts +468 -0
  424. package/render/page/types.ts +17 -0
  425. package/render/table/createTableAction.ts +270 -0
  426. package/render/table/deleteTableAction.ts +193 -0
  427. package/render/table/fetchAndCacheTableRows.ts +174 -0
  428. package/render/table/tableSlice.ts +1106 -0
  429. package/render/table/toolValueUtils.ts +363 -0
  430. package/render/table/types.ts +252 -0
  431. package/render/table/utils/tableSerialization.ts +50 -0
  432. package/server/handlers/agentRun/types.ts +104 -0
  433. package/share/action.ts +225 -0
  434. package/share/helpers.ts +302 -0
  435. package/share/keys.ts +243 -0
  436. package/share/publicSharePolicy.ts +27 -0
  437. package/share/shareSlice.ts +53 -0
  438. package/share/types.ts +100 -0
@@ -0,0 +1,224 @@
1
+ type SimplifiedMarkdownOptions = {
2
+ mentionResolver?: (node: any) => string;
3
+ };
4
+
5
+ function renderTextNode(node: any): string {
6
+ if (!node || typeof node.text !== "string") return "";
7
+
8
+ let text = node.text;
9
+ if (!text) return "";
10
+
11
+ if (node.bold) text = `**${text}**`;
12
+ if (node.italic) text = `*${text}*`;
13
+ if (node.strikethrough) text = `~~${text}~~`;
14
+ return text;
15
+ }
16
+
17
+ function renderPlainText(node: any, options: SimplifiedMarkdownOptions = {}): string {
18
+ if (!node) return "";
19
+ if (typeof node.text === "string") return renderTextNode(node);
20
+ if (!Array.isArray(node.children)) return "";
21
+ return node.children.map((child: any) => renderPlainText(child, options)).join("");
22
+ }
23
+
24
+ function renderTable(node: any, listDepth: number, options: SimplifiedMarkdownOptions): string {
25
+ const rows = Array.isArray(node.children) ? node.children : [];
26
+ if (rows.length === 0) return "";
27
+
28
+ const alignments = Array.isArray(node.columns)
29
+ ? node.columns.map((column: any) => column?.align || "left")
30
+ : [];
31
+
32
+ const renderedRows = rows.map((row: any) =>
33
+ (Array.isArray(row?.children) ? row.children : []).map((cell: any) => {
34
+ const content = renderPlainText(cell, options).replace(/\n+/g, " ").trim();
35
+ return content || " ";
36
+ })
37
+ );
38
+
39
+ const header = renderedRows[0] || [];
40
+ const divider = header.map((_, index) => {
41
+ const align = alignments[index];
42
+ if (align === "center") return ":---:";
43
+ if (align === "right") return "---:";
44
+ return "---";
45
+ });
46
+ const body = renderedRows.slice(1);
47
+
48
+ const allRows = [header, divider, ...body]
49
+ .map((cells) => `| ${cells.join(" | ")} |`)
50
+ .join("\n");
51
+
52
+ return `${allRows}\n\n`;
53
+ }
54
+
55
+ function renderListItem(
56
+ node: any,
57
+ listDepth: number,
58
+ ordered: boolean,
59
+ start: number,
60
+ index: number,
61
+ options: SimplifiedMarkdownOptions = {}
62
+ ): string {
63
+ const indentation = " ".repeat(listDepth);
64
+ const marker = node.checked === true
65
+ ? "- [x]"
66
+ : node.checked === false
67
+ ? "- [ ]"
68
+ : ordered
69
+ ? `${start + index}.`
70
+ : "-";
71
+
72
+ const segments = Array.isArray(node.children) ? node.children : [];
73
+ const renderedSegments = segments
74
+ .map((child: any) => renderNode(child, listDepth + 1, options).trimEnd())
75
+ .filter(Boolean);
76
+
77
+ if (renderedSegments.length === 0) {
78
+ return `${indentation}${marker}\n`;
79
+ }
80
+
81
+ const [first, ...rest] = renderedSegments;
82
+ const lines = first.split("\n");
83
+ const firstLine = lines.shift() || "";
84
+ const restFirst = lines.map((line) => `${indentation} ${line}`).join("\n");
85
+ const restBlocks = rest.map((block) => `${indentation} ${block}`).join("\n");
86
+
87
+ return [
88
+ `${indentation}${marker} ${firstLine}`,
89
+ restFirst,
90
+ restBlocks,
91
+ ]
92
+ .filter(Boolean)
93
+ .join("\n") + "\n";
94
+ }
95
+
96
+ /**
97
+ * 递归地把 Slate 节点线性化为“易读 markdown”。
98
+ * 这里的目标是让 AI / 工具读取时更稳定,不追求展示侧的视觉保真。
99
+ */
100
+ function renderNode(
101
+ node: any,
102
+ listDepth = 0,
103
+ options: SimplifiedMarkdownOptions = {}
104
+ ): string {
105
+ if (!node) return "";
106
+ const indentation = " ".repeat(listDepth);
107
+
108
+ switch (node.type) {
109
+ case "heading-one":
110
+ return `# ${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\n\n`;
111
+ case "heading-two":
112
+ return `## ${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\n\n`;
113
+ case "heading-three":
114
+ return `### ${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\n\n`;
115
+ case "heading-four":
116
+ return `#### ${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\n\n`;
117
+ case "heading-five":
118
+ return `##### ${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\n\n`;
119
+ case "heading-six":
120
+ return `###### ${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\n\n`;
121
+
122
+ case "paragraph":
123
+ return `${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\n\n`;
124
+
125
+ case "list":
126
+ return node.children
127
+ .map((item: any, index: number) =>
128
+ renderListItem(item, listDepth, !!node.ordered, node.start || 1, index, options)
129
+ )
130
+ .join("");
131
+
132
+ case "list-item":
133
+ return renderListItem(node, listDepth, false, 1, 0, options);
134
+
135
+ case "quote":
136
+ const content = node.children
137
+ .map((n: any) => renderNode(n, listDepth, options))
138
+ .join("")
139
+ .trim();
140
+ return `> ${content.replace(/\n/g, "\n> ")}\n\n`;
141
+
142
+ case "code-block":
143
+ const code = node.children
144
+ .map((line: any) =>
145
+ (line.children || []).map((text: any) => text.text).join("")
146
+ )
147
+ .join("\n");
148
+ return "```" + (node.language || "") + "\n" + code + "\n```\n\n";
149
+
150
+ case "link":
151
+ const linkText = node.children
152
+ .map((n: any) => renderNode(n, listDepth, options))
153
+ .join("");
154
+ return `[${linkText}](${node.url})`;
155
+
156
+ case "table":
157
+ return renderTable(node, listDepth, options);
158
+
159
+ case "code-inline":
160
+ return `\`${node.children.map((n: any) => renderNode(n, listDepth, options)).join("")}\``;
161
+
162
+ case "mention": {
163
+ if (options.mentionResolver) {
164
+ return options.mentionResolver(node);
165
+ }
166
+ const label = node.label || node.resourceId || "mention";
167
+ const resourceType = node.resourceType || "unknown";
168
+ const resourceId = node.resourceId || "unknown";
169
+ // AI / 工具链仍依赖 mention 的可逆文本表示。
170
+ return `@[${resourceType}:${resourceId}|${label}]`;
171
+ }
172
+
173
+ case "image": {
174
+ const alt = node.alt || "";
175
+ const title = node.title ? ` "${node.title}"` : "";
176
+ return `![${alt}](${node.url || ""}${title})`;
177
+ }
178
+
179
+ case "html-inline":
180
+ return typeof node.html === "string" ? node.html : "";
181
+
182
+ case "html-block":
183
+ return typeof node.html === "string" ? `${node.html}\n\n` : "";
184
+
185
+ case "thematic-break":
186
+ return "---\n\n";
187
+
188
+ default:
189
+ return (
190
+ renderTextNode(node) ||
191
+ (node.children
192
+ ? node.children
193
+ .map((child: any) => renderNode(child, listDepth, options))
194
+ .join("")
195
+ : "")
196
+ );
197
+ }
198
+ }
199
+
200
+ /**
201
+ * 把 Slate 转成给 AI / 工具消费的 markdown 文本。
202
+ *
203
+ * 目标:
204
+ * - 保留结构信息,让模型和工具容易读。
205
+ * - 保持 mention 等关键语义可逆。
206
+ *
207
+ * 非目标:
208
+ * - 不保证展示侧完全复刻编辑器视觉。
209
+ * - 不作为只读渲染缓存;展示侧请用 `slateToRenderMarkdown`。
210
+ */
211
+ export function slateToSimplifiedMarkdown(
212
+ nodes: any[],
213
+ options: SimplifiedMarkdownOptions = {}
214
+ ): string {
215
+ if (!nodes || nodes.length === 0) {
216
+ return "";
217
+ }
218
+ return (
219
+ nodes
220
+ .map((node) => renderNode(node, 0, options))
221
+ .join("")
222
+ .trim() + "\n"
223
+ );
224
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 这是一个递归的辅助函数,用于从单个 Slate 节点及其子节点中提取所有文本内容。
3
+ * @param node 当前要处理的 Slate 节点。
4
+ * @returns 提取出的文本字符串。
5
+ */
6
+ function getNodeText(node: any): string {
7
+ // 如果是文本节点,直接返回其文本内容
8
+ if (node.text) {
9
+ return node.text;
10
+ }
11
+
12
+ // 如果是元素节点(且非空),则递归地处理其所有子节点,
13
+ // 并将结果用适当的分隔符连接。对于大多数块级元素,换行符是合适的。
14
+ if (node.children && Array.isArray(node.children)) {
15
+ return node.children.map(getNodeText).join("\n");
16
+ }
17
+
18
+ // 对于其他情况(如空节点或无子节点的元素),返回空字符串
19
+ return "";
20
+ }
21
+
22
+ /**
23
+ * 将 Slate 节点数组转换为一个单一的、拼接好的纯文本字符串。
24
+ * @param nodes Slate 节点数组。
25
+ * @returns 拼接后的纯文本字符串,顶层节点间用双换行符分隔以模拟段落。
26
+ */
27
+ export function slateToText(nodes: any[]): string {
28
+ if (!nodes || nodes.length === 0) {
29
+ return "";
30
+ }
31
+
32
+ return nodes.map(getNodeText).join("\n\n");
33
+ }
@@ -0,0 +1,233 @@
1
+ import { Node } from "slate";
2
+
3
+ // ================ 类型定义 ================
4
+ export type EditorContent = Array<{
5
+ type: string;
6
+ children: Array<{ text: string;[key: string]: any }>;
7
+ [key: string]: any;
8
+ }>;
9
+
10
+ export const createEmptyParagraph = () => ({
11
+ type: "paragraph",
12
+ children: [{ text: "" }],
13
+ });
14
+
15
+ export const ensureEditorContent = (
16
+ slateData: EditorContent | null | undefined
17
+ ): EditorContent =>
18
+ Array.isArray(slateData) && slateData.length > 0
19
+ ? slateData
20
+ : [createEmptyParagraph()];
21
+
22
+ // ================ 工具函数 ================
23
+
24
+ /**
25
+ * 原生实现的深度比较
26
+ * 仅考虑普通对象、数组、基本类型,适用于 Slate Node 这类 JSON 结构
27
+ */
28
+ const deepEqual = (a: any, b: any): boolean => {
29
+ // 引用相同或值相同(包含基本类型)
30
+ if (a === b) return true;
31
+
32
+ // 其中一个为 null 或 undefined
33
+ if (a == null || b == null) return false;
34
+
35
+ // 类型不同
36
+ if (typeof a !== "object" || typeof b !== "object") return false;
37
+
38
+ // 数组比较
39
+ const isArrayA = Array.isArray(a);
40
+ const isArrayB = Array.isArray(b);
41
+ if (isArrayA || isArrayB) {
42
+ if (!isArrayA || !isArrayB) return false;
43
+ if (a.length !== b.length) return false;
44
+ for (let i = 0; i < a.length; i++) {
45
+ if (!deepEqual(a[i], b[i])) return false;
46
+ }
47
+ return true;
48
+ }
49
+
50
+ // 普通对象比较
51
+ const keysA = Object.keys(a);
52
+ const keysB = Object.keys(b);
53
+ if (keysA.length !== keysB.length) return false;
54
+
55
+ for (const key of keysA) {
56
+ if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
57
+ if (!deepEqual(a[key], b[key])) return false;
58
+ }
59
+
60
+ return true;
61
+ };
62
+
63
+ /**
64
+ * 比较两个 Slate 内容是否相同
65
+ * @param newContent 新内容
66
+ * @param oldContent 旧内容
67
+ * @returns {boolean} true 如果内容不同,false 如果内容相同
68
+ */
69
+ export const compareSlateContent = (
70
+ newContent: EditorContent | null,
71
+ oldContent: EditorContent | null
72
+ ): boolean => {
73
+ // 快速引用检查
74
+ if (newContent === oldContent) return false; // 内容相同,未发生变化
75
+
76
+ // 空值检查
77
+ if (!newContent || !oldContent) return true; // 内容不同
78
+
79
+ // 长度检查 (作为另一层快速检查)
80
+ if (newContent.length !== oldContent.length) return true; // 内容不同
81
+
82
+ // 使用原生 deepEqual 进行深度比较
83
+ // deepEqual 返回 true 表示内容相同,所以需要取反
84
+ return !deepEqual(newContent, oldContent);
85
+ };
86
+
87
+ /**
88
+ * 从 Slate 数据中提取页面标题
89
+ * @param slateData Slate 编辑器内容数据
90
+ * @returns {string} 提取的标题或默认值 "新页面"
91
+ */
92
+ export const extractTitleFromSlate = (slateData: EditorContent): string => {
93
+ if (!Array.isArray(slateData) || slateData.length === 0) return "新页面";
94
+
95
+ // 优先查找 heading-one 元素作为标题
96
+ const titleNode = slateData.find((node) => node.type === "heading-one");
97
+
98
+ if (titleNode) {
99
+ // 使用 Slate 内置的 Node.string 工具,可靠地提取所有文本,即使标题中有格式
100
+ const text = Node.string(titleNode).trim();
101
+ if (text) {
102
+ return text;
103
+ }
104
+ }
105
+
106
+ // 回退到查找第一个包含非空文本的块元素
107
+ for (const node of slateData) {
108
+ const text = Node.string(node).trim();
109
+ if (text) {
110
+ return text.length > 30 ? `${text.substring(0, 30)}...` : text;
111
+ }
112
+ }
113
+
114
+ return "新页面";
115
+ };
116
+
117
+ export const splitSlateTitleAndBody = (
118
+ slateData: EditorContent | null | undefined,
119
+ explicitTitle?: string | null
120
+ ): { title: string; body: EditorContent } => {
121
+ const content = ensureEditorContent(slateData);
122
+ const firstNode = content[0];
123
+ const normalizedExplicitTitle = explicitTitle?.trim() || "";
124
+ const firstNonEmptyText = content
125
+ .map((node) => Node.string(node).trim())
126
+ .find(Boolean);
127
+
128
+ if (firstNode?.type === "heading-one") {
129
+ const firstText = Node.string(firstNode).trim();
130
+ const shouldTreatAsTitle =
131
+ !!firstText &&
132
+ (!normalizedExplicitTitle || normalizedExplicitTitle === firstText);
133
+
134
+ if (shouldTreatAsTitle) {
135
+ const body = content.slice(1);
136
+ return {
137
+ title: firstText,
138
+ body: ensureEditorContent(body),
139
+ };
140
+ }
141
+ }
142
+
143
+ return {
144
+ title: normalizedExplicitTitle || firstNonEmptyText || "",
145
+ body: content,
146
+ };
147
+ };
148
+
149
+ /**
150
+ * 从 Slate 数据中提取所有提及 (Mention) 的资源 ID
151
+ * @param slateData Slate 编辑器内容数据
152
+ * @returns {string[]} 去重后的资源 ID 列表
153
+ */
154
+ // Return only tool IDs to maintain backward compatibility with 'tools' DB field
155
+ export const extractMentionsFromSlate = (slateData: EditorContent): string[] => {
156
+ const tools = new Set<string>();
157
+
158
+ const traverse = (nodes: any[]) => {
159
+ for (const node of nodes) {
160
+ if (node.type === "mention" && node.resourceId) {
161
+ // Only collect if it's explicitly a tool, OR if resourceType is missing (legacy assumption?)
162
+ // Better to be strict: only tools.
163
+ if (node.resourceType === "tool") {
164
+ tools.add(node.resourceId);
165
+ }
166
+ }
167
+ if (node.children && Array.isArray(node.children)) {
168
+ traverse(node.children);
169
+ }
170
+ }
171
+ };
172
+
173
+ if (Array.isArray(slateData)) {
174
+ traverse(slateData);
175
+ }
176
+
177
+ return Array.from(tools);
178
+ };
179
+
180
+ export interface CategorizedMentions {
181
+ tools: string[];
182
+ pages: string[];
183
+ agents: string[];
184
+ spaces: string[];
185
+ }
186
+
187
+ /**
188
+ * Extract categorized mentions for Context assembly
189
+ */
190
+ export const extractCategorizedMentions = (slateData: EditorContent): CategorizedMentions => {
191
+ const result: CategorizedMentions = {
192
+ tools: [],
193
+ pages: [],
194
+ agents: [],
195
+ spaces: []
196
+ };
197
+
198
+ const traverse = (nodes: any[]) => {
199
+ for (const node of nodes) {
200
+ if (node.type === "mention" && node.resourceId && node.resourceType) {
201
+ switch (node.resourceType) {
202
+ case "tool":
203
+ result.tools.push(node.resourceId);
204
+ break;
205
+ case "page":
206
+ result.pages.push(node.resourceId);
207
+ break;
208
+ case "agent":
209
+ result.agents.push(node.resourceId);
210
+ break;
211
+ case "space":
212
+ result.spaces.push(node.resourceId);
213
+ break;
214
+ }
215
+ }
216
+ if (node.children && Array.isArray(node.children)) {
217
+ traverse(node.children);
218
+ }
219
+ }
220
+ };
221
+
222
+ if (Array.isArray(slateData)) {
223
+ traverse(slateData);
224
+ }
225
+
226
+ // Deduplicate
227
+ result.tools = [...new Set(result.tools)];
228
+ result.pages = [...new Set(result.pages)];
229
+ result.agents = [...new Set(result.agents)];
230
+ result.spaces = [...new Set(result.spaces)];
231
+
232
+ return result;
233
+ };
@@ -0,0 +1,193 @@
1
+ // app/space/addSpaceAction.ts
2
+
3
+ import { SpaceMemberWithSpaceInfo } from "../../app/types";
4
+ import {
5
+ MemberRole,
6
+ SpaceVisibility,
7
+ SpaceData,
8
+ SpaceContent,
9
+ } from "../../app/types";
10
+ import { selectUserId } from "../../auth/authSlice";
11
+ import { DataType } from "../types";
12
+ import { fetchUserData } from "../../database/client/fetchUserData";
13
+ import { ulid } from "ulid";
14
+ import { patch, write } from "../../database/dbSlice";
15
+ import { createSpaceKey } from "../space/spaceKeys";
16
+ import { CreateSpaceRequest, selectAllMemberSpaces } from "./spaceSlice";
17
+ import type { AppDispatch, RootState } from "../../app/store";
18
+
19
+ //
20
+ // Helper: 一次性读取本地用户数据
21
+ //
22
+ interface BaseItem {
23
+ id: string;
24
+ type: DataType;
25
+ userId: string;
26
+ createdAt?: string | number;
27
+ updatedAt?: string | number;
28
+ [key: string]: any;
29
+ }
30
+
31
+ interface GetUserDataOptions {
32
+ types: DataType | DataType[];
33
+ userId: string;
34
+ limit: number;
35
+ isLoggedIn?: boolean;
36
+ currentUserId?: string;
37
+ db: any;
38
+ }
39
+
40
+ async function getUserDataOnce({
41
+ types,
42
+ userId,
43
+ limit,
44
+ isLoggedIn = false,
45
+ currentUserId,
46
+ db,
47
+ }: GetUserDataOptions): Promise<{
48
+ data: BaseItem[];
49
+ error?: Error;
50
+ }> {
51
+ try {
52
+ const typeArray = Array.isArray(types) ? types : [types];
53
+ const effectiveUserId =
54
+ userId === "local" && isLoggedIn && currentUserId
55
+ ? currentUserId
56
+ : userId;
57
+ const localResults = await fetchUserData(db, typeArray, effectiveUserId);
58
+ const localData = Object.values(localResults).flat();
59
+ return { data: localData };
60
+ } catch (err) {
61
+ const error =
62
+ err instanceof Error ? err : new Error("Unknown error occurred");
63
+ return { data: [], error };
64
+ }
65
+ }
66
+
67
+ const targetTypes: DataType[] = [DataType.DIALOG, DataType.DOC];
68
+
69
+ const getCurrentPathForLog = () =>
70
+ typeof window !== "undefined" &&
71
+ typeof window.location?.pathname === "string"
72
+ ? window.location.pathname
73
+ : undefined;
74
+
75
+ /**
76
+ * 新增 Space,包括首次迁移旧侧边栏数据到 Space.contents
77
+ */
78
+ export const addSpaceAction = async (
79
+ input: CreateSpaceRequest,
80
+ thunkAPI: { dispatch: AppDispatch; getState: () => RootState; extra: { db: any } }
81
+ ): Promise<SpaceMemberWithSpaceInfo> => {
82
+ const {
83
+ name,
84
+ description = "",
85
+ visibility = SpaceVisibility.PRIVATE,
86
+ } = input;
87
+ const { dispatch, getState, extra } = thunkAPI;
88
+ const state = getState();
89
+ const userId = selectUserId(state);
90
+ if (!userId) throw new Error("User is not logged in.");
91
+
92
+ const spaceId = ulid();
93
+ const now = Date.now();
94
+ const nowISO = new Date(now).toISOString();
95
+
96
+ // 基本 Space 数据
97
+ const spaceData: SpaceData = {
98
+ id: spaceId,
99
+ name,
100
+ description,
101
+ ownerId: userId,
102
+ visibility,
103
+ members: [userId],
104
+ categories: {},
105
+ contents: {},
106
+ createdAt: now,
107
+ updatedAt: now,
108
+ type: DataType.SPACE,
109
+ };
110
+
111
+ const spaces = selectAllMemberSpaces(state);
112
+ const hasSpace = spaces.length > 0;
113
+
114
+ console.info("[space/create] addSpaceAction", {
115
+ userId,
116
+ name,
117
+ visibility,
118
+ memberSpaceCount: spaces.length,
119
+ currentPath: getCurrentPathForLog(),
120
+ });
121
+
122
+ if (!hasSpace) {
123
+ // 首次创建 Space 时尝试迁移旧侧边栏数据
124
+ const { data: oldItems = [] } = await getUserDataOnce({
125
+ types: targetTypes,
126
+ userId,
127
+ limit: 100,
128
+ db: extra.db,
129
+ });
130
+
131
+ const hasOldSideData = oldItems.length > 0;
132
+ if (hasOldSideData) {
133
+ const contents: Record<string, SpaceContent> = {};
134
+ const updatePromises: Promise<any>[] = [];
135
+
136
+ for (const item of oldItems) {
137
+ if (!item.id || !item.type) continue;
138
+ const stableContentKey =
139
+ typeof item.dbKey === "string" && item.dbKey.trim()
140
+ ? item.dbKey
141
+ : item.id;
142
+ contents[stableContentKey] = {
143
+ title: item.title || "",
144
+ type: item.type,
145
+ contentKey: stableContentKey,
146
+ categoryId: "",
147
+ pinned: false,
148
+ createdAt: item.createdAt ?? now,
149
+ updatedAt: item.updatedAt ?? now,
150
+ order: item.order,
151
+ };
152
+ if (item.dbKey) {
153
+ updatePromises.push(
154
+ dispatch(
155
+ patch({
156
+ dbKey: item.dbKey,
157
+ changes: { spaceId, updatedAt: now },
158
+ })
159
+ )
160
+ );
161
+ }
162
+ }
163
+ spaceData.contents = contents;
164
+ await Promise.all(updatePromises);
165
+ }
166
+ }
167
+
168
+ // 写入 Space
169
+ const spaceKey = createSpaceKey.space(spaceId);
170
+ await dispatch(write({ data: spaceData, customKey: spaceKey })).unwrap();
171
+
172
+ // 写入 SpaceMember
173
+ const spaceMemberKey = createSpaceKey.member(userId, spaceId);
174
+ const spaceMemberData: SpaceMemberWithSpaceInfo = {
175
+ dbKey: spaceMemberKey,
176
+ type: DataType.SPACE,
177
+ userId,
178
+ role: MemberRole.OWNER,
179
+ joinedAt: now,
180
+ spaceId,
181
+ spaceName: name,
182
+ ownerId: userId,
183
+ visibility,
184
+ createdAt: nowISO,
185
+ updatedAt: nowISO,
186
+ };
187
+
188
+ await dispatch(
189
+ write({ data: spaceMemberData, customKey: spaceMemberKey })
190
+ ).unwrap();
191
+
192
+ return spaceMemberData;
193
+ };