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.
- package/README.md +4 -4
- package/agent-runtime/dialogWritePlan.ts +39 -0
- package/agent-runtime/hostAdapter.ts +4 -0
- package/agent-runtime/hybridRecordStore.ts +5 -3
- package/agent-runtime/index.ts +15 -0
- package/agent-runtime/localLoop.ts +87 -7
- package/agent-runtime/localToolPolicy.ts +2 -13
- package/agent-runtime/localWorkspaceTools.ts +42 -110
- package/agent-runtime/runtimeToolPolicy.ts +2 -11
- package/agent-runtime/runtimeToolSurface.ts +198 -0
- package/agent-runtime/types.ts +1 -0
- package/agentAliases.ts +2 -1
- package/agentRunCommand.ts +10 -32
- package/agentRuntimeLocal.ts +1 -0
- package/ai/agent/_executeModel.ts +146 -0
- package/ai/agent/agentSlice.ts +556 -1
- package/ai/agent/appWorkingMemory.ts +126 -0
- package/ai/agent/buildEditingContext.ts +378 -0
- package/ai/agent/buildSystemPrompt.ts +585 -0
- package/ai/agent/canvasEditingContext.ts +49 -0
- package/ai/agent/cleanAgentMessages.ts +140 -0
- package/ai/agent/cliChatClient.ts +153 -0
- package/ai/agent/cliExecutor.ts +314 -40
- package/ai/agent/contextCompiler.ts +107 -0
- package/ai/agent/contextLayerContract.ts +44 -0
- package/ai/agent/createAgentSchema.ts +272 -0
- package/ai/agent/currentTimeContext.ts +65 -0
- package/ai/agent/executeToolCall.ts +58 -0
- package/ai/agent/fetchAgentContexts.ts +42 -0
- package/ai/agent/generatePrompt.ts +3 -0
- package/ai/agent/getFullChatContextKeys.ts +168 -0
- package/ai/agent/guidedCreation/capabilities.ts +84 -0
- package/ai/agent/guidedCreation/types.ts +38 -0
- package/ai/agent/isLiveAudioOnlyAgent.ts +26 -0
- package/ai/agent/liveAudioModel.ts +2 -0
- package/ai/agent/pageBuilderHandoffRules.ts +75 -0
- package/ai/agent/persistMessageWithFixedId.ts +37 -0
- package/ai/agent/planSlice.ts +259 -0
- package/ai/agent/referenceUtils.ts +229 -0
- package/ai/agent/runAgentBackground.ts +310 -0
- package/ai/agent/runAgentClientLoop.ts +164 -0
- package/ai/agent/runtimeGuidance.ts +116 -0
- package/ai/agent/serverOrigin.ts +7 -0
- package/ai/agent/startParallelAgentStreams.ts +424 -0
- package/ai/agent/startupProtocol.ts +53 -0
- package/ai/agent/streamAgentChatTurn.ts +2001 -0
- package/ai/agent/streamAgentChatTurnUtils.ts +860 -0
- package/ai/agent/toolFailureGuard.ts +99 -0
- package/ai/agent/types.ts +73 -0
- package/ai/agent/utils/imageOutput.ts +37 -0
- package/ai/agent/utils/publicImageAgentMode.ts +26 -0
- package/ai/ai.locale.ts +1095 -0
- package/ai/chat/accumulateToolCallChunks.ts +126 -0
- package/ai/chat/fetchUtils.ts +143 -0
- package/ai/chat/inlineImageUrlsForCustomProvider.ts +117 -0
- package/ai/chat/parseApiError.ts +67 -0
- package/ai/chat/parseMultilineSSE.ts +95 -0
- package/ai/chat/sendOpenAICompletionsRequest.ts +897 -0
- package/ai/chat/sendOpenAIResponseRequest.ts +720 -0
- package/ai/chat/serverProxyRetry.ts +102 -0
- package/ai/chat/shouldUseServerProxy.ts +18 -0
- package/ai/chat/streamRetry.ts +46 -0
- package/ai/chat/updateTotalUsage.ts +89 -0
- package/ai/context/buildReferenceContext.ts +437 -0
- package/ai/context/retention.ts +165 -0
- package/ai/context/tokenUtils.ts +78 -0
- package/ai/llm/agentCapabilities.ts +74 -0
- package/ai/llm/deepinfra.ts +79 -0
- package/ai/llm/fireworks.ts +68 -0
- package/ai/llm/generateRequestBody.ts +165 -0
- package/ai/llm/getModelContextWindow.ts +93 -0
- package/ai/llm/getPricing.ts +252 -0
- package/ai/llm/imagePricing.ts +66 -0
- package/ai/llm/isResponseAPIModel.ts +13 -0
- package/ai/llm/kimi.ts +23 -0
- package/ai/llm/mimo.ts +99 -0
- package/ai/llm/mistral.ts +21 -0
- package/ai/llm/models.ts +45 -0
- package/ai/llm/openrouterModels.ts +6 -0
- package/ai/llm/providers.ts +313 -0
- package/ai/llm/reasoningModels.ts +27 -0
- package/ai/llm/types.ts +82 -0
- package/ai/llm/usageRequestOptions.ts +59 -0
- package/ai/memory/queryShared.ts +161 -0
- package/ai/memory/recentRelationshipRecap.ts +247 -0
- package/ai/memory/remember.ts +167 -0
- package/ai/memory/store.ts +20 -0
- package/ai/memory/storeShared.ts +76 -0
- package/ai/memory/types.ts +46 -0
- package/ai/memory/understanding.ts +349 -0
- package/ai/memory/understandingGreeting.ts +264 -0
- package/ai/policy/personalizationDialog.ts +333 -0
- package/ai/policy/runtimePolicy.ts +454 -0
- package/ai/policy/selfUpdateFields.ts +48 -0
- package/ai/policy/types.ts +64 -0
- package/ai/skills/referenceRuntime.ts +274 -0
- package/ai/skills/skillDiagnostics.ts +251 -0
- package/ai/skills/skillDocBuilder.ts +139 -0
- package/ai/skills/skillSummaryMarker.ts +26 -0
- package/ai/token/calculatePrice.ts +576 -0
- package/ai/token/missingUsageEstimate.ts +42 -0
- package/ai/token/normalizeUsage.ts +124 -0
- package/ai/token/openaiImageGenerationUsage.ts +56 -0
- package/ai/token/prepareTokenUsageData.ts +93 -0
- package/ai/token/resolveBillingTarget.ts +52 -0
- package/ai/token/saveTokenRecord.ts +53 -0
- package/ai/token/types.ts +103 -0
- package/ai/tools/agent/agentTools.ts +235 -0
- package/ai/tools/agent/agentUpdateShared.ts +311 -0
- package/ai/tools/agent/callAgentTool.ts +139 -0
- package/ai/tools/agent/createAgentTool.ts +512 -0
- package/ai/tools/agent/createDialogTool.ts +69 -0
- package/ai/tools/agent/createSkillAgentTool.ts +62 -0
- package/ai/tools/agent/parallelBudget.ts +221 -0
- package/ai/tools/agent/prepareAgentDraftTool.ts +159 -0
- package/ai/tools/agent/presets/appBuilderPreset.ts +154 -0
- package/ai/tools/agent/runLlmTool.ts +96 -0
- package/ai/tools/agent/runStreamingAgentTool.ts +73 -0
- package/ai/tools/agent/skillAgentArgs.ts +106 -0
- package/ai/tools/agent/startAgentDialogTool.ts +53 -0
- package/ai/tools/agent/streamParallelAgentsTool.ts +123 -0
- package/ai/tools/agent/updateAgentTool.ts +96 -0
- package/ai/tools/agent/updateSelfTool.ts +113 -0
- package/ai/tools/amazonProductScraperTool.ts +86 -0
- package/ai/tools/apifyActorClient.ts +45 -0
- package/ai/tools/appEditGuard.ts +372 -0
- package/ai/tools/appReadSnapshot.ts +153 -0
- package/ai/tools/appTools.ts +1549 -0
- package/ai/tools/applyEditTool.ts +259 -0
- package/ai/tools/applyLineEditsTool.ts +315 -0
- package/ai/tools/browserTools/click.ts +33 -0
- package/ai/tools/browserTools/closeSession.ts +29 -0
- package/ai/tools/browserTools/common.ts +27 -0
- package/ai/tools/browserTools/openSession.ts +48 -0
- package/ai/tools/browserTools/readContent.ts +38 -0
- package/ai/tools/browserTools/selectOption.ts +46 -0
- package/ai/tools/browserTools/typeText.ts +42 -0
- package/ai/tools/category/createCategoryTool.ts +66 -0
- package/ai/tools/category/queryContentsByCategoryTool.ts +69 -0
- package/ai/tools/category/updateContentCategoryTool.ts +75 -0
- package/ai/tools/cfBrowserTools.ts +319 -0
- package/ai/tools/cfSpeechToTextTool.ts +49 -0
- package/ai/tools/checkEnvTool.ts +102 -0
- package/ai/tools/cloudflareCrawlTool.ts +289 -0
- package/ai/tools/codeSearchTool.ts +123 -0
- package/ai/tools/codeTools.ts +101 -0
- package/ai/tools/convertMarxistsBookTool.ts +103 -0
- package/ai/tools/createDocTool.ts +132 -0
- package/ai/tools/createSkillDocTool.ts +155 -0
- package/ai/tools/createWorkflowTool.ts +154 -0
- package/ai/tools/delayTool.ts +31 -0
- package/ai/tools/deleteSpacesTool.ts +325 -0
- package/ai/tools/deleteSpacesToolModel.ts +159 -0
- package/ai/tools/devReloadUtils.ts +29 -0
- package/ai/tools/dialogMessageSearch.ts +137 -0
- package/ai/tools/doctorSkillTool.ts +72 -0
- package/ai/tools/ecommerceScraperTool.ts +86 -0
- package/ai/tools/emailTools.ts +549 -0
- package/ai/tools/evalSkillTool.ts +92 -0
- package/ai/tools/exaSearchTool.ts +63 -0
- package/ai/tools/execShellTool.ts +266 -0
- package/ai/tools/executeSqlTool.ts +192 -0
- package/ai/tools/fetchWebpageSupport.ts +333 -0
- package/ai/tools/fetchWebpageTool.ts +97 -0
- package/ai/tools/geminiImagePreviewTool.ts +386 -0
- package/ai/tools/generateDocxTool.ts +215 -0
- package/ai/tools/googleSearchScraperTool.ts +106 -0
- package/ai/tools/importDataTool.ts +133 -0
- package/ai/tools/importSkillTool.ts +162 -0
- package/ai/tools/index.ts +2308 -0
- package/ai/tools/jdProductScraperTool.ts +821 -0
- package/ai/tools/listUserSpacesTool.ts +113 -0
- package/ai/tools/localFilesTool.ts +276 -0
- package/ai/tools/marxistsOfflineBook.ts +253 -0
- package/ai/tools/modelUsageTools.ts +206 -0
- package/ai/tools/noloWorkspaceReadTools.ts +467 -0
- package/ai/tools/olmOcrTool.ts +33 -0
- package/ai/tools/openaiImageTool.ts +267 -0
- package/ai/tools/prepareTools.ts +23 -0
- package/ai/tools/readDocTool.ts +88 -0
- package/ai/tools/readFileTool.ts +214 -0
- package/ai/tools/readTool.ts +194 -0
- package/ai/tools/readXPostTool.ts +229 -0
- package/ai/tools/readXhsProfileTool.ts +627 -0
- package/ai/tools/rememberMemoryTool.ts +84 -0
- package/ai/tools/remotionVideoTool.ts +151 -0
- package/ai/tools/searchDialogMessagesTool.ts +222 -0
- package/ai/tools/searchWorkspaceTool.ts +259 -0
- package/ai/tools/skillFollowup.ts +86 -0
- package/ai/tools/surfWeatherTool.ts +169 -0
- package/ai/tools/table/addTableRowTool.ts +217 -0
- package/ai/tools/table/createTableTool.ts +315 -0
- package/ai/tools/table/rowTools.ts +386 -0
- package/ai/tools/table/schemaTools.ts +244 -0
- package/ai/tools/table/shareTableTool.ts +148 -0
- package/ai/tools/table/toolShared.ts +129 -0
- package/ai/tools/taobaoTmallProductScraperTool.ts +49 -0
- package/ai/tools/toolApiClient.ts +279 -0
- package/ai/tools/toolResultError.ts +42 -0
- package/ai/tools/toolRunSlice.ts +303 -0
- package/ai/tools/toolSchemaCompatibility.ts +53 -0
- package/ai/tools/uiAskChoiceTool.ts +104 -0
- package/ai/tools/updateContentTitleTool.ts +84 -0
- package/ai/tools/updateDocTool.ts +105 -0
- package/ai/tools/updateUserPreferenceProfileTool.ts +153 -0
- package/ai/tools/wereadGatewayTool.ts +152 -0
- package/ai/tools/whisperTool.ts +76 -0
- package/ai/tools/writeFileTool.ts +213 -0
- package/ai/tools/youtubeScraperTool.ts +116 -0
- package/ai/tools/ziweiChartTool.ts +678 -0
- package/ai/types.ts +55 -0
- package/ai/workflow/workflowExecutor.ts +323 -0
- package/ai/workflow/workflowSlice.ts +73 -0
- package/ai/workflow/workflowTypes.ts +106 -0
- package/app/actions/syncAppRecord.ts +73 -0
- package/app/constants/animationSets.ts +21 -0
- package/app/constants/appEditor.ts +99 -0
- package/app/favorite/favoriteSlice.ts +690 -0
- package/app/favorite/type.ts +43 -0
- package/app/hooks/deleteDbKey.ts +233 -0
- package/app/i18n/client.ts +13 -0
- package/app/i18n/i18n.base.ts +14 -0
- package/app/i18n/i18n.config.ts +77 -0
- package/app/i18n/index.ts +15 -0
- package/app/i18n/mapLanguage.ts +11 -0
- package/app/i18n/translations/appBuilder.locale.ts +453 -0
- package/app/i18n/translations/error.locale.ts +246 -0
- package/app/i18n/translations/interface.locale.ts +2174 -0
- package/app/i18n/translations/pricing.locale.ts +397 -0
- package/app/i18n/translations/privacy.locale.ts +168 -0
- package/app/i18n/translations/seo.locale.ts +129 -0
- package/app/i18n/translations/terms.locale.ts +124 -0
- package/app/i18n/types.ts +6 -0
- package/app/notifications/model.ts +77 -0
- package/app/notifications/notificationSlice.ts +141 -0
- package/app/reducer.ts +36 -0
- package/app/settings/dbActionThunks.ts +34 -0
- package/app/settings/defaultSpacePreference.ts +87 -0
- package/app/settings/settingSlice.tsx +1212 -0
- package/app/settings/settingsRecord.ts +8 -0
- package/app/stateViews/runtime.ts +90 -0
- package/app/store.ts +55 -0
- package/app/theme/colors.ts +280 -0
- package/app/theme/fontPreference.ts +77 -0
- package/app/theme/theme.config.ts +120 -0
- package/app/theme/themeModeBootstrap.ts +123 -0
- package/app/types/appSummary.ts +114 -0
- package/app/types.ts +358 -0
- package/app/utils/appKeys.ts +55 -0
- package/app/utils/async.ts +28 -0
- package/app/utils/desktopAgentRuntimeTurnClient.ts +73 -0
- package/app/utils/env.ts +17 -0
- package/app/utils/fileUtils.ts +229 -0
- package/app/utils/imageUtils.ts +274 -0
- package/app/utils/myContentItems.ts +289 -0
- package/app/utils/retryAfter.ts +36 -0
- package/app/utils/retryFetch.ts +61 -0
- package/app/utils/toast.ts +3 -0
- package/auth/action/signUpAction.ts +227 -0
- package/auth/adminPermissions.ts +18 -0
- package/auth/authSlice.ts +531 -0
- package/auth/client/loginRequest.ts +14 -0
- package/auth/resetAuthScopedClientState.ts +27 -0
- package/auth/routes.ts +178 -0
- package/auth/token.ts +63 -0
- package/auth/types.ts +40 -0
- package/chat/chat.locale.ts +813 -0
- package/chat/dialog/actions/addCybotAction.ts +52 -0
- package/chat/dialog/actions/addReferenceKeysAction.ts +62 -0
- package/chat/dialog/actions/builtinDialogLlm.ts +35 -0
- package/chat/dialog/actions/cleanupCliSession.ts +40 -0
- package/chat/dialog/actions/createDialogAction.ts +379 -0
- package/chat/dialog/actions/createScheduledTaskAction.ts +78 -0
- package/chat/dialog/actions/handleSendMessageAction.ts +197 -0
- package/chat/dialog/actions/handleSendMessageResolver.ts +27 -0
- package/chat/dialog/actions/removeCybotAction.ts +6 -0
- package/chat/dialog/actions/removeDialogAgentAction.ts +44 -0
- package/chat/dialog/actions/replacePrimaryCybotAction.ts +6 -0
- package/chat/dialog/actions/setPrimaryDialogAgentAction.ts +52 -0
- package/chat/dialog/actions/updateDialogSummaryAction.ts +430 -0
- package/chat/dialog/actions/updateDialogTitleAction.ts +151 -0
- package/chat/dialog/actions/updateDialogTitlePolicy.ts +30 -0
- package/chat/dialog/actions/updateTokensAction.ts +233 -0
- package/chat/dialog/dialogAgents.ts +72 -0
- package/chat/dialog/dialogSlice.ts +872 -0
- package/chat/dialog/dialogTitle.ts +81 -0
- package/chat/dialog/dialogTokenStats.ts +12 -0
- package/chat/dialog/dialogUrl.ts +6 -0
- package/chat/dialog/goal.ts +108 -0
- package/chat/dialog/objectAssistantRegistry.ts +286 -0
- package/chat/dialog/schedule.ts +17 -0
- package/chat/messages/fetchAndCacheMessages.ts +119 -0
- package/chat/messages/fetchConvMsgs.ts +51 -0
- package/chat/messages/fileUrl.ts +13 -0
- package/chat/messages/messageAgent.ts +8 -0
- package/chat/messages/messageContent.ts +199 -0
- package/chat/messages/messageContract.ts +88 -0
- package/chat/messages/messageSlice.ts +1367 -0
- package/chat/messages/toolThunks.ts +625 -0
- package/cli/agentAliases.ts +2 -1
- package/cli/agentRunCommand.ts +10 -32
- package/cli/agentRuntimeLocal.ts +1 -0
- package/cli/client/agentRun.ts +67 -95
- package/cli/client/localRuntimeAdapter.ts +323 -54
- package/cli/commandRegistry.ts +2 -2
- package/cli/machineWsRunDispatch.ts +51 -6
- package/cli/offlineMarxistsAgentCommand.ts +6 -4
- package/client/agentConfigResolver.test.ts +2 -2
- package/client/agentRun.test.ts +175 -57
- package/client/agentRun.ts +67 -95
- package/client/localRuntimeAdapter.test.ts +682 -37
- package/client/localRuntimeAdapter.ts +323 -54
- package/client/localRuntimeDryRun.test.ts +23 -9
- package/client/localToolPolicy.test.ts +4 -4
- package/commandRegistry.ts +2 -2
- package/core/builtinAgents.ts +209 -0
- package/core/config.ts +15 -0
- package/core/crypto.ts +51 -0
- package/core/generateKeyPairFromSeedV1.ts +15 -0
- package/core/generateMainKey.ts +22 -0
- package/core/init.ts +41 -0
- package/core/localOrigins.ts +8 -0
- package/core/password.ts +13 -0
- package/core/prefix.ts +23 -0
- package/create/editor/transforms/fromMarkdown/index.ts +260 -0
- package/create/editor/transforms/fromMarkdown/inline.ts +285 -0
- package/create/editor/transforms/fromMarkdown/table.ts +130 -0
- package/create/editor/transforms/markdownToSlate.ts +24 -0
- package/create/editor/transforms/slateToRenderMarkdown.ts +218 -0
- package/create/editor/transforms/slateToSimplifiedMarkdown.ts +224 -0
- package/create/editor/transforms/slateToText.ts +33 -0
- package/create/editor/utils/slateUtils.ts +233 -0
- package/create/space/addSpaceAction.ts +193 -0
- package/create/space/category/categoryActions.ts +427 -0
- package/create/space/changeSpaceAction.ts +36 -0
- package/create/space/constants.ts +8 -0
- package/create/space/content/addContentAction.ts +116 -0
- package/create/space/content/contentThunks.ts +90 -0
- package/create/space/content/deleteContentFromSpaceAction.ts +187 -0
- package/create/space/content/deleteMultipleContentAction.ts +112 -0
- package/create/space/content/moveContentAction.ts +285 -0
- package/create/space/content/updateContentCategoryAction.ts +154 -0
- package/create/space/content/updateContentTitleAction.ts +151 -0
- package/create/space/content/uploadAndAddFileToSpaceAction.ts +98 -0
- package/create/space/contentKeyUtils.ts +117 -0
- package/create/space/deleteSpaceAction.ts +276 -0
- package/create/space/fetchSpaceAction.ts +70 -0
- package/create/space/fetchSpaceSidebarStateAction.ts +26 -0
- package/create/space/loadDefaultSpaceAction.ts +57 -0
- package/create/space/member/addMemberAction.ts +79 -0
- package/create/space/member/fetchUserSpaceMembershipsAction.ts +386 -0
- package/create/space/member/memberThunks.ts +47 -0
- package/create/space/member/removeMemberAction.ts +67 -0
- package/create/space/resolvePreferredSpaceId.ts +113 -0
- package/create/space/sidebarVisibleTypes.ts +241 -0
- package/create/space/space.locale.ts +1087 -0
- package/create/space/spaceAccess.ts +182 -0
- package/create/space/spaceCollapsedState.ts +54 -0
- package/create/space/spaceKeys.ts +65 -0
- package/create/space/spaceSlice.ts +328 -0
- package/create/space/spaceThunks.ts +410 -0
- package/create/space/types.ts +27 -0
- package/create/space/updateSpaceAction.ts +107 -0
- package/create/space/utils/permissions.ts +47 -0
- package/create/types.ts +21 -0
- package/database/actions/agentReadResolution.ts +33 -0
- package/database/actions/common.ts +243 -0
- package/database/actions/deleteFile.ts +40 -0
- package/database/actions/fileContent.ts +125 -0
- package/database/actions/patch.ts +155 -0
- package/database/actions/read.ts +358 -0
- package/database/actions/readAndWait.ts +260 -0
- package/database/actions/readRequestManager.ts +120 -0
- package/database/actions/readResolution.ts +125 -0
- package/database/actions/remove.ts +94 -0
- package/database/actions/replication.ts +477 -0
- package/database/actions/upload.ts +186 -0
- package/database/actions/upsert.ts +56 -0
- package/database/actions/write.ts +146 -0
- package/database/authority/ownerKey.ts +80 -0
- package/database/authority/recordAuthority.ts +67 -0
- package/database/authority/userAuthorityRegistry.ts +54 -0
- package/database/client/fetchUserData.ts +61 -0
- package/database/dbActionThunks.ts +1 -0
- package/database/dbSlice.ts +149 -0
- package/database/fileRing.ts +51 -0
- package/database/fileStorage.ts +232 -0
- package/database/fileUrl.ts +34 -0
- package/database/keys.ts +767 -0
- package/database/queryPrefixes.ts +14 -0
- package/database/requests.ts +443 -0
- package/database/runtimeServerContext.ts +54 -0
- package/database/server/levelAuthorityStore.ts +20 -1
- package/database/tenantPlacement.ts +57 -0
- package/database/userPreferenceRegister.ts +131 -0
- package/database/utils/ulid.ts +1 -0
- package/integrations/anthropic/anthropicModels.ts +47 -0
- package/integrations/deepseek/models.ts +37 -0
- package/integrations/google/models.ts +341 -0
- package/integrations/openai/chatCompletionStreamMode.ts +10 -0
- package/integrations/openai/filterAndCleanMessages.ts +284 -0
- package/integrations/openai/flexTier.ts +102 -0
- package/integrations/openai/generateOpenAIRequestBody.ts +274 -0
- package/integrations/openai/generateResponseRequestBody.ts +77 -0
- package/integrations/openai/models.ts +271 -0
- package/integrations/openai/providerBodyCompatibility.ts +23 -0
- package/integrations/openai/responsesHelpers.ts +297 -0
- package/integrations/x-reader/types.ts +109 -0
- package/integrations/xai/models.ts +13 -0
- package/integrations/xhs-reader/analyze/profileAnalyzer.ts +205 -0
- package/integrations/xhs-reader/backends/playwrightProfileCollector.ts +624 -0
- package/integrations/xhs-reader/bridge/readXhsProfileWithBridge.ts +227 -0
- package/integrations/xhs-reader/client/xhsWebApiClient.ts +229 -0
- package/integrations/xhs-reader/normalize.ts +390 -0
- package/integrations/xhs-reader/orchestrator.ts +178 -0
- package/integrations/xhs-reader/redaction.ts +68 -0
- package/integrations/xhs-reader/types.ts +244 -0
- package/integrations/xhs-reader/url.ts +57 -0
- package/machineWsRunDispatch.ts +51 -6
- package/offlineMarxistsAgentCommand.ts +6 -4
- package/package.json +430 -3
- package/render/page/createPageAction.ts +183 -0
- package/render/page/docSlice.ts +468 -0
- package/render/page/types.ts +17 -0
- package/render/table/createTableAction.ts +270 -0
- package/render/table/deleteTableAction.ts +193 -0
- package/render/table/fetchAndCacheTableRows.ts +174 -0
- package/render/table/tableSlice.ts +1106 -0
- package/render/table/toolValueUtils.ts +363 -0
- package/render/table/types.ts +252 -0
- package/render/table/utils/tableSerialization.ts +50 -0
- package/server/handlers/agentRun/types.ts +104 -0
- package/share/action.ts +225 -0
- package/share/helpers.ts +302 -0
- package/share/keys.ts +243 -0
- package/share/publicSharePolicy.ts +27 -0
- package/share/shareSlice.ts +53 -0
- package/share/types.ts +100 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { selectUserId } from "../../auth/authSlice";
|
|
2
|
+
import { createSpaceKey } from "../space/spaceKeys";
|
|
3
|
+
import { read, remove, patch } from "../../database/dbSlice";
|
|
4
|
+
import { deleteDbKey } from "../../app/hooks/deleteDbKey";
|
|
5
|
+
import {
|
|
6
|
+
persistDefaultSpacePreference,
|
|
7
|
+
readDefaultSpaceIdPreference,
|
|
8
|
+
} from "../../app/settings/defaultSpacePreference";
|
|
9
|
+
import {
|
|
10
|
+
isAgentKey,
|
|
11
|
+
isAppKey,
|
|
12
|
+
isDialogKey,
|
|
13
|
+
isFileKey,
|
|
14
|
+
isPageKey,
|
|
15
|
+
isTableMetaKey,
|
|
16
|
+
splitKey,
|
|
17
|
+
} from "../../database/keys";
|
|
18
|
+
import { normalizeSpaceId } from "./spaceKeys";
|
|
19
|
+
|
|
20
|
+
// 定义ThunkAPI的通用类型(根据redux-thunk的用法)
|
|
21
|
+
interface ThunkAPI {
|
|
22
|
+
dispatch: (action: any) => any;
|
|
23
|
+
getState: () => any; // 如果有RootState类型,可替换为RootState
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type DeleteSpaceStrategy =
|
|
27
|
+
| "delete-space-only"
|
|
28
|
+
| "move-owned-to-all"
|
|
29
|
+
| "delete-owned-content";
|
|
30
|
+
|
|
31
|
+
type DeleteSpaceArgs =
|
|
32
|
+
| string
|
|
33
|
+
| {
|
|
34
|
+
spaceId: string;
|
|
35
|
+
strategy?: DeleteSpaceStrategy;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const getCurrentUserId = (state: any): string => selectUserId(state);
|
|
39
|
+
|
|
40
|
+
const fetchSpaceData = async (
|
|
41
|
+
spaceId: string,
|
|
42
|
+
dispatch: ThunkAPI["dispatch"]
|
|
43
|
+
) => {
|
|
44
|
+
const spaceKey = createSpaceKey.space(spaceId);
|
|
45
|
+
try {
|
|
46
|
+
return await dispatch(read({
|
|
47
|
+
dbKey: spaceKey
|
|
48
|
+
})).unwrap();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.warn(`Failed to read space ${spaceId}:`, error);
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const checkOwnerPermission = (spaceData: any | undefined, userId: string) => {
|
|
56
|
+
if (spaceData && spaceData.ownerId !== userId) {
|
|
57
|
+
throw new Error("Only owner can delete space");
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const deleteSpaceData = async (
|
|
62
|
+
spaceId: string,
|
|
63
|
+
dispatch: ThunkAPI["dispatch"]
|
|
64
|
+
) => {
|
|
65
|
+
const spaceKey = createSpaceKey.space(spaceId);
|
|
66
|
+
try {
|
|
67
|
+
await dispatch(remove(spaceKey)).unwrap();
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.warn(`Failed to delete space ${spaceId}:`, error);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const deleteAllMembers = async (
|
|
74
|
+
spaceData: any | undefined,
|
|
75
|
+
spaceId: string,
|
|
76
|
+
dispatch: ThunkAPI["dispatch"]
|
|
77
|
+
) => {
|
|
78
|
+
if (spaceData?.members) {
|
|
79
|
+
for (const memberId of spaceData.members) {
|
|
80
|
+
const memberKey = createSpaceKey.member(memberId, spaceId);
|
|
81
|
+
await dispatch(remove(memberKey))
|
|
82
|
+
.unwrap()
|
|
83
|
+
.catch((err) =>
|
|
84
|
+
console.warn(
|
|
85
|
+
`Failed to delete member ${memberId} for space ${spaceId}:`,
|
|
86
|
+
err
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const deleteCurrentUserMember = async (
|
|
94
|
+
userId: string,
|
|
95
|
+
spaceId: string,
|
|
96
|
+
dispatch: ThunkAPI["dispatch"]
|
|
97
|
+
) => {
|
|
98
|
+
const currentUserMemberKey = createSpaceKey.member(userId, spaceId);
|
|
99
|
+
await dispatch(remove(currentUserMemberKey))
|
|
100
|
+
.unwrap()
|
|
101
|
+
.catch((err) =>
|
|
102
|
+
console.warn(
|
|
103
|
+
`Failed to delete member key for user ${userId} in space ${spaceId}:`,
|
|
104
|
+
err
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const clearDefaultSpacePreferenceIfNeeded = async (
|
|
110
|
+
userId: string,
|
|
111
|
+
spaceId: string,
|
|
112
|
+
dispatch: ThunkAPI["dispatch"]
|
|
113
|
+
) => {
|
|
114
|
+
const defaultSpaceId = await readDefaultSpaceIdPreference(dispatch, userId);
|
|
115
|
+
if (defaultSpaceId && normalizeSpaceId(defaultSpaceId) === normalizeSpaceId(spaceId)) {
|
|
116
|
+
await persistDefaultSpacePreference(dispatch, userId, null);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const clearDeletedMemberDefaultSpacePreferences = async (
|
|
121
|
+
userIds: string[],
|
|
122
|
+
spaceId: string,
|
|
123
|
+
dispatch: ThunkAPI["dispatch"]
|
|
124
|
+
) => {
|
|
125
|
+
const uniqueUserIds = Array.from(new Set(userIds.filter(Boolean)));
|
|
126
|
+
for (const userId of uniqueUserIds) {
|
|
127
|
+
await clearDefaultSpacePreferenceIfNeeded(userId, spaceId, dispatch);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const resolveDeleteArgs = (
|
|
132
|
+
input: DeleteSpaceArgs
|
|
133
|
+
): { spaceId: string; strategy: DeleteSpaceStrategy } => {
|
|
134
|
+
if (typeof input === "string") {
|
|
135
|
+
return { spaceId: input, strategy: "delete-space-only" };
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
spaceId: input.spaceId,
|
|
139
|
+
strategy: input.strategy ?? "delete-space-only",
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const isOwnedByUser = (entityKey: string, entity: any, userId: string): boolean => {
|
|
144
|
+
if (!entityKey || !userId) return false;
|
|
145
|
+
|
|
146
|
+
const keyParts = splitKey(entityKey);
|
|
147
|
+
const keyedOwner = keyParts[1];
|
|
148
|
+
|
|
149
|
+
if (
|
|
150
|
+
(isDialogKey(entityKey) ||
|
|
151
|
+
isPageKey(entityKey) ||
|
|
152
|
+
isFileKey(entityKey) ||
|
|
153
|
+
isTableMetaKey(entityKey)) &&
|
|
154
|
+
keyedOwner === userId
|
|
155
|
+
) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if ((isAgentKey(entityKey) || isAppKey(entityKey)) && entity?.userId === userId) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (entity?.tenantId === userId || entity?.userId === userId || entity?.ownerId === userId) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return false;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const nextUpdatedAt = (entity: any): string => {
|
|
171
|
+
const source =
|
|
172
|
+
entity?.updatedAt ??
|
|
173
|
+
entity?.updated_at ??
|
|
174
|
+
entity?.createdAt ??
|
|
175
|
+
entity?.created ??
|
|
176
|
+
Date.now();
|
|
177
|
+
const timestamp =
|
|
178
|
+
typeof source === "number" ? source : Date.parse(String(source)) || Date.now();
|
|
179
|
+
return new Date(Math.max(Date.now(), timestamp + 1)).toISOString();
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const listSpaceEntities = async (
|
|
183
|
+
spaceData: any | undefined,
|
|
184
|
+
dispatch: ThunkAPI["dispatch"]
|
|
185
|
+
) => {
|
|
186
|
+
const results: Array<{ entityKey: string; entity: any }> = [];
|
|
187
|
+
const contents = Object.values(spaceData?.contents ?? {}).filter(Boolean) as Array<{
|
|
188
|
+
contentKey?: string;
|
|
189
|
+
}>;
|
|
190
|
+
|
|
191
|
+
for (const item of contents) {
|
|
192
|
+
const entityKey = typeof item.contentKey === "string" ? item.contentKey : "";
|
|
193
|
+
if (!entityKey) continue;
|
|
194
|
+
|
|
195
|
+
let entity: any = null;
|
|
196
|
+
try {
|
|
197
|
+
entity = await dispatch(read({ dbKey: entityKey })).unwrap();
|
|
198
|
+
} catch {
|
|
199
|
+
entity = null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
results.push({ entityKey, entity });
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return results;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const clearEntitySpaceIds = async (
|
|
209
|
+
entities: Array<{ entityKey: string; entity: any }>,
|
|
210
|
+
dispatch: ThunkAPI["dispatch"]
|
|
211
|
+
) => {
|
|
212
|
+
await Promise.all(
|
|
213
|
+
entities
|
|
214
|
+
.filter(({ entity }) => entity && typeof entity === "object")
|
|
215
|
+
.map(({ entityKey, entity }) =>
|
|
216
|
+
dispatch(
|
|
217
|
+
patch({
|
|
218
|
+
dbKey: entityKey,
|
|
219
|
+
changes: {
|
|
220
|
+
spaceId: null,
|
|
221
|
+
updatedAt: nextUpdatedAt(entity),
|
|
222
|
+
},
|
|
223
|
+
})
|
|
224
|
+
).unwrap()
|
|
225
|
+
)
|
|
226
|
+
);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const deleteOwnedEntities = async (
|
|
230
|
+
ownedEntities: Array<{ entityKey: string; entity: any }>,
|
|
231
|
+
dispatch: ThunkAPI["dispatch"]
|
|
232
|
+
) => {
|
|
233
|
+
for (const { entityKey } of ownedEntities) {
|
|
234
|
+
await dispatch(deleteDbKey(entityKey));
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export const deleteSpaceAction = async (
|
|
239
|
+
input: DeleteSpaceArgs,
|
|
240
|
+
thunkAPI: ThunkAPI
|
|
241
|
+
) => {
|
|
242
|
+
const { dispatch, getState } = thunkAPI;
|
|
243
|
+
const { spaceId, strategy } = resolveDeleteArgs(input);
|
|
244
|
+
const userId = getCurrentUserId(getState());
|
|
245
|
+
const spaceData = await fetchSpaceData(spaceId, dispatch);
|
|
246
|
+
|
|
247
|
+
checkOwnerPermission(spaceData, userId);
|
|
248
|
+
|
|
249
|
+
if (spaceData && strategy !== "delete-space-only") {
|
|
250
|
+
const allEntities = await listSpaceEntities(spaceData, dispatch);
|
|
251
|
+
const ownedEntities = allEntities.filter(({ entityKey, entity }) =>
|
|
252
|
+
isOwnedByUser(entityKey, entity, userId)
|
|
253
|
+
);
|
|
254
|
+
const unownedEntities = allEntities.filter(
|
|
255
|
+
({ entityKey, entity }) => !isOwnedByUser(entityKey, entity, userId)
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
if (strategy === "move-owned-to-all") {
|
|
259
|
+
await clearEntitySpaceIds(allEntities, dispatch);
|
|
260
|
+
} else if (strategy === "delete-owned-content") {
|
|
261
|
+
await deleteOwnedEntities(ownedEntities, dispatch);
|
|
262
|
+
await clearEntitySpaceIds(unownedEntities, dispatch);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
await deleteSpaceData(spaceId, dispatch);
|
|
267
|
+
await deleteAllMembers(spaceData, spaceId, dispatch);
|
|
268
|
+
await deleteCurrentUserMember(userId, spaceId, dispatch);
|
|
269
|
+
await clearDeletedMemberDefaultSpacePreferences(
|
|
270
|
+
[userId, ...(Array.isArray(spaceData?.members) ? spaceData.members : [])],
|
|
271
|
+
spaceId,
|
|
272
|
+
dispatch
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
return { spaceId, strategy };
|
|
276
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { SpaceId } from "../space/types";
|
|
2
|
+
import type { SpaceData } from "../../app/types";
|
|
3
|
+
import { createSpaceKey, normalizeSpaceId } from "../space/spaceKeys";
|
|
4
|
+
import {
|
|
5
|
+
fetchAuthoritativeRemoteSpace,
|
|
6
|
+
selectSpaceRemoteAuth,
|
|
7
|
+
} from "../space/spaceAccess";
|
|
8
|
+
|
|
9
|
+
type FetchSpaceInput = SpaceId | { spaceId: SpaceId; fresh?: boolean };
|
|
10
|
+
|
|
11
|
+
export const fetchSpaceAction = async (
|
|
12
|
+
input: FetchSpaceInput,
|
|
13
|
+
thunkAPI: any
|
|
14
|
+
): Promise<{ spaceId: SpaceId; spaceData: SpaceData }> => {
|
|
15
|
+
const rawSpaceId = typeof input === "string" ? input : input?.spaceId;
|
|
16
|
+
const fresh = typeof input === "object" && input !== null ? !!input.fresh : false;
|
|
17
|
+
const { dispatch } = thunkAPI;
|
|
18
|
+
|
|
19
|
+
if (!rawSpaceId) {
|
|
20
|
+
throw new Error("spaceId is required");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Normalize ID for fetching
|
|
24
|
+
const spaceId = normalizeSpaceId(rawSpaceId);
|
|
25
|
+
const spaceKey = createSpaceKey.space(spaceId);
|
|
26
|
+
|
|
27
|
+
if (fresh) {
|
|
28
|
+
const { token, userId, servers } = selectSpaceRemoteAuth(thunkAPI.getState());
|
|
29
|
+
if (token && userId && servers.length > 0) {
|
|
30
|
+
const remoteSpace = await fetchAuthoritativeRemoteSpace({
|
|
31
|
+
servers,
|
|
32
|
+
token,
|
|
33
|
+
userId,
|
|
34
|
+
spaceId,
|
|
35
|
+
});
|
|
36
|
+
if (remoteSpace) return { spaceId, spaceData: remoteSpace };
|
|
37
|
+
throw new Error(`Space not found: ${spaceId}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const readSpace = async (dbKey: string): Promise<SpaceData | null> => {
|
|
42
|
+
try {
|
|
43
|
+
const { read, readAndWait } = await import("../../database/dbSlice");
|
|
44
|
+
if (fresh) {
|
|
45
|
+
return await dispatch(readAndWait(dbKey)).unwrap();
|
|
46
|
+
}
|
|
47
|
+
return await dispatch(
|
|
48
|
+
read({
|
|
49
|
+
dbKey,
|
|
50
|
+
})
|
|
51
|
+
).unwrap();
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
let spaceData: SpaceData | null = await readSpace(spaceKey);
|
|
58
|
+
|
|
59
|
+
// If not found, try the raw ID as a fallback (maybe stored with the prefix)
|
|
60
|
+
if (!spaceData && rawSpaceId !== spaceKey) {
|
|
61
|
+
spaceData = await readSpace(rawSpaceId);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!spaceData) {
|
|
65
|
+
throw new Error(`Space not found: ${spaceId}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Ensure returned ID is normalized
|
|
69
|
+
return { spaceId, spaceData };
|
|
70
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { normalizeSpaceId } from "./spaceKeys";
|
|
2
|
+
import { readStoredCollapsedCategories } from "./spaceCollapsedState";
|
|
3
|
+
|
|
4
|
+
interface FetchSpaceSidebarStateResponse {
|
|
5
|
+
collapsedCategories: Record<string, boolean>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const fetchSpaceSidebarStateAction = async (
|
|
9
|
+
spaceId: string,
|
|
10
|
+
thunkAPI: any,
|
|
11
|
+
): Promise<FetchSpaceSidebarStateResponse> => {
|
|
12
|
+
const { dispatch, getState } = thunkAPI;
|
|
13
|
+
const normalizedSpaceId = normalizeSpaceId(spaceId);
|
|
14
|
+
void dispatch;
|
|
15
|
+
void getState;
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
collapsedCategories:
|
|
19
|
+
typeof window === "undefined"
|
|
20
|
+
? {}
|
|
21
|
+
: readStoredCollapsedCategories(
|
|
22
|
+
normalizedSpaceId,
|
|
23
|
+
window.localStorage,
|
|
24
|
+
),
|
|
25
|
+
};
|
|
26
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { RootState } from "../../app/store";
|
|
2
|
+
import { readDefaultSpaceIdPreference } from "../../app/settings/defaultSpacePreference";
|
|
3
|
+
|
|
4
|
+
import { changeSpace } from "./spaceSlice";
|
|
5
|
+
import { readSpaceIfExists } from "./resolvePreferredSpaceId";
|
|
6
|
+
|
|
7
|
+
export const loadDefaultSpaceAction = async (
|
|
8
|
+
userId: string | undefined,
|
|
9
|
+
thunkAPI
|
|
10
|
+
): Promise<string | null> => {
|
|
11
|
+
const dispatch = thunkAPI.dispatch;
|
|
12
|
+
const state = thunkAPI.getState() as RootState;
|
|
13
|
+
|
|
14
|
+
if (state.space.currentSpaceId) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const memberSpaces = state.space.memberSpaces;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const defaultSpaceId = await readDefaultSpaceIdPreference(dispatch, userId);
|
|
22
|
+
const spaceIdToLoad = await readSpaceIfExists(dispatch, defaultSpaceId);
|
|
23
|
+
|
|
24
|
+
if (spaceIdToLoad) {
|
|
25
|
+
await dispatch(changeSpace(spaceIdToLoad)).unwrap();
|
|
26
|
+
return spaceIdToLoad;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (memberSpaces === null) {
|
|
30
|
+
console.warn(
|
|
31
|
+
`[Space] Skipped default-space selection for ${userId}: memberships are still loading and no readable default-space register exists.`
|
|
32
|
+
);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Fall back to first readable member space when no register exists (e.g. accounts
|
|
37
|
+
// created before the register migration)
|
|
38
|
+
for (const memberSpace of memberSpaces) {
|
|
39
|
+
const fallbackId = memberSpace?.spaceId;
|
|
40
|
+
const readableId = await readSpaceIfExists(dispatch, fallbackId);
|
|
41
|
+
if (readableId) {
|
|
42
|
+
console.info(
|
|
43
|
+
`[Space] No register for ${userId}, falling back to member space: ${readableId}`
|
|
44
|
+
);
|
|
45
|
+
await dispatch(changeSpace(readableId)).unwrap();
|
|
46
|
+
return readableId;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
console.warn(
|
|
51
|
+
`[Space] Skipped default-space selection for ${userId}: no readable default-space register exists.`
|
|
52
|
+
);
|
|
53
|
+
return null;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { ULID } from "../../../app/types";
|
|
2
|
+
import type { MemberRole } from "../../../app/types";
|
|
3
|
+
import type { SpaceData } from "../../../app/types";
|
|
4
|
+
import { selectUserId } from "../../../auth/authSlice";
|
|
5
|
+
import { createSpaceKey } from "../../space/spaceKeys";
|
|
6
|
+
import { read, write } from "../../../database/dbSlice";
|
|
7
|
+
import { SpaceMemberWithSpaceInfo } from "../../../app/types";
|
|
8
|
+
import { DataType } from "../../types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 添加成员到空间
|
|
12
|
+
*
|
|
13
|
+
* 说明:
|
|
14
|
+
* 1. 当前用户必须为空间现有成员,才可以添加新成员;
|
|
15
|
+
* 2. 如果成员已存在则直接报错;
|
|
16
|
+
* 3. 更新 SpaceData.members 数组,同时为新成员创建 SpaceMemberWithSpaceInfo 数据。
|
|
17
|
+
*/
|
|
18
|
+
export const addMemberAction = async (
|
|
19
|
+
input: { spaceId: ULID; memberId: string; role?: MemberRole },
|
|
20
|
+
thunkAPI: any
|
|
21
|
+
): Promise<{ spaceId: ULID; updatedSpaceData: SpaceData }> => {
|
|
22
|
+
const { spaceId, memberId, role = MemberRole.MEMBER } = input; // 默认角色为 MEMBER
|
|
23
|
+
const { dispatch, getState } = thunkAPI;
|
|
24
|
+
const state = getState();
|
|
25
|
+
const currentUserId = selectUserId(state);
|
|
26
|
+
|
|
27
|
+
const spaceKey = createSpaceKey.space(spaceId);
|
|
28
|
+
const spaceData: SpaceData | null = await dispatch(read({
|
|
29
|
+
dbKey: spaceKey
|
|
30
|
+
})).unwrap();
|
|
31
|
+
|
|
32
|
+
if (!spaceData) {
|
|
33
|
+
throw new Error("Space not found");
|
|
34
|
+
}
|
|
35
|
+
// 检查当前用户是否为该空间的成员
|
|
36
|
+
if (!spaceData.members.includes(currentUserId)) {
|
|
37
|
+
throw new Error("当前用户不是空间成员,无法添加成员");
|
|
38
|
+
}
|
|
39
|
+
// 检查待添加的成员是否已存在
|
|
40
|
+
if (spaceData.members.includes(memberId)) {
|
|
41
|
+
throw new Error("成员已存在");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 更新 SpaceData
|
|
45
|
+
const updatedSpaceData: SpaceData = {
|
|
46
|
+
...spaceData,
|
|
47
|
+
members: [...spaceData.members, memberId],
|
|
48
|
+
updatedAt: Date.now(),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// 写入更新后的 SpaceData
|
|
52
|
+
await dispatch(
|
|
53
|
+
write({ data: updatedSpaceData, customKey: spaceKey })
|
|
54
|
+
).unwrap();
|
|
55
|
+
|
|
56
|
+
// 创建并写入新成员的 SpaceMemberWithSpaceInfo 数据
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
const spaceMemberData: SpaceMemberWithSpaceInfo = {
|
|
59
|
+
userId: memberId,
|
|
60
|
+
role: role, // 使用传入的 role,默认为 MEMBER
|
|
61
|
+
joinedAt: now,
|
|
62
|
+
updatedAt: now, // 可选字段,初始化时设置为当前时间
|
|
63
|
+
spaceId: spaceId,
|
|
64
|
+
spaceName: spaceData.name,
|
|
65
|
+
ownerId: spaceData.ownerId,
|
|
66
|
+
visibility: spaceData.visibility,
|
|
67
|
+
type: DataType.SPACE, // 添加 type 字段
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const spaceMemberKey = createSpaceKey.member(memberId, spaceId);
|
|
71
|
+
await dispatch(
|
|
72
|
+
write({
|
|
73
|
+
data: spaceMemberData,
|
|
74
|
+
customKey: spaceMemberKey,
|
|
75
|
+
})
|
|
76
|
+
).unwrap();
|
|
77
|
+
|
|
78
|
+
return { spaceId, updatedSpaceData };
|
|
79
|
+
};
|