@glodon-aiot/chat-app-sdk 0.0.27 → 0.0.28

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/es/index.esm.js CHANGED
@@ -7414,7 +7414,7 @@ var ___CSS_LOADER_EXPORT___ = _common_temp_default_node_modules_pnpm_css_loader_
7414
7414
  // Module
7415
7415
  ___CSS_LOADER_EXPORT___.push([
7416
7416
  module.id,
7417
- ".d5141aa56d2a57c00935 {\n width: 100%;\n margin-top: 7px;\n text-align: left;\n}\n.d79b06a73340274bc426 {\n font-size: 14px;\n font-weight: 400;\n color: #666;\n margin-bottom: 8px;\n line-height: 20px;\n}\n.eda25befdf424f596ef1 {\n padding-right: 25px;\n padding-left: 69px;\n}\n.e98fa6d756df3cd56afc {\n padding-right: 10px;\n padding-left: 58px;\n}\n.ed28c7ac4d2c9165f95b {\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: center;\n width: -moz-fit-content;\n width: fit-content;\n font-size: 14px;\n font-weight: 400;\n font-style: normal;\n line-height: 20px;\n border-style: solid;\n border-width: 1px;\n}\n.ed28c7ac4d2c9165f95b svg {\n width: 14px;\n height: 14px;\n}\n.b23b4c693bd848c83e8f {\n width: 100%;\n margin-top: 8px;\n}\n.e40e4bebca37dd563842 {\n padding-left: 69px;\n}\n.e854b20ceb21944e2eef {\n padding-left: 44px;\n}\n.fc781d12eaaa0f3deaf9 {\n margin-left: 56px;\n}\n.ced572f6343196fb5030 {\n margin-left: 28px;\n}\n",
7417
+ ".d5141aa56d2a57c00935 {\n width: 100%;\n margin-top: 7px;\n text-align: left;\n}\n.d79b06a73340274bc426 {\n font-size: 14px;\n font-weight: 400;\n color: #666;\n margin-bottom: 8px;\n line-height: 20px;\n}\n.eda25befdf424f596ef1 {\n padding-right: 25px;\n padding-left: 25px;\n}\n.e98fa6d756df3cd56afc {\n padding-right: 10px;\n padding-left: 25px;\n}\n.ed28c7ac4d2c9165f95b {\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: center;\n width: -moz-fit-content;\n width: fit-content;\n font-size: 14px;\n font-weight: 400;\n font-style: normal;\n line-height: 20px;\n border-style: solid;\n border-width: 1px;\n}\n.ed28c7ac4d2c9165f95b svg {\n width: 14px;\n height: 14px;\n}\n.b23b4c693bd848c83e8f {\n width: 100%;\n margin-top: 8px;\n}\n.e40e4bebca37dd563842 {\n padding-left: 69px;\n}\n.e854b20ceb21944e2eef {\n padding-left: 44px;\n}\n.fc781d12eaaa0f3deaf9 {\n margin-left: 56px;\n}\n.ced572f6343196fb5030 {\n margin-left: 28px;\n}\n",
7418
7418
  ""
7419
7419
  ]);
7420
7420
  // Exports
@@ -426655,6 +426655,507 @@ const DragUploadArea = ()=>{
426655
426655
  });
426656
426656
  };
426657
426657
 
426658
+ ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/public/use-latest-section-id.ts
426659
+ /*
426660
+ * Copyright 2025 coze-dev Authors
426661
+ *
426662
+ * Licensed under the Apache License, Version 2.0 (the "License");
426663
+ * you may not use this file except in compliance with the License.
426664
+ * You may obtain a copy of the License at
426665
+ *
426666
+ * http://www.apache.org/licenses/LICENSE-2.0
426667
+ *
426668
+ * Unless required by applicable law or agreed to in writing, software
426669
+ * distributed under the License is distributed on an "AS IS" BASIS,
426670
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
426671
+ * See the License for the specific language governing permissions and
426672
+ * limitations under the License.
426673
+ */
426674
+ const use_latest_section_id_useLatestSectionId = ()=>{
426675
+ const { useSectionIdStore } = use_chat_area_context_useChatAreaStoreSet();
426676
+ const latestSectionId = useSectionIdStore((state)=>state.latestSectionId);
426677
+ return latestSectionId;
426678
+ };
426679
+
426680
+ ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/context/use-conversation-id.ts
426681
+ /*
426682
+ * Copyright 2025 coze-dev Authors
426683
+ *
426684
+ * Licensed under the Apache License, Version 2.0 (the "License");
426685
+ * you may not use this file except in compliance with the License.
426686
+ * You may obtain a copy of the License at
426687
+ *
426688
+ * http://www.apache.org/licenses/LICENSE-2.0
426689
+ *
426690
+ * Unless required by applicable law or agreed to in writing, software
426691
+ * distributed under the License is distributed on an "AS IS" BASIS,
426692
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
426693
+ * See the License for the specific language governing permissions and
426694
+ * limitations under the License.
426695
+ */
426696
+
426697
+
426698
+ const useConversationId = ()=>{
426699
+ const chatAreaStoreSetContext = use_chat_area_context_useChatAreaStoreSet();
426700
+ if (!is_valid_context_isValidContext(chatAreaStoreSetContext)) throw new Error("chatAreaStoreSetContext is not valid");
426701
+ const { useGlobalInitStore } = chatAreaStoreSetContext;
426702
+ const conversationId = useGlobalInitStore((state)=>state.conversationId);
426703
+ return conversationId;
426704
+ };
426705
+
426706
+ ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/file/use-upload-to-knowledge.ts
426707
+ /*
426708
+ * Copyright 2025 coze-dev Authors
426709
+ *
426710
+ * Licensed under the Apache License, Version 2.0 (the "License");
426711
+ * you may not use this file except in compliance with the License.
426712
+ * You may obtain a copy of the License at
426713
+ *
426714
+ * http://www.apache.org/licenses/LICENSE-2.0
426715
+ *
426716
+ * Unless required by applicable law or agreed to in writing, software
426717
+ * distributed under the License is distributed on an "AS IS" BASIS,
426718
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
426719
+ * See the License for the specific language governing permissions and
426720
+ * limitations under the License.
426721
+ */ /* eslint-disable max-lines -- This file contains complex upload logic that requires many lines */
426722
+
426723
+
426724
+
426725
+ // Try to import from open-chat if available
426726
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
426727
+ let use_upload_to_knowledge_useChatAppProps = null;
426728
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
426729
+ let use_upload_to_knowledge_useChatCozeSdk = null;
426730
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
426731
+ let use_upload_to_knowledge_useChatAppStore = null;
426732
+ // Try to import updateCurrentConversationInfo from open-chat if available
426733
+ // Note: This variable is currently unused but kept for future use
426734
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
426735
+ const use_upload_to_knowledge_updateCurrentConversationInfo = null;
426736
+ let use_upload_to_knowledge_createConversationForMessage = null;
426737
+ try {
426738
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
426739
+ const openChatModule = __webpack_require__(Object(function webpackMissingModule() { var e = new Error("Cannot find module '@coze-studio/open-chat'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
426740
+ if (openChatModule.useChatAppProps) use_upload_to_knowledge_useChatAppProps = openChatModule.useChatAppProps;
426741
+ if (openChatModule.useChatCozeSdk) use_upload_to_knowledge_useChatCozeSdk = openChatModule.useChatCozeSdk;
426742
+ if (openChatModule.useChatAppStore) use_upload_to_knowledge_useChatAppStore = openChatModule.useChatAppStore;
426743
+ // Try to get updateCurrentConversationInfo from store
426744
+ try {
426745
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
426746
+ const storeHook = openChatModule.useChatAppStore;
426747
+ storeHook && typeof storeHook;
426748
+ } catch (error) {
426749
+ // Store not available
426750
+ error;
426751
+ }
426752
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
426753
+ const createConversationModule = __webpack_require__(Object(function webpackMissingModule() { var e = new Error("Cannot find module '@coze-studio/open-chat/chat/builder-chat/services/create-conversation'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
426754
+ if (createConversationModule.createConversationForMessage) use_upload_to_knowledge_createConversationForMessage = createConversationModule.createConversationForMessage;
426755
+ } catch (error) {
426756
+ // Module not available, hooks will be null
426757
+ error;
426758
+ }
426759
+ /** 按 fileId 存储轮询的 AbortController,删除文件时用于停止轮询 */ const knowledgePollingControllers = new Map();
426760
+ /**
426761
+ * 取消指定 fileId 的知识库文件状态轮询(会话中删除正在上传的文件时调用)
426762
+ */ function cancelKnowledgePolling(fileId) {
426763
+ const controller = knowledgePollingControllers.get(fileId);
426764
+ if (controller) {
426765
+ controller.abort();
426766
+ knowledgePollingControllers.delete(fileId);
426767
+ }
426768
+ }
426769
+ var use_upload_to_knowledge_FileProcessStatus;
426770
+ (function(FileProcessStatus) {
426771
+ FileProcessStatus[FileProcessStatus["Processing"] = 1] = "Processing";
426772
+ FileProcessStatus[FileProcessStatus["Completed"] = 2] = "Completed";
426773
+ FileProcessStatus[FileProcessStatus["Failed"] = 3] = "Failed";
426774
+ FileProcessStatus[FileProcessStatus["NotFound"] = -1] = "NotFound";
426775
+ })(use_upload_to_knowledge_FileProcessStatus || (use_upload_to_knowledge_FileProcessStatus = {}));
426776
+ /**
426777
+ * Query file processing status
426778
+ * @param params Query parameters
426779
+ * @returns File status items or null if query failed
426780
+ */ async function queryFileStatus(params) {
426781
+ const { apiUrl, token, appId, conversationId, sectionId, knowledgeId, docIds } = params;
426782
+ try {
426783
+ const requestBody = {
426784
+ app_id: appId,
426785
+ conversation_id: conversationId,
426786
+ section_id: sectionId,
426787
+ knowledge_id: knowledgeId,
426788
+ doc_ids: docIds
426789
+ };
426790
+ const apiEndpoint = `${apiUrl}/v1/workflows/conversation/file/status`;
426791
+ const response = await fetch(apiEndpoint, {
426792
+ method: "POST",
426793
+ headers: {
426794
+ "Content-Type": "application/json",
426795
+ Authorization: `Bearer ${token}`
426796
+ },
426797
+ body: JSON.stringify(requestBody)
426798
+ });
426799
+ const result = await response.json();
426800
+ if (result.code === 0 && result.data) {
426801
+ // Log status for each file
426802
+ result.data.forEach((item)=>{
426803
+ const statusText = item.status === 1 ? "处理中" : item.status === 2 ? "已完成" : item.status === 3 ? "处理失败" : item.status === -1 ? "文件不存在或异常" : `未知状态(${item.status})`;
426804
+ console.log(`File ${item.file_id} status: ${statusText}`, {
426805
+ file_id: item.file_id,
426806
+ status: item.status,
426807
+ message: item.message
426808
+ });
426809
+ });
426810
+ return result.data;
426811
+ } else {
426812
+ console.error("Failed to query file status:", result.msg || "Unknown error");
426813
+ return null;
426814
+ }
426815
+ } catch (error) {
426816
+ console.error("Error querying file status:", error);
426817
+ return null;
426818
+ }
426819
+ }
426820
+ /**
426821
+ * Poll file status until completion or failure
426822
+ * @param params Query parameters
426823
+ * @param options Polling options (intervalMs, signal for cancellation)
426824
+ * @returns Final file status items or null if polling failed / was aborted
426825
+ */ async function pollFileStatus(params) {
426826
+ let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
426827
+ const { intervalMs = 2000, signal } = options;
426828
+ for(;;){
426829
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) return null;
426830
+ const statusResult = await queryFileStatus(params);
426831
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) return null;
426832
+ if (!statusResult || statusResult.length === 0) {
426833
+ await new Promise((resolve)=>setTimeout(resolve, intervalMs));
426834
+ continue;
426835
+ }
426836
+ // Check if all files are in final state (completed, failed, or not found)
426837
+ const allFinal = statusResult.every((item)=>item.status === 2 || item.status === 3 || item.status === -1);
426838
+ if (allFinal) return statusResult;
426839
+ // Some files are still processing, wait and retry
426840
+ await new Promise((resolve)=>setTimeout(resolve, intervalMs));
426841
+ }
426842
+ }
426843
+ /**
426844
+ * Hook to upload file to knowledge base
426845
+ */ // eslint-disable-next-line @coze-arch/max-line-per-function
426846
+ const useUploadToKnowledge = (config)=>{
426847
+ const conversationId = useConversationId();
426848
+ const sectionId = use_latest_section_id_useLatestSectionId();
426849
+ const storeSet = use_chat_area_context_useChatAreaStoreSet();
426850
+ const { useGlobalInitStore, useSectionIdStore } = storeSet;
426851
+ // Get setLatestSectionId from the store
426852
+ // Always call the hook to satisfy React Hooks rules
426853
+ // useChatAreaStoreSet() throws if context is invalid, so useSectionIdStore is always defined
426854
+ const setLatestSectionId = useSectionIdStore((state)=>state.setLatestSectionId);
426855
+ // Try to get apiUrl from useChatAppStore as fallback
426856
+ let apiUrlFromStore;
426857
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
426858
+ const chatAppStoreHook = use_upload_to_knowledge_useChatAppStore;
426859
+ if (chatAppStoreHook && typeof chatAppStoreHook === "function") try {
426860
+ apiUrlFromStore = chatAppStoreHook((state)=>state.apiUrl);
426861
+ } catch (error) {
426862
+ // Store not available
426863
+ error;
426864
+ }
426865
+ const uploadFileToKnowledge = (0,react_.useCallback)(// eslint-disable-next-line @coze-arch/max-line-per-function, max-lines-per-function, complexity -- uploadFileToKnowledge requires many lines for complete file upload functionality
426866
+ async (file, options)=>{
426867
+ const fileId = options === null || options === void 0 ? void 0 : options.fileId;
426868
+ const controller = fileId ? new AbortController() : undefined;
426869
+ if (fileId && controller) knowledgePollingControllers.set(fileId, controller);
426870
+ try {
426871
+ var _chatConfig_appInfo, _chatConfig_auth;
426872
+ let chatConfig;
426873
+ let cozeApiSdk;
426874
+ // Use config from props first, then try to get from hooks, then fallback to store
426875
+ let apiUrl = (config === null || config === void 0 ? void 0 : config.apiUrl) || apiUrlFromStore;
426876
+ let appId = config === null || config === void 0 ? void 0 : config.appId;
426877
+ let token = config === null || config === void 0 ? void 0 : config.token;
426878
+ let workflowId = config === null || config === void 0 ? void 0 : config.workflowId;
426879
+ let draftMode = config === null || config === void 0 ? void 0 : config.draftMode;
426880
+ let conversationName = config === null || config === void 0 ? void 0 : config.conversationName;
426881
+ let connectorId = config === null || config === void 0 ? void 0 : config.connectorId;
426882
+ let chatType = config === null || config === void 0 ? void 0 : config.chatType;
426883
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useChatAppProps may not be available in all contexts
426884
+ const chatAppPropsHook = use_upload_to_knowledge_useChatAppProps;
426885
+ if (chatAppPropsHook && typeof chatAppPropsHook === "function") try {
426886
+ const chatAppProps = chatAppPropsHook();
426887
+ chatConfig = chatAppProps === null || chatAppProps === void 0 ? void 0 : chatAppProps.chatConfig;
426888
+ // Use values from hook if not provided in config
426889
+ if (!apiUrl) {
426890
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useChatAppStore may not be available in all contexts
426891
+ const storeHook = use_upload_to_knowledge_useChatAppStore;
426892
+ if (storeHook && typeof storeHook === "function") try {
426893
+ apiUrl = storeHook((state)=>state.apiUrl) || apiUrl;
426894
+ } catch (error) {
426895
+ // Store not available
426896
+ error;
426897
+ }
426898
+ }
426899
+ // Fill in missing values from chatConfig if not in config
426900
+ if (!appId) {
426901
+ var _chatConfig_appInfo1;
426902
+ appId = (chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo1 = chatConfig.appInfo) === null || _chatConfig_appInfo1 === void 0 ? void 0 : _chatConfig_appInfo1.appId) || (chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.bot_id);
426903
+ }
426904
+ if (!token) {
426905
+ var _chatConfig_auth1;
426906
+ token = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_auth1 = chatConfig.auth) === null || _chatConfig_auth1 === void 0 ? void 0 : _chatConfig_auth1.token;
426907
+ }
426908
+ if (!workflowId) {
426909
+ var _chatConfig_appInfo2;
426910
+ workflowId = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo2 = chatConfig.appInfo) === null || _chatConfig_appInfo2 === void 0 ? void 0 : _chatConfig_appInfo2.workflowId;
426911
+ }
426912
+ if (draftMode === undefined) {
426913
+ var _chatConfig_appInfo3;
426914
+ draftMode = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo3 = chatConfig.appInfo) === null || _chatConfig_appInfo3 === void 0 ? void 0 : _chatConfig_appInfo3.draft_mode;
426915
+ }
426916
+ if (!conversationName) {
426917
+ var _chatConfig_appInfo4;
426918
+ conversationName = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo4 = chatConfig.appInfo) === null || _chatConfig_appInfo4 === void 0 ? void 0 : _chatConfig_appInfo4.conversationName;
426919
+ }
426920
+ if (!connectorId) {
426921
+ var _chatConfig_auth2;
426922
+ connectorId = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_auth2 = chatConfig.auth) === null || _chatConfig_auth2 === void 0 ? void 0 : _chatConfig_auth2.connectorId;
426923
+ }
426924
+ if (!chatType) chatType = chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.type;
426925
+ } catch (error) {
426926
+ // Hook not available in this context
426927
+ error;
426928
+ }
426929
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useChatCozeSdk may not be available in all contexts
426930
+ const chatCozeSdkHook = use_upload_to_knowledge_useChatCozeSdk;
426931
+ if (chatCozeSdkHook && typeof chatCozeSdkHook === "function") try {
426932
+ const chatCozeSdk = chatCozeSdkHook();
426933
+ cozeApiSdk = chatCozeSdk === null || chatCozeSdk === void 0 ? void 0 : chatCozeSdk.cozeApiSdk;
426934
+ } catch (error1) {
426935
+ // Hook not available in this context
426936
+ error1;
426937
+ }
426938
+ // Check if we have minimum required info (apiUrl and appId)
426939
+ // We can work without chatConfig and cozeApiSdk if config is provided
426940
+ if (!apiUrl || !appId) {
426941
+ console.warn("Cannot upload to knowledge: apiUrl or appId is missing");
426942
+ return null;
426943
+ }
426944
+ // If we don't have chatConfig, create a minimal one from config
426945
+ if (!chatConfig) chatConfig = {
426946
+ type: chatType,
426947
+ appInfo: {
426948
+ appId,
426949
+ workflowId,
426950
+ draft_mode: draftMode,
426951
+ conversationName
426952
+ },
426953
+ bot_id: appId,
426954
+ auth: {
426955
+ token,
426956
+ connectorId
426957
+ }
426958
+ };
426959
+ // 1. Get or create conversation
426960
+ let currentConversationId = conversationId || "";
426961
+ let currentSectionId = sectionId || "";
426962
+ // If no conversation, create one
426963
+ if (!currentConversationId) {
426964
+ var _chatConfig_appInfo5, _chatConfig_appInfo6, _chatConfig_appInfo7, _chatConfig_appInfo8, _chatConfig_auth3, _chatConfig_auth4;
426965
+ const finalAppId = appId || ((_chatConfig_appInfo5 = chatConfig.appInfo) === null || _chatConfig_appInfo5 === void 0 ? void 0 : _chatConfig_appInfo5.appId) || chatConfig.bot_id || "";
426966
+ if (!finalAppId) {
426967
+ console.error("Cannot upload to knowledge: app_id is missing");
426968
+ return null;
426969
+ }
426970
+ const projectType = (chatType || chatConfig.type) === "app" ? "app" : "bot";
426971
+ const finalWorkflowId = workflowId || ((_chatConfig_appInfo6 = chatConfig.appInfo) === null || _chatConfig_appInfo6 === void 0 ? void 0 : _chatConfig_appInfo6.workflowId);
426972
+ const finalDraftMode = draftMode !== undefined ? draftMode : (_chatConfig_appInfo7 = chatConfig.appInfo) === null || _chatConfig_appInfo7 === void 0 ? void 0 : _chatConfig_appInfo7.draft_mode;
426973
+ const finalConversationName = conversationName || ((_chatConfig_appInfo8 = chatConfig.appInfo) === null || _chatConfig_appInfo8 === void 0 ? void 0 : _chatConfig_appInfo8.conversationName);
426974
+ const finalConnectorId = connectorId || ((_chatConfig_auth3 = chatConfig.auth) === null || _chatConfig_auth3 === void 0 ? void 0 : _chatConfig_auth3.connectorId);
426975
+ const finalToken = token || ((_chatConfig_auth4 = chatConfig.auth) === null || _chatConfig_auth4 === void 0 ? void 0 : _chatConfig_auth4.token) || "";
426976
+ // Try to use createConversationForMessage if available
426977
+ if (use_upload_to_knowledge_createConversationForMessage && cozeApiSdk) try {
426978
+ const conversationResult = await use_upload_to_knowledge_createConversationForMessage(cozeApiSdk, {
426979
+ projectType,
426980
+ projectId: finalAppId,
426981
+ workflowId: finalWorkflowId,
426982
+ mode: finalDraftMode ? "draft" : "release",
426983
+ conversationName: finalConversationName,
426984
+ connectorId: finalConnectorId
426985
+ });
426986
+ currentConversationId = conversationResult.conversationId;
426987
+ currentSectionId = conversationResult.sectionId;
426988
+ } catch (error) {
426989
+ console.warn("Failed to create conversation using createConversationForMessage:", error);
426990
+ // Fall through to direct API call
426991
+ }
426992
+ // If createConversationForMessage failed or is not available, use direct API call
426993
+ // Note: finalApiUrl is defined later in the code, so we use apiUrl here
426994
+ if (!currentConversationId && apiUrl && finalToken) try {
426995
+ let createUrl = "";
426996
+ let createPayload = {};
426997
+ if (projectType === "bot") {
426998
+ createUrl = `${apiUrl}/v1/conversations/create`;
426999
+ createPayload = {
427000
+ connector_id: finalConnectorId
427001
+ };
427002
+ } else {
427003
+ createUrl = `${apiUrl}/v1/workflow/conversation/create`;
427004
+ createPayload = {
427005
+ app_id: finalAppId,
427006
+ draft_mode: finalDraftMode || false,
427007
+ workflow_id: finalWorkflowId || "",
427008
+ connector_id: finalConnectorId
427009
+ };
427010
+ // Only add get_or_create if conversationName is provided
427011
+ if (finalConversationName && finalConversationName.trim() !== "") {
427012
+ createPayload.get_or_create = true;
427013
+ createPayload.conversation_name = finalConversationName;
427014
+ }
427015
+ }
427016
+ const createResponse = await fetch(createUrl, {
427017
+ method: "POST",
427018
+ headers: {
427019
+ "Content-Type": "application/json",
427020
+ Authorization: `Bearer ${finalToken}`,
427021
+ "Accept-Language": "en"
427022
+ },
427023
+ body: JSON.stringify(createPayload)
427024
+ });
427025
+ const createResult = await createResponse.json();
427026
+ if (createResult.code === 0 && createResult.data) {
427027
+ currentConversationId = createResult.data.id || "";
427028
+ currentSectionId = createResult.data.last_section_id || "";
427029
+ } else {
427030
+ console.error("Failed to create conversation:", createResult.msg || "Unknown error");
427031
+ return null;
427032
+ }
427033
+ } catch (error1) {
427034
+ console.error("Error creating conversation:", error1);
427035
+ return null;
427036
+ }
427037
+ // Update conversation ID in chat area
427038
+ if (currentConversationId) {
427039
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useGlobalInitStore type may vary by context
427040
+ const globalStore = useGlobalInitStore;
427041
+ if (globalStore && typeof globalStore.getState === "function") {
427042
+ const { setConversationId } = globalStore.getState();
427043
+ setConversationId(currentConversationId);
427044
+ }
427045
+ if (currentSectionId && setLatestSectionId) setLatestSectionId(currentSectionId);
427046
+ // Also update currentConversationInfo in store so text messages can use it
427047
+ // First try to use the callback from config (preferred method)
427048
+ if (config === null || config === void 0 ? void 0 : config.updateCurrentConversationInfo) try {
427049
+ // Delay updating currentConversationInfo to ensure file message is displayed first
427050
+ // This prevents chatarea from refreshing before the file message is added to the store
427051
+ // Use requestAnimationFrame + setTimeout to ensure file message is fully rendered and saved
427052
+ const DELAY_MS = 200; // Increased delay to ensure file message is fully saved to store
427053
+ requestAnimationFrame(()=>{
427054
+ setTimeout(()=>{
427055
+ if (config.updateCurrentConversationInfo) config.updateCurrentConversationInfo({
427056
+ id: currentConversationId,
427057
+ last_section_id: currentSectionId
427058
+ });
427059
+ }, DELAY_MS);
427060
+ });
427061
+ } catch (error) {
427062
+ console.warn("Failed to schedule updateCurrentConversationInfo:", error);
427063
+ }
427064
+ else {
427065
+ // Fallback: try to use dynamically imported hook (may not work in callbacks)
427066
+ // Note: This is a fallback that may not work in callbacks
427067
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- fallback hook may not be available
427068
+ const storeHook = use_upload_to_knowledge_useChatAppStore;
427069
+ }
427070
+ }
427071
+ }
427072
+ if (!currentConversationId || !currentSectionId) {
427073
+ console.error("Cannot upload to knowledge: conversation_id or section_id is missing");
427074
+ return null;
427075
+ }
427076
+ // 2. Prepare FormData
427077
+ const formData = new FormData();
427078
+ formData.append("file", file);
427079
+ formData.append("app_id", appId || ((_chatConfig_appInfo = chatConfig.appInfo) === null || _chatConfig_appInfo === void 0 ? void 0 : _chatConfig_appInfo.appId) || chatConfig.bot_id || "");
427080
+ formData.append("conversation_id", currentConversationId);
427081
+ formData.append("section_id", currentSectionId);
427082
+ // 3. Call upload API
427083
+ // Use apiUrl from config, store, or from cozeApiSdk
427084
+ const finalApiUrl = apiUrl || (cozeApiSdk === null || cozeApiSdk === void 0 ? void 0 : cozeApiSdk.baseURL) || "";
427085
+ const finalToken = token || ((_chatConfig_auth = chatConfig.auth) === null || _chatConfig_auth === void 0 ? void 0 : _chatConfig_auth.token) || "";
427086
+ if (!finalApiUrl) {
427087
+ console.error("Cannot upload to knowledge: API URL is missing");
427088
+ return null;
427089
+ }
427090
+ // Use fetch to upload file
427091
+ const apiEndpoint = `${finalApiUrl}/v1/workflows/conversation/file/toKnowledge`;
427092
+ const response = await fetch(apiEndpoint, {
427093
+ method: "POST",
427094
+ headers: {
427095
+ Authorization: `Bearer ${finalToken}`
427096
+ },
427097
+ body: formData
427098
+ });
427099
+ const result = await response.json();
427100
+ if (result.code === 0 && result.data) {
427101
+ var _chatConfig_appInfo9;
427102
+ // Response data includes: url, uri, bytes, CreatedAt, file_name, id, doc_id, knowledge_id
427103
+ console.log("File uploaded to knowledge successfully:", {
427104
+ url: result.data.url,
427105
+ uri: result.data.uri,
427106
+ file_name: result.data.file_name,
427107
+ id: result.data.id,
427108
+ doc_id: result.data.doc_id,
427109
+ knowledge_id: result.data.knowledge_id,
427110
+ bytes: result.data.bytes,
427111
+ CreatedAt: result.data.CreatedAt
427112
+ });
427113
+ // 4. Query file status after upload (poll until completion or failure)
427114
+ const statusResult = await pollFileStatus({
427115
+ apiUrl: finalApiUrl,
427116
+ token: finalToken,
427117
+ appId: appId || ((_chatConfig_appInfo9 = chatConfig.appInfo) === null || _chatConfig_appInfo9 === void 0 ? void 0 : _chatConfig_appInfo9.appId) || chatConfig.bot_id || "",
427118
+ conversationId: currentConversationId,
427119
+ sectionId: currentSectionId,
427120
+ knowledgeId: result.data.knowledge_id,
427121
+ docIds: [
427122
+ result.data.doc_id
427123
+ ]
427124
+ }, {
427125
+ intervalMs: 2000,
427126
+ signal: controller === null || controller === void 0 ? void 0 : controller.signal
427127
+ });
427128
+ // 轮询被用户取消(已删除文件)时不再更新 store,直接返回 null
427129
+ if (statusResult === null && (controller === null || controller === void 0 ? void 0 : controller.signal.aborted)) return null;
427130
+ if (statusResult) {
427131
+ // Check if file processing failed
427132
+ const failedFile = statusResult.find((item)=>item.status === 3);
427133
+ if (failedFile) console.error(`File processing failed: ${failedFile.message}`, failedFile);
427134
+ }
427135
+ return result.data;
427136
+ } else {
427137
+ console.error("Failed to upload file to knowledge:", result.msg || "Unknown error");
427138
+ return null;
427139
+ }
427140
+ } catch (error) {
427141
+ console.error("Error uploading file to knowledge:", error);
427142
+ return null;
427143
+ } finally{
427144
+ if (fileId) knowledgePollingControllers.delete(fileId);
427145
+ }
427146
+ }, [
427147
+ conversationId,
427148
+ sectionId,
427149
+ setLatestSectionId,
427150
+ useGlobalInitStore,
427151
+ apiUrlFromStore,
427152
+ config
427153
+ ]);
427154
+ return {
427155
+ uploadFileToKnowledge
427156
+ };
427157
+ };
427158
+
426658
427159
  ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/file/use-delete-file.ts
426659
427160
  /*
426660
427161
  * Copyright 2025 coze-dev Authors
@@ -426672,10 +427173,12 @@ const DragUploadArea = ()=>{
426672
427173
  * limitations under the License.
426673
427174
  */
426674
427175
 
427176
+
426675
427177
  const use_delete_file_useDeleteFile = ()=>{
426676
427178
  const { useBatchFileUploadStore } = use_chat_area_context_useChatAreaStoreSet();
426677
427179
  const { cancelUploadById } = useUploadController();
426678
427180
  return (fileId)=>{
427181
+ cancelKnowledgePolling(fileId);
426679
427182
  const { immerDeleteFileDataById } = useBatchFileUploadStore.getState();
426680
427183
  immerDeleteFileDataById(fileId);
426681
427184
  cancelUploadById(fileId);
@@ -427754,500 +428257,6 @@ const DELAY_TIME = 150;
427754
428257
  };
427755
428258
  };
427756
428259
 
427757
- ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/public/use-latest-section-id.ts
427758
- /*
427759
- * Copyright 2025 coze-dev Authors
427760
- *
427761
- * Licensed under the Apache License, Version 2.0 (the "License");
427762
- * you may not use this file except in compliance with the License.
427763
- * You may obtain a copy of the License at
427764
- *
427765
- * http://www.apache.org/licenses/LICENSE-2.0
427766
- *
427767
- * Unless required by applicable law or agreed to in writing, software
427768
- * distributed under the License is distributed on an "AS IS" BASIS,
427769
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
427770
- * See the License for the specific language governing permissions and
427771
- * limitations under the License.
427772
- */
427773
- const use_latest_section_id_useLatestSectionId = ()=>{
427774
- const { useSectionIdStore } = use_chat_area_context_useChatAreaStoreSet();
427775
- const latestSectionId = useSectionIdStore((state)=>state.latestSectionId);
427776
- return latestSectionId;
427777
- };
427778
-
427779
- ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/context/use-conversation-id.ts
427780
- /*
427781
- * Copyright 2025 coze-dev Authors
427782
- *
427783
- * Licensed under the Apache License, Version 2.0 (the "License");
427784
- * you may not use this file except in compliance with the License.
427785
- * You may obtain a copy of the License at
427786
- *
427787
- * http://www.apache.org/licenses/LICENSE-2.0
427788
- *
427789
- * Unless required by applicable law or agreed to in writing, software
427790
- * distributed under the License is distributed on an "AS IS" BASIS,
427791
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
427792
- * See the License for the specific language governing permissions and
427793
- * limitations under the License.
427794
- */
427795
-
427796
-
427797
- const useConversationId = ()=>{
427798
- const chatAreaStoreSetContext = use_chat_area_context_useChatAreaStoreSet();
427799
- if (!is_valid_context_isValidContext(chatAreaStoreSetContext)) throw new Error("chatAreaStoreSetContext is not valid");
427800
- const { useGlobalInitStore } = chatAreaStoreSetContext;
427801
- const conversationId = useGlobalInitStore((state)=>state.conversationId);
427802
- return conversationId;
427803
- };
427804
-
427805
- ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/file/use-upload-to-knowledge.ts
427806
- /*
427807
- * Copyright 2025 coze-dev Authors
427808
- *
427809
- * Licensed under the Apache License, Version 2.0 (the "License");
427810
- * you may not use this file except in compliance with the License.
427811
- * You may obtain a copy of the License at
427812
- *
427813
- * http://www.apache.org/licenses/LICENSE-2.0
427814
- *
427815
- * Unless required by applicable law or agreed to in writing, software
427816
- * distributed under the License is distributed on an "AS IS" BASIS,
427817
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
427818
- * See the License for the specific language governing permissions and
427819
- * limitations under the License.
427820
- */ /* eslint-disable max-lines -- This file contains complex upload logic that requires many lines */
427821
-
427822
-
427823
-
427824
- // Try to import from open-chat if available
427825
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
427826
- let use_upload_to_knowledge_useChatAppProps = null;
427827
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
427828
- let use_upload_to_knowledge_useChatCozeSdk = null;
427829
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
427830
- let use_upload_to_knowledge_useChatAppStore = null;
427831
- // Try to import updateCurrentConversationInfo from open-chat if available
427832
- // Note: This variable is currently unused but kept for future use
427833
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
427834
- const use_upload_to_knowledge_updateCurrentConversationInfo = null;
427835
- let use_upload_to_knowledge_createConversationForMessage = null;
427836
- try {
427837
- // eslint-disable-next-line @typescript-eslint/no-require-imports
427838
- const openChatModule = __webpack_require__(Object(function webpackMissingModule() { var e = new Error("Cannot find module '@coze-studio/open-chat'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
427839
- if (openChatModule.useChatAppProps) use_upload_to_knowledge_useChatAppProps = openChatModule.useChatAppProps;
427840
- if (openChatModule.useChatCozeSdk) use_upload_to_knowledge_useChatCozeSdk = openChatModule.useChatCozeSdk;
427841
- if (openChatModule.useChatAppStore) use_upload_to_knowledge_useChatAppStore = openChatModule.useChatAppStore;
427842
- // Try to get updateCurrentConversationInfo from store
427843
- try {
427844
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
427845
- const storeHook = openChatModule.useChatAppStore;
427846
- storeHook && typeof storeHook;
427847
- } catch (error) {
427848
- // Store not available
427849
- error;
427850
- }
427851
- // eslint-disable-next-line @typescript-eslint/no-require-imports
427852
- const createConversationModule = __webpack_require__(Object(function webpackMissingModule() { var e = new Error("Cannot find module '@coze-studio/open-chat/chat/builder-chat/services/create-conversation'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
427853
- if (createConversationModule.createConversationForMessage) use_upload_to_knowledge_createConversationForMessage = createConversationModule.createConversationForMessage;
427854
- } catch (error) {
427855
- // Module not available, hooks will be null
427856
- error;
427857
- }
427858
- var use_upload_to_knowledge_FileProcessStatus;
427859
- (function(FileProcessStatus) {
427860
- FileProcessStatus[FileProcessStatus["Processing"] = 1] = "Processing";
427861
- FileProcessStatus[FileProcessStatus["Completed"] = 2] = "Completed";
427862
- FileProcessStatus[FileProcessStatus["Failed"] = 3] = "Failed";
427863
- FileProcessStatus[FileProcessStatus["NotFound"] = -1] = "NotFound";
427864
- })(use_upload_to_knowledge_FileProcessStatus || (use_upload_to_knowledge_FileProcessStatus = {}));
427865
- /**
427866
- * Query file processing status
427867
- * @param params Query parameters
427868
- * @returns File status items or null if query failed
427869
- */ async function queryFileStatus(params) {
427870
- const { apiUrl, token, appId, conversationId, sectionId, knowledgeId, docIds } = params;
427871
- try {
427872
- const requestBody = {
427873
- app_id: appId,
427874
- conversation_id: conversationId,
427875
- section_id: sectionId,
427876
- knowledge_id: knowledgeId,
427877
- doc_ids: docIds
427878
- };
427879
- const apiEndpoint = `${apiUrl}/v1/workflows/conversation/file/status`;
427880
- const response = await fetch(apiEndpoint, {
427881
- method: "POST",
427882
- headers: {
427883
- "Content-Type": "application/json",
427884
- Authorization: `Bearer ${token}`
427885
- },
427886
- body: JSON.stringify(requestBody)
427887
- });
427888
- const result = await response.json();
427889
- if (result.code === 0 && result.data) {
427890
- // Log status for each file
427891
- result.data.forEach((item)=>{
427892
- const statusText = item.status === 1 ? "处理中" : item.status === 2 ? "已完成" : item.status === 3 ? "处理失败" : item.status === -1 ? "文件不存在或异常" : `未知状态(${item.status})`;
427893
- console.log(`File ${item.file_id} status: ${statusText}`, {
427894
- file_id: item.file_id,
427895
- status: item.status,
427896
- message: item.message
427897
- });
427898
- });
427899
- return result.data;
427900
- } else {
427901
- console.error("Failed to query file status:", result.msg || "Unknown error");
427902
- return null;
427903
- }
427904
- } catch (error) {
427905
- console.error("Error querying file status:", error);
427906
- return null;
427907
- }
427908
- }
427909
- /**
427910
- * Poll file status until completion or failure
427911
- * @param params Query parameters
427912
- * @param options Polling options
427913
- * @returns Final file status items or null if polling failed
427914
- */ async function pollFileStatus(params) {
427915
- let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
427916
- const { maxAttempts = 30, intervalMs = 2000 } = options;
427917
- let attempts = 0;
427918
- while(attempts < maxAttempts){
427919
- const statusResult = await queryFileStatus(params);
427920
- if (!statusResult || statusResult.length === 0) {
427921
- attempts++;
427922
- if (attempts >= maxAttempts) {
427923
- console.warn("File status polling reached max attempts");
427924
- return null;
427925
- }
427926
- await new Promise((resolve)=>setTimeout(resolve, intervalMs));
427927
- continue;
427928
- }
427929
- // Check if all files are in final state (completed, failed, or not found)
427930
- const allFinal = statusResult.every((item)=>item.status === 2 || item.status === 3 || item.status === -1);
427931
- if (allFinal) return statusResult;
427932
- // Some files are still processing, wait and retry
427933
- attempts++;
427934
- if (attempts >= maxAttempts) {
427935
- console.warn("File status polling reached max attempts, some files may still be processing");
427936
- return statusResult;
427937
- }
427938
- await new Promise((resolve)=>setTimeout(resolve, intervalMs));
427939
- }
427940
- return null;
427941
- }
427942
- /**
427943
- * Hook to upload file to knowledge base
427944
- */ // eslint-disable-next-line @coze-arch/max-line-per-function
427945
- const useUploadToKnowledge = (config)=>{
427946
- const conversationId = useConversationId();
427947
- const sectionId = use_latest_section_id_useLatestSectionId();
427948
- const storeSet = use_chat_area_context_useChatAreaStoreSet();
427949
- const { useGlobalInitStore, useSectionIdStore } = storeSet;
427950
- // Get setLatestSectionId from the store
427951
- // Always call the hook to satisfy React Hooks rules
427952
- // useChatAreaStoreSet() throws if context is invalid, so useSectionIdStore is always defined
427953
- const setLatestSectionId = useSectionIdStore((state)=>state.setLatestSectionId);
427954
- // Try to get apiUrl from useChatAppStore as fallback
427955
- let apiUrlFromStore;
427956
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
427957
- const chatAppStoreHook = use_upload_to_knowledge_useChatAppStore;
427958
- if (chatAppStoreHook && typeof chatAppStoreHook === "function") try {
427959
- apiUrlFromStore = chatAppStoreHook((state)=>state.apiUrl);
427960
- } catch (error) {
427961
- // Store not available
427962
- error;
427963
- }
427964
- const uploadFileToKnowledge = (0,react_.useCallback)(// eslint-disable-next-line @coze-arch/max-line-per-function, max-lines-per-function, complexity -- uploadFileToKnowledge requires many lines for complete file upload functionality
427965
- async (file)=>{
427966
- try {
427967
- var _chatConfig_appInfo, _chatConfig_auth;
427968
- let chatConfig;
427969
- let cozeApiSdk;
427970
- // Use config from props first, then try to get from hooks, then fallback to store
427971
- let apiUrl = (config === null || config === void 0 ? void 0 : config.apiUrl) || apiUrlFromStore;
427972
- let appId = config === null || config === void 0 ? void 0 : config.appId;
427973
- let token = config === null || config === void 0 ? void 0 : config.token;
427974
- let workflowId = config === null || config === void 0 ? void 0 : config.workflowId;
427975
- let draftMode = config === null || config === void 0 ? void 0 : config.draftMode;
427976
- let conversationName = config === null || config === void 0 ? void 0 : config.conversationName;
427977
- let connectorId = config === null || config === void 0 ? void 0 : config.connectorId;
427978
- let chatType = config === null || config === void 0 ? void 0 : config.chatType;
427979
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useChatAppProps may not be available in all contexts
427980
- const chatAppPropsHook = use_upload_to_knowledge_useChatAppProps;
427981
- if (chatAppPropsHook && typeof chatAppPropsHook === "function") try {
427982
- const chatAppProps = chatAppPropsHook();
427983
- chatConfig = chatAppProps === null || chatAppProps === void 0 ? void 0 : chatAppProps.chatConfig;
427984
- // Use values from hook if not provided in config
427985
- if (!apiUrl) {
427986
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useChatAppStore may not be available in all contexts
427987
- const storeHook = use_upload_to_knowledge_useChatAppStore;
427988
- if (storeHook && typeof storeHook === "function") try {
427989
- apiUrl = storeHook((state)=>state.apiUrl) || apiUrl;
427990
- } catch (error) {
427991
- // Store not available
427992
- error;
427993
- }
427994
- }
427995
- // Fill in missing values from chatConfig if not in config
427996
- if (!appId) {
427997
- var _chatConfig_appInfo1;
427998
- appId = (chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo1 = chatConfig.appInfo) === null || _chatConfig_appInfo1 === void 0 ? void 0 : _chatConfig_appInfo1.appId) || (chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.bot_id);
427999
- }
428000
- if (!token) {
428001
- var _chatConfig_auth1;
428002
- token = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_auth1 = chatConfig.auth) === null || _chatConfig_auth1 === void 0 ? void 0 : _chatConfig_auth1.token;
428003
- }
428004
- if (!workflowId) {
428005
- var _chatConfig_appInfo2;
428006
- workflowId = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo2 = chatConfig.appInfo) === null || _chatConfig_appInfo2 === void 0 ? void 0 : _chatConfig_appInfo2.workflowId;
428007
- }
428008
- if (draftMode === undefined) {
428009
- var _chatConfig_appInfo3;
428010
- draftMode = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo3 = chatConfig.appInfo) === null || _chatConfig_appInfo3 === void 0 ? void 0 : _chatConfig_appInfo3.draft_mode;
428011
- }
428012
- if (!conversationName) {
428013
- var _chatConfig_appInfo4;
428014
- conversationName = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo4 = chatConfig.appInfo) === null || _chatConfig_appInfo4 === void 0 ? void 0 : _chatConfig_appInfo4.conversationName;
428015
- }
428016
- if (!connectorId) {
428017
- var _chatConfig_auth2;
428018
- connectorId = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_auth2 = chatConfig.auth) === null || _chatConfig_auth2 === void 0 ? void 0 : _chatConfig_auth2.connectorId;
428019
- }
428020
- if (!chatType) chatType = chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.type;
428021
- } catch (error) {
428022
- // Hook not available in this context
428023
- error;
428024
- }
428025
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useChatCozeSdk may not be available in all contexts
428026
- const chatCozeSdkHook = use_upload_to_knowledge_useChatCozeSdk;
428027
- if (chatCozeSdkHook && typeof chatCozeSdkHook === "function") try {
428028
- const chatCozeSdk = chatCozeSdkHook();
428029
- cozeApiSdk = chatCozeSdk === null || chatCozeSdk === void 0 ? void 0 : chatCozeSdk.cozeApiSdk;
428030
- } catch (error1) {
428031
- // Hook not available in this context
428032
- error1;
428033
- }
428034
- // Check if we have minimum required info (apiUrl and appId)
428035
- // We can work without chatConfig and cozeApiSdk if config is provided
428036
- if (!apiUrl || !appId) {
428037
- console.warn("Cannot upload to knowledge: apiUrl or appId is missing");
428038
- return null;
428039
- }
428040
- // If we don't have chatConfig, create a minimal one from config
428041
- if (!chatConfig) chatConfig = {
428042
- type: chatType,
428043
- appInfo: {
428044
- appId,
428045
- workflowId,
428046
- draft_mode: draftMode,
428047
- conversationName
428048
- },
428049
- bot_id: appId,
428050
- auth: {
428051
- token,
428052
- connectorId
428053
- }
428054
- };
428055
- // 1. Get or create conversation
428056
- let currentConversationId = conversationId || "";
428057
- let currentSectionId = sectionId || "";
428058
- // If no conversation, create one
428059
- if (!currentConversationId) {
428060
- var _chatConfig_appInfo5, _chatConfig_appInfo6, _chatConfig_appInfo7, _chatConfig_appInfo8, _chatConfig_auth3, _chatConfig_auth4;
428061
- const finalAppId = appId || ((_chatConfig_appInfo5 = chatConfig.appInfo) === null || _chatConfig_appInfo5 === void 0 ? void 0 : _chatConfig_appInfo5.appId) || chatConfig.bot_id || "";
428062
- if (!finalAppId) {
428063
- console.error("Cannot upload to knowledge: app_id is missing");
428064
- return null;
428065
- }
428066
- const projectType = (chatType || chatConfig.type) === "app" ? "app" : "bot";
428067
- const finalWorkflowId = workflowId || ((_chatConfig_appInfo6 = chatConfig.appInfo) === null || _chatConfig_appInfo6 === void 0 ? void 0 : _chatConfig_appInfo6.workflowId);
428068
- const finalDraftMode = draftMode !== undefined ? draftMode : (_chatConfig_appInfo7 = chatConfig.appInfo) === null || _chatConfig_appInfo7 === void 0 ? void 0 : _chatConfig_appInfo7.draft_mode;
428069
- const finalConversationName = conversationName || ((_chatConfig_appInfo8 = chatConfig.appInfo) === null || _chatConfig_appInfo8 === void 0 ? void 0 : _chatConfig_appInfo8.conversationName);
428070
- const finalConnectorId = connectorId || ((_chatConfig_auth3 = chatConfig.auth) === null || _chatConfig_auth3 === void 0 ? void 0 : _chatConfig_auth3.connectorId);
428071
- const finalToken = token || ((_chatConfig_auth4 = chatConfig.auth) === null || _chatConfig_auth4 === void 0 ? void 0 : _chatConfig_auth4.token) || "";
428072
- // Try to use createConversationForMessage if available
428073
- if (use_upload_to_knowledge_createConversationForMessage && cozeApiSdk) try {
428074
- const conversationResult = await use_upload_to_knowledge_createConversationForMessage(cozeApiSdk, {
428075
- projectType,
428076
- projectId: finalAppId,
428077
- workflowId: finalWorkflowId,
428078
- mode: finalDraftMode ? "draft" : "release",
428079
- conversationName: finalConversationName,
428080
- connectorId: finalConnectorId
428081
- });
428082
- currentConversationId = conversationResult.conversationId;
428083
- currentSectionId = conversationResult.sectionId;
428084
- } catch (error) {
428085
- console.warn("Failed to create conversation using createConversationForMessage:", error);
428086
- // Fall through to direct API call
428087
- }
428088
- // If createConversationForMessage failed or is not available, use direct API call
428089
- // Note: finalApiUrl is defined later in the code, so we use apiUrl here
428090
- if (!currentConversationId && apiUrl && finalToken) try {
428091
- let createUrl = "";
428092
- let createPayload = {};
428093
- if (projectType === "bot") {
428094
- createUrl = `${apiUrl}/v1/conversations/create`;
428095
- createPayload = {
428096
- connector_id: finalConnectorId
428097
- };
428098
- } else {
428099
- createUrl = `${apiUrl}/v1/workflow/conversation/create`;
428100
- createPayload = {
428101
- app_id: finalAppId,
428102
- draft_mode: finalDraftMode || false,
428103
- workflow_id: finalWorkflowId || "",
428104
- connector_id: finalConnectorId
428105
- };
428106
- // Only add get_or_create if conversationName is provided
428107
- if (finalConversationName && finalConversationName.trim() !== "") {
428108
- createPayload.get_or_create = true;
428109
- createPayload.conversation_name = finalConversationName;
428110
- }
428111
- }
428112
- const createResponse = await fetch(createUrl, {
428113
- method: "POST",
428114
- headers: {
428115
- "Content-Type": "application/json",
428116
- Authorization: `Bearer ${finalToken}`,
428117
- "Accept-Language": "en"
428118
- },
428119
- body: JSON.stringify(createPayload)
428120
- });
428121
- const createResult = await createResponse.json();
428122
- if (createResult.code === 0 && createResult.data) {
428123
- currentConversationId = createResult.data.id || "";
428124
- currentSectionId = createResult.data.last_section_id || "";
428125
- } else {
428126
- console.error("Failed to create conversation:", createResult.msg || "Unknown error");
428127
- return null;
428128
- }
428129
- } catch (error1) {
428130
- console.error("Error creating conversation:", error1);
428131
- return null;
428132
- }
428133
- // Update conversation ID in chat area
428134
- if (currentConversationId) {
428135
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- useGlobalInitStore type may vary by context
428136
- const globalStore = useGlobalInitStore;
428137
- if (globalStore && typeof globalStore.getState === "function") {
428138
- const { setConversationId } = globalStore.getState();
428139
- setConversationId(currentConversationId);
428140
- }
428141
- if (currentSectionId && setLatestSectionId) setLatestSectionId(currentSectionId);
428142
- // Also update currentConversationInfo in store so text messages can use it
428143
- // First try to use the callback from config (preferred method)
428144
- if (config === null || config === void 0 ? void 0 : config.updateCurrentConversationInfo) try {
428145
- // Delay updating currentConversationInfo to ensure file message is displayed first
428146
- // This prevents chatarea from refreshing before the file message is added to the store
428147
- // Use requestAnimationFrame + setTimeout to ensure file message is fully rendered and saved
428148
- const DELAY_MS = 200; // Increased delay to ensure file message is fully saved to store
428149
- requestAnimationFrame(()=>{
428150
- setTimeout(()=>{
428151
- if (config.updateCurrentConversationInfo) config.updateCurrentConversationInfo({
428152
- id: currentConversationId,
428153
- last_section_id: currentSectionId
428154
- });
428155
- }, DELAY_MS);
428156
- });
428157
- } catch (error) {
428158
- console.warn("Failed to schedule updateCurrentConversationInfo:", error);
428159
- }
428160
- else {
428161
- // Fallback: try to use dynamically imported hook (may not work in callbacks)
428162
- // Note: This is a fallback that may not work in callbacks
428163
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- fallback hook may not be available
428164
- const storeHook = use_upload_to_knowledge_useChatAppStore;
428165
- }
428166
- }
428167
- }
428168
- if (!currentConversationId || !currentSectionId) {
428169
- console.error("Cannot upload to knowledge: conversation_id or section_id is missing");
428170
- return null;
428171
- }
428172
- // 2. Prepare FormData
428173
- const formData = new FormData();
428174
- formData.append("file", file);
428175
- formData.append("app_id", appId || ((_chatConfig_appInfo = chatConfig.appInfo) === null || _chatConfig_appInfo === void 0 ? void 0 : _chatConfig_appInfo.appId) || chatConfig.bot_id || "");
428176
- formData.append("conversation_id", currentConversationId);
428177
- formData.append("section_id", currentSectionId);
428178
- // 3. Call upload API
428179
- // Use apiUrl from config, store, or from cozeApiSdk
428180
- const finalApiUrl = apiUrl || (cozeApiSdk === null || cozeApiSdk === void 0 ? void 0 : cozeApiSdk.baseURL) || "";
428181
- const finalToken = token || ((_chatConfig_auth = chatConfig.auth) === null || _chatConfig_auth === void 0 ? void 0 : _chatConfig_auth.token) || "";
428182
- if (!finalApiUrl) {
428183
- console.error("Cannot upload to knowledge: API URL is missing");
428184
- return null;
428185
- }
428186
- // Use fetch to upload file
428187
- const apiEndpoint = `${finalApiUrl}/v1/workflows/conversation/file/toKnowledge`;
428188
- const response = await fetch(apiEndpoint, {
428189
- method: "POST",
428190
- headers: {
428191
- Authorization: `Bearer ${finalToken}`
428192
- },
428193
- body: formData
428194
- });
428195
- const result = await response.json();
428196
- if (result.code === 0 && result.data) {
428197
- var _chatConfig_appInfo9;
428198
- // Response data includes: url, uri, bytes, CreatedAt, file_name, id, doc_id, knowledge_id
428199
- console.log("File uploaded to knowledge successfully:", {
428200
- url: result.data.url,
428201
- uri: result.data.uri,
428202
- file_name: result.data.file_name,
428203
- id: result.data.id,
428204
- doc_id: result.data.doc_id,
428205
- knowledge_id: result.data.knowledge_id,
428206
- bytes: result.data.bytes,
428207
- CreatedAt: result.data.CreatedAt
428208
- });
428209
- // 4. Query file status after upload (poll until completion or failure)
428210
- const statusResult = await pollFileStatus({
428211
- apiUrl: finalApiUrl,
428212
- token: finalToken,
428213
- appId: appId || ((_chatConfig_appInfo9 = chatConfig.appInfo) === null || _chatConfig_appInfo9 === void 0 ? void 0 : _chatConfig_appInfo9.appId) || chatConfig.bot_id || "",
428214
- conversationId: currentConversationId,
428215
- sectionId: currentSectionId,
428216
- knowledgeId: result.data.knowledge_id,
428217
- docIds: [
428218
- result.data.doc_id
428219
- ]
428220
- }, {
428221
- maxAttempts: 30,
428222
- intervalMs: 2000
428223
- });
428224
- if (statusResult) {
428225
- // Check if file processing failed
428226
- const failedFile = statusResult.find((item)=>item.status === 3);
428227
- if (failedFile) console.error(`File processing failed: ${failedFile.message}`, failedFile);
428228
- }
428229
- return result.data;
428230
- } else {
428231
- console.error("Failed to upload file to knowledge:", result.msg || "Unknown error");
428232
- return null;
428233
- }
428234
- } catch (error) {
428235
- console.error("Error uploading file to knowledge:", error);
428236
- return null;
428237
- }
428238
- }, [
428239
- conversationId,
428240
- sectionId,
428241
- setLatestSectionId,
428242
- useGlobalInitStore,
428243
- apiUrlFromStore,
428244
- config
428245
- ]);
428246
- return {
428247
- uploadFileToKnowledge
428248
- };
428249
- };
428250
-
428251
428260
  ;// CONCATENATED MODULE: ../../../common/chat-area/chat-area/src/hooks/file/use-paste-upload.ts
428252
428261
  /*
428253
428262
  * Copyright 2025 coze-dev Authors
@@ -428397,6 +428406,7 @@ var components_chat_input_index_module_update = injectStylesIntoStyleTag_default
428397
428406
 
428398
428407
 
428399
428408
 
428409
+
428400
428410
 
428401
428411
 
428402
428412
  const ChatInputArea = /*#__PURE__*/ (0,react_.forwardRef)((_, ref)=>{
@@ -428535,29 +428545,52 @@ const chat_input_ChatInput = /*#__PURE__*/ (0,react_.forwardRef)((props, ref)=>{
428535
428545
  return;
428536
428546
  }
428537
428547
  // 如果是非图片文件且 uploadToKnowledge 启用,上传到知识库
428538
- if (uploadToKnowledge) try {
428539
- // Add file to BatchUploadFileList (display above input) instead of sending as message
428540
- // This matches the behavior of normal file uploads
428541
- const { immerCreateFileData } = useBatchFileUploadStore.getState();
428542
- const fileId = index_browser_nanoid();
428543
- immerCreateFileData(fileId, payload.file);
428544
- // Now upload to knowledge (this will create conversation and update currentConversationInfo)
428545
- // The update is delayed to prevent chatarea refresh before file is displayed
428546
- const uploadResult = await uploadFileToKnowledge(payload.file);
428547
- // Update file status based on upload result
428548
- const { immerUpdateFileDataById } = useBatchFileUploadStore.getState();
428549
- if (uploadResult) // Upload successful, mark as success and save uri and fileId from response
428550
- immerUpdateFileDataById(fileId, (data)=>{
428551
- data.status = types_FileStatus.Success;
428552
- data.percent = 100;
428553
- // Save uri, fileId, and knowledge_id from API response for sending messages
428554
- data.uri = uploadResult.uri;
428555
- data.fileId = uploadResult.id;
428556
- data.url = uploadResult.url;
428557
- data.knowledge_id = uploadResult.knowledge_id;
428558
- });
428559
- else {
428560
- // Upload failed, mark as error and show toast
428548
+ if (uploadToKnowledge) {
428549
+ let fileId;
428550
+ try {
428551
+ // Add file to BatchUploadFileList (display above input) instead of sending as message
428552
+ const { immerCreateFileData } = useBatchFileUploadStore.getState();
428553
+ fileId = index_browser_nanoid();
428554
+ immerCreateFileData(fileId, payload.file);
428555
+ // Now upload to knowledge (this will create conversation and update currentConversationInfo)
428556
+ // The update is delayed to prevent chatarea refresh before file is displayed
428557
+ const uploadResult = await uploadFileToKnowledge(payload.file, {
428558
+ fileId
428559
+ });
428560
+ // Update file status based on upload result(若用户已删除该文件则不再更新,也不提示失败)
428561
+ const storeState = useBatchFileUploadStore.getState();
428562
+ const fileStillExists = storeState.fileIdList.includes(fileId);
428563
+ if (!fileStillExists) return;
428564
+ const { immerUpdateFileDataById } = storeState;
428565
+ if (uploadResult) // Upload successful, mark as success and save uri and fileId from response
428566
+ immerUpdateFileDataById(fileId, (data)=>{
428567
+ data.status = types_FileStatus.Success;
428568
+ data.percent = 100;
428569
+ // Save uri, fileId, and knowledge_id from API response for sending messages
428570
+ data.uri = uploadResult.uri;
428571
+ data.fileId = uploadResult.id;
428572
+ data.url = uploadResult.url;
428573
+ data.knowledge_id = uploadResult.knowledge_id;
428574
+ });
428575
+ else {
428576
+ // Upload failed, mark as error and show toast
428577
+ immerUpdateFileDataById(fileId, (data)=>{
428578
+ data.status = types_FileStatus.Error;
428579
+ data.percent = 0;
428580
+ });
428581
+ esm_webpack_exports_Toast.error({
428582
+ content: "上传文件到知识库失败,请重试",
428583
+ showClose: false
428584
+ });
428585
+ }
428586
+ return;
428587
+ } catch (error) {
428588
+ console.error("Failed to upload file to knowledge:", error);
428589
+ // 若用户已删除该文件(store 中不存在),不再重新创建并展示错误
428590
+ const storeState = useBatchFileUploadStore.getState();
428591
+ if (fileId === undefined || !storeState.fileIdList.includes(fileId)) return;
428592
+ // 上传异常时仅把当前文件标为错误,不重复创建新文件
428593
+ const { immerUpdateFileDataById } = storeState;
428561
428594
  immerUpdateFileDataById(fileId, (data)=>{
428562
428595
  data.status = types_FileStatus.Error;
428563
428596
  data.percent = 0;
@@ -428566,25 +428599,8 @@ const chat_input_ChatInput = /*#__PURE__*/ (0,react_.forwardRef)((props, ref)=>{
428566
428599
  content: "上传文件到知识库失败,请重试",
428567
428600
  showClose: false
428568
428601
  });
428602
+ return;
428569
428603
  }
428570
- return;
428571
- } catch (error) {
428572
- console.error("Failed to upload file to knowledge:", error);
428573
- // Even on error, show file in BatchUploadFileList so user can see what was attempted
428574
- // Add file to BatchUploadFileList (display above input) instead of sending as message
428575
- const { immerCreateFileData, immerUpdateFileDataById } = useBatchFileUploadStore.getState();
428576
- const fileId = index_browser_nanoid();
428577
- immerCreateFileData(fileId, payload.file);
428578
- // Mark file as error and show toast
428579
- immerUpdateFileDataById(fileId, (data)=>{
428580
- data.status = types_FileStatus.Error;
428581
- data.percent = 0;
428582
- });
428583
- esm_webpack_exports_Toast.error({
428584
- content: "上传文件到知识库失败,请重试",
428585
- showClose: false
428586
- });
428587
- return;
428588
428604
  }
428589
428605
  // Then proceed with normal upload (only if uploadToKnowledge is false)
428590
428606
  if (enableMultimodalUpload) {
@@ -438426,7 +438442,7 @@ var conversation_list_index_module_update = injectStylesIntoStyleTag_default()(c
438426
438442
 
438427
438443
  const ConversationList = /*#__PURE__*/ (0,react_.forwardRef)(// eslint-disable-next-line @coze-arch/max-line-per-function
438428
438444
  (param, ref)=>{
438429
- let { onRename, onDelete, loading, groupedConversations, conversations, hasMore, loadMore, removeConversation } = param;
438445
+ let { onRename, onDelete, onConversationKeyChange, loading, groupedConversations, conversations, hasMore, loadMore, removeConversation } = param;
438430
438446
  const { currentConversationInfo, updateCurrentConversationInfo, cozeApi, updateConversations } = context_useChatAppStore(shallow_useShallow((state)=>({
438431
438447
  currentConversationInfo: state.currentConversationInfo,
438432
438448
  updateCurrentConversationInfo: state.updateCurrentConversationInfo,
@@ -438485,6 +438501,7 @@ const ConversationList = /*#__PURE__*/ (0,react_.forwardRef)(// eslint-disable-n
438485
438501
  // 更新当前会话信息为空会话,这会触发 chat-area 重新初始化
438486
438502
  updateCurrentConversationInfo(emptyConversationInfo);
438487
438503
  conversationRef.current = emptyConversationInfo;
438504
+ onConversationKeyChange === null || onConversationKeyChange === void 0 || onConversationKeyChange("empty");
438488
438505
  } catch (error) {
438489
438506
  console.error(error);
438490
438507
  } finally{
@@ -438512,6 +438529,7 @@ const ConversationList = /*#__PURE__*/ (0,react_.forwardRef)(// eslint-disable-n
438512
438529
  };
438513
438530
  conversationRef.current = c;
438514
438531
  updateCurrentConversationInfo(c);
438532
+ onConversationKeyChange === null || onConversationKeyChange === void 0 || onConversationKeyChange(conversation.id);
438515
438533
  return;
438516
438534
  }
438517
438535
  // 如果会话ID相同,检查是否真的需要更新(避免不必要的重载)
@@ -438536,6 +438554,7 @@ const ConversationList = /*#__PURE__*/ (0,react_.forwardRef)(// eslint-disable-n
438536
438554
  console.log("handleConversationChange conversation2", c);
438537
438555
  conversationRef.current = c;
438538
438556
  updateCurrentConversationInfo(c);
438557
+ onConversationKeyChange === null || onConversationKeyChange === void 0 || onConversationKeyChange(conversation.id);
438539
438558
  return;
438540
438559
  }
438541
438560
  // 会话ID不同,正常更新
@@ -438557,6 +438576,7 @@ const ConversationList = /*#__PURE__*/ (0,react_.forwardRef)(// eslint-disable-n
438557
438576
  conversationRef.current = c;
438558
438577
  // 然后更新 currentConversationInfo,这会触发 openRequestInit 重新调用
438559
438578
  updateCurrentConversationInfo(c);
438579
+ onConversationKeyChange === null || onConversationKeyChange === void 0 || onConversationKeyChange(conversation.id);
438560
438580
  };
438561
438581
  const handleDeleteConversation = async (conversation)=>{
438562
438582
  try {
@@ -438774,6 +438794,12 @@ var conversation_list_sider_index_module_update = injectStylesIntoStyleTag_defau
438774
438794
  const groupedConversations = useGroupedConversations(conversations);
438775
438795
  const [isModalLoading, setIsModalLoading] = (0,react_.useState)(false);
438776
438796
  const [modalInfo, setModalInfo] = (0,react_.useState)(null);
438797
+ // 使用稳定 key,避免空会话下上传文件创建新会话时因 key 从 '' 变为 newId 导致整树 remount、上传列表被清空
438798
+ const [fragmentKey, setFragmentKey] = (0,react_.useState)(()=>(currentConversationInfo === null || currentConversationInfo === void 0 ? void 0 : currentConversationInfo.id) ?? "empty");
438799
+ // 点击「新会话」时使用唯一 key 强制 remount,否则 fragmentKey 本就为 'empty' 不会 remount,空会话界面不展示
438800
+ const handleConversationKeyChange = (0,react_.useCallback)((key)=>{
438801
+ setFragmentKey((k)=>key === "empty" ? `empty-${Date.now()}` : key);
438802
+ }, []);
438777
438803
  const handleOpenRenameModal = (conversation)=>{
438778
438804
  if (!(conversation === null || conversation === void 0 ? void 0 : conversation.id)) {
438779
438805
  console.error("Cannot rename conversation: id is missing", conversation);
@@ -438899,6 +438925,7 @@ var conversation_list_sider_index_module_update = injectStylesIntoStyleTag_defau
438899
438925
  ref: conversationListRef,
438900
438926
  onRename: handleOpenRenameModal,
438901
438927
  onDelete: handleOpenDeleteModal,
438928
+ onConversationKeyChange: handleConversationKeyChange,
438902
438929
  loading: loading,
438903
438930
  groupedConversations: groupedConversations,
438904
438931
  conversations: conversations,
@@ -438908,7 +438935,7 @@ var conversation_list_sider_index_module_update = injectStylesIntoStyleTag_defau
438908
438935
  }) : null,
438909
438936
  /*#__PURE__*/ (0,jsx_runtime_.jsx)(react_.Fragment, {
438910
438937
  children: children
438911
- }, currentConversationInfo === null || currentConversationInfo === void 0 ? void 0 : currentConversationInfo.id),
438938
+ }, fragmentKey),
438912
438939
  /*#__PURE__*/ (0,jsx_runtime_.jsx)(esm_webpack_exports_SideSheet, {
438913
438940
  visible: (currentConversationInfo === null || currentConversationInfo === void 0 ? void 0 : currentConversationInfo.conversationListVisible) && !(currentConversationInfo === null || currentConversationInfo === void 0 ? void 0 : currentConversationInfo.isLargeWidth),
438914
438941
  closeIcon: /*#__PURE__*/ (0,jsx_runtime_.jsx)(__webpack_exports__IconCozSideNav, {}),
@@ -438930,6 +438957,7 @@ var conversation_list_sider_index_module_update = injectStylesIntoStyleTag_defau
438930
438957
  ref: conversationListRef,
438931
438958
  onRename: handleOpenRenameModal,
438932
438959
  onDelete: handleOpenDeleteModal,
438960
+ onConversationKeyChange: handleConversationKeyChange,
438933
438961
  loading: loading,
438934
438962
  groupedConversations: groupedConversations,
438935
438963
  conversations: conversations,
@@ -447131,7 +447159,7 @@ const use_request_init_getConversationInfo = async (param)=>{
447131
447159
  next_cursor: nextCursor
447132
447160
  };
447133
447161
  };
447134
- // 新增:获取当前 section 对应的知识库列表
447162
+ // 新增:获取当前 section 对应的知识库列表(供清除对话后刷新知识库使用)
447135
447163
  const getConversationKnowledges = async (param)=>{
447136
447164
  let { cozeApiSdk, conversationId, sectionId, appId } = param;
447137
447165
  if (!conversationId || !sectionId || !appId) return [];
@@ -449481,6 +449509,8 @@ class MessageParser {
449481
449509
  case "error":
449482
449510
  {
449483
449511
  const messageError = src_safe_json_parse_safeJSONParse(data);
449512
+ const hasExplicitError = (messageError === null || messageError === void 0 ? void 0 : messageError.code) !== undefined && (messageError === null || messageError === void 0 ? void 0 : messageError.code) !== 0 || (messageError === null || messageError === void 0 ? void 0 : messageError.msg) !== undefined && String(messageError.msg).trim() !== "";
449513
+ if (!hasExplicitError) return;
449484
449514
  const errorMsg = (messageError === null || messageError === void 0 ? void 0 : messageError.msg) || src_I18n.t("sendFailed");
449485
449515
  esm_webpack_exports_Toast.error(errorMsg);
449486
449516
  throw new Error("Chat stream error");
@@ -449971,10 +450001,12 @@ class MessageParser {
449971
450001
 
449972
450002
 
449973
450003
 
450004
+
450005
+
449974
450006
  /* eslint-disable @coze-arch/max-line-per-function -- This adapter function handles complex message sending logic */ const useSendMessageAdapter = (userInfo, refChatFunc)=>{
449975
450007
  var _chatConfig_auth;
449976
450008
  const { debug, chatConfig } = context_useChatAppProps();
449977
- const { shortcuts, apiUrl, updateConversations, updateCurrentConversationInfo, currentConversationInfo, conversations, cozeApi, conversationKnowledgeIds } = context_useChatAppStore(shallow_useShallow((state)=>({
450009
+ const { shortcuts, apiUrl, updateConversations, updateCurrentConversationInfo, currentConversationInfo, conversations, cozeApi, conversationKnowledgeIds, setConversationKnowledgeIds } = context_useChatAppStore(shallow_useShallow((state)=>({
449978
450010
  shortcuts: state.shortcuts,
449979
450011
  apiUrl: state.apiUrl,
449980
450012
  updateConversations: state.updateConversations,
@@ -449982,7 +450014,8 @@ class MessageParser {
449982
450014
  currentConversationInfo: state.currentConversationInfo,
449983
450015
  conversations: state.conversations,
449984
450016
  cozeApi: state.cozeApi,
449985
- conversationKnowledgeIds: state.conversationKnowledgeIds
450017
+ conversationKnowledgeIds: state.conversationKnowledgeIds,
450018
+ setConversationKnowledgeIds: state.setConversationKnowledgeIds
449986
450019
  })));
449987
450020
  // 从 context 获取 cozeApiSdk 作为备用
449988
450021
  const { cozeApiSdk } = context_useChatCozeSdk();
@@ -449999,6 +450032,8 @@ class MessageParser {
449999
450032
  refStore.current = storeInstance;
450000
450033
  // 保存新创建的 conversation 信息,以便在消息发送成功后更新状态
450001
450034
  const refPendingConversationInfo = (0,react_.useRef)(null);
450035
+ // 已因 DONE 返回过 synthetic ack 时置为 true,后续 ERROR 事件不再交给 parser(避免误报「发送失败」)
450036
+ const refStreamAlreadySucceeded = (0,react_.useRef)(false);
450002
450037
  // 新增:追踪最新的 conversationKnowledgeIds
450003
450038
  const refConversationKnowledgeIds = (0,react_.useRef)(conversationKnowledgeIds);
450004
450039
  shortcutsRef.current = shortcuts;
@@ -450182,6 +450217,7 @@ class MessageParser {
450182
450217
  sectionId: conversationResult.sectionId || "",
450183
450218
  conversationName: conversationResult.conversationName
450184
450219
  };
450220
+ refStreamAlreadySucceeded.current = false;
450185
450221
  // 立即添加会话到列表,使用创建时返回的名称
450186
450222
  const existingConversation = refConversations.current.find((c)=>c.id === conversationResult.conversationId);
450187
450223
  if (!existingConversation && refUpdateConversations.current) {
@@ -450205,20 +450241,32 @@ class MessageParser {
450205
450241
  conversationId: conversationResult.conversationId,
450206
450242
  conversationName: conversationResult.conversationName
450207
450243
  });
450244
+ // 立即更新 currentConversationInfo,使会话历史中新 item 显示选中样式(fragmentKey 已保证不会 remount)
450245
+ const existingInfo = refCurrentConversationInfo.current;
450246
+ refUpdateCurrentConversationInfo.current({
450247
+ ...existingInfo,
450248
+ id: conversationResult.conversationId,
450249
+ last_section_id: conversationResult.sectionId || "",
450250
+ name: conversationResult.conversationName || "",
450251
+ ...isAppType && {
450252
+ title: ""
450253
+ },
450254
+ created_at: newConversation.created_at,
450255
+ updated_at: newConversation.updated_at,
450256
+ meta_data: {},
450257
+ conversationListVisible: (existingInfo === null || existingInfo === void 0 ? void 0 : existingInfo.conversationListVisible) ?? false,
450258
+ isLargeWidth: (existingInfo === null || existingInfo === void 0 ? void 0 : existingInfo.isLargeWidth) ?? false
450259
+ });
450208
450260
  }
450209
- // 选中新创建的会话:先更新 currentConversationInfo,确保会话被选中
450210
- // 不立即调用 updateCurrentConversationInfo,避免触发组件卸载
450211
- // 将在消息流完成(DONE 事件)时更新 currentConversationInfo
450212
- // 这样可以避免触发 useRequestInit 的依赖变化,防止重新初始化
450213
- // 会话列表中的新会话已经通过 updateConversations 添加,可以正常显示
450214
- console.log("onBeforeSendMessage: Conversation created, will update currentConversationInfo after stream completes", {
450215
- conversationId: conversationResult.conversationId
450216
- });
450261
+ // 选中新创建的会话:currentConversationInfo 已在上方更新,会话列表会显示选中样式
450217
450262
  // 确保 pendingInfo 被设置,以便在 DONE 事件时更新
450218
- if (refPendingConversationInfo) refPendingConversationInfo.current = {
450219
- conversationId: conversationResult.conversationId,
450220
- sectionId: conversationResult.sectionId || ""
450221
- };
450263
+ if (refPendingConversationInfo) {
450264
+ refPendingConversationInfo.current = {
450265
+ conversationId: conversationResult.conversationId,
450266
+ sectionId: conversationResult.sectionId || ""
450267
+ };
450268
+ refStreamAlreadySucceeded.current = false;
450269
+ }
450222
450270
  // 注意:不在这里调用 setConversationId,因为它会触发额外的 updateConversations 调用
450223
450271
  // 这会导致 useConversationList 的同步逻辑被触发,设置 isSyncing = true
450224
450272
  // 当真正的 store 更新发生时,isSyncing 仍然是 true,导致 useEffect 被跳过
@@ -450289,8 +450337,18 @@ class MessageParser {
450289
450337
  ...configSetting,
450290
450338
  ...bodySetting
450291
450339
  };
450292
- // 新增:合并会话 section 关联的知识库 ID SETTING.KNOWLEDGE_IDS
450293
- // 直接从 store 获取最新值,避免 ref 因 React 渲染时机延迟导致数据不是最新
450340
+ // 提前解析 body 中的 knowledge_ids(文件上传等),与 store 一起参与 SETTING.KNOWLEDGE_IDS 合并
450341
+ const parsedBodyForKnowledge = catchParse(requestConfig.body) || {};
450342
+ let existingBodyKnowledgeIds = [];
450343
+ if (parsedBodyForKnowledge.knowledge_ids) existingBodyKnowledgeIds = Array.isArray(parsedBodyForKnowledge.knowledge_ids) ? parsedBodyForKnowledge.knowledge_ids.map(String) : typeof parsedBodyForKnowledge.knowledge_ids === "string" ? (()=>{
450344
+ try {
450345
+ return JSON.parse(parsedBodyForKnowledge.knowledge_ids);
450346
+ } catch {
450347
+ return [];
450348
+ }
450349
+ })() : [];
450350
+ // 合并会话 section 关联的知识库 ID 与本次 body 的 knowledge_ids 到 SETTING.KNOWLEDGE_IDS
450351
+ // 来源:mergedSetting 已有、store(ref)、body.knowledge_ids,保证第二次发送仍带上前一次的知识库
450294
450352
  let knowledgeIdsFromConversation = [];
450295
450353
  try {
450296
450354
  var _refStore_current;
@@ -450299,54 +450357,44 @@ class MessageParser {
450299
450357
  } catch {
450300
450358
  knowledgeIdsFromConversation = refConversationKnowledgeIds.current || [];
450301
450359
  }
450302
- if (knowledgeIdsFromConversation.length > 0) {
450303
- // 获取已有的 KNOWLEDGE_IDS
450304
- let existingIds = [];
450305
- if (mergedSetting.KNOWLEDGE_IDS) {
450306
- if (Array.isArray(mergedSetting.KNOWLEDGE_IDS)) existingIds = mergedSetting.KNOWLEDGE_IDS.map(String);
450307
- else if (typeof mergedSetting.KNOWLEDGE_IDS === "string") try {
450308
- existingIds = JSON.parse(mergedSetting.KNOWLEDGE_IDS);
450309
- } catch {
450310
- existingIds = [];
450311
- }
450360
+ let existingIds = [];
450361
+ if (mergedSetting.KNOWLEDGE_IDS) {
450362
+ if (Array.isArray(mergedSetting.KNOWLEDGE_IDS)) existingIds = mergedSetting.KNOWLEDGE_IDS.map(String);
450363
+ else if (typeof mergedSetting.KNOWLEDGE_IDS === "string") try {
450364
+ existingIds = JSON.parse(mergedSetting.KNOWLEDGE_IDS);
450365
+ } catch {
450366
+ existingIds = [];
450312
450367
  }
450313
- // 合并并去重
450314
- const allIds = [
450315
- ...existingIds,
450316
- ...knowledgeIdsFromConversation
450317
- ];
450318
- const uniqueIds = Array.from(new Set(allIds));
450319
- if (uniqueIds.length > 0) mergedSetting.KNOWLEDGE_IDS = uniqueIds;
450320
- console.log("onBeforeSendMessage: Merged conversation knowledge IDs into parameters", {
450321
- knowledgeIdsFromConversation,
450322
- existingIds,
450323
- uniqueIds
450324
- });
450325
450368
  }
450369
+ const allIds = [
450370
+ ...existingIds,
450371
+ ...knowledgeIdsFromConversation,
450372
+ ...existingBodyKnowledgeIds
450373
+ ];
450374
+ const uniqueIds = Array.from(new Set(allIds));
450375
+ if (uniqueIds.length > 0) {
450376
+ mergedSetting.KNOWLEDGE_IDS = uniqueIds;
450377
+ // 将本次请求使用的知识库 ID 同步到 store,保证下次发送(无 body knowledge_ids 时)仍能带上
450378
+ setConversationKnowledgeIds(uniqueIds);
450379
+ }
450380
+ if (uniqueIds.length > 0) console.log("onBeforeSendMessage: Merged conversation knowledge IDs into parameters", {
450381
+ knowledgeIdsFromConversation,
450382
+ existingBodyKnowledgeIds,
450383
+ existingIds,
450384
+ uniqueIds
450385
+ });
450326
450386
  // 将合并后的 SETTING 设回 parameters
450327
450387
  if (Object.keys(mergedSetting).length > 0) mergedParameters.SETTING = mergedSetting;
450328
450388
  console.log("onBeforeSendMessage: Final mergedParameters", mergedParameters);
450329
450389
  // 更新 requestConfig.body 中的 conversation_id
450330
450390
  // 同时将会话知识库 ID 写入 body 的 knowledge_ids 字段
450331
- // 这样 builder-chat 的 onBeforeSendMessage hook 可以从 body 中读取
450332
- // 并合并到最终的 parameters.SETTING.KNOWLEDGE_IDS
450333
- const parsedBody = catchParse(requestConfig.body) || {};
450334
- // 合并已有的 knowledge_ids(来自文件上传等)和会话知识库 ID
450335
- let existingBodyKnowledgeIds = [];
450336
- if (parsedBody.knowledge_ids) existingBodyKnowledgeIds = Array.isArray(parsedBody.knowledge_ids) ? parsedBody.knowledge_ids.map(String) : typeof parsedBody.knowledge_ids === "string" ? (()=>{
450337
- try {
450338
- return JSON.parse(parsedBody.knowledge_ids);
450339
- } catch {
450340
- return [];
450341
- }
450342
- })() : [];
450343
450391
  const combinedKnowledgeIds = [
450344
450392
  ...existingBodyKnowledgeIds,
450345
450393
  ...knowledgeIdsFromConversation
450346
450394
  ];
450347
450395
  const uniqueBodyKnowledgeIds = Array.from(new Set(combinedKnowledgeIds));
450348
450396
  const updatedBodyObj = {
450349
- ...parsedBody,
450397
+ ...parsedBodyForKnowledge,
450350
450398
  conversation_id: conversationId
450351
450399
  };
450352
450400
  // 只在有知识库 ID 时才添加 knowledge_ids 字段
@@ -450408,110 +450456,137 @@ class MessageParser {
450408
450456
  sectionId: refChatFunc === null || refChatFunc === void 0 ? void 0 : (_refChatFunc_current = refChatFunc.current) === null || _refChatFunc_current === void 0 ? void 0 : _refChatFunc_current.getSectionId(),
450409
450457
  onConversationUpdate: handleConversationUpdateRef.current || undefined
450410
450458
  });
450411
- // 如果有待更新的 conversation 信息,在收到第一条消息(CHAT_CREATED)时更新会话列表
450412
- // 在消息流完成(DONE)时更新 currentConversationInfo 和 chatCore 的 conversationId
450413
- if (refPendingConversationInfo.current && originalParser) {
450414
- let hasUpdatedConversationList = false;
450415
- let hasUpdatedChatCore = false;
450459
+ // pending 时在 CHAT_CREATED/DONE 时更新会话状态;每次 DONE 时都刷新知识库列表
450460
+ if (!originalParser) return undefined;
450461
+ let hasUpdatedConversationList = false;
450462
+ let hasUpdatedChatCore = false;
450463
+ return (parseEvent, method)=>{
450416
450464
  const pendingInfo = refPendingConversationInfo.current;
450417
- return (parseEvent, method)=>{
450418
- if (!originalParser) return undefined;
450419
- const result = originalParser(parseEvent, method);
450420
- // 检查事件类型
450421
- const { type, event } = parseEvent;
450422
- const isChatCreatedEvent = type === "event" && event === "conversation.chat.created";
450423
- const isDoneEvent = type === "event" && event === "done";
450424
- // 在收到第一条消息(CHAT_CREATED)时更新会话列表和 currentConversationInfo
450425
- // 更新 currentConversationInfo 以确保会话列表中的新会话显示为选中状态
450426
- // 只更新 id last_section_id,不更新 name,避免触发不必要的重新初始化
450427
- if (isChatCreatedEvent && !hasUpdatedConversationList && pendingInfo.conversationId) {
450428
- hasUpdatedConversationList = true;
450429
- console.log("onGetMessageStreamParser: Updating conversation list and currentConversationInfo after CHAT_CREATED", {
450430
- conversationId: pendingInfo.conversationId
450431
- });
450432
- // 检查会话是否已经存在于列表中,避免重复添加
450433
- const existingConversation = refConversations.current.find((c)=>c.id === pendingInfo.conversationId);
450434
- // 如果会话不存在,才更新会话列表
450435
- // 注意:会话已经在创建时添加到列表了,这里主要是为了兼容性检查
450436
- if (!existingConversation) {
450437
- const chatType = refChatConfig.current.type;
450438
- const isAppType = chatType === client_ChatType.APP;
450439
- const newConversation = {
450440
- id: pendingInfo.conversationId,
450441
- last_section_id: pendingInfo.sectionId,
450442
- // 使用创建时返回的名称
450443
- name: pendingInfo.conversationName || "",
450444
- created_at: Math.floor(Date.now() / 1000),
450445
- updated_at: Math.floor(Date.now() / 1000),
450446
- meta_data: {},
450447
- // App 模式需要 title 字段
450448
- ...isAppType && pendingInfo.conversationName && {
450449
- title: pendingInfo.conversationName
450450
- }
450451
- };
450452
- if (refUpdateConversations.current) refUpdateConversations.current([
450453
- newConversation
450454
- ], "add");
450455
- }
450456
- // 在 CHAT_CREATED 时,只添加会话到列表,不更新 currentConversationInfo
450457
- // 这样可以避免触发 useRequestInit 的依赖变化,防止重新初始化
450458
- // 但是,我们需要确保 chatCore 的 conversationId 被更新,以便消息流能正常继续
450459
- // 通过 refChatFunc.setConversationId 更新,但只更新 chatCore,不更新 currentConversationInfo
450460
- // 注意:setConversationId 会检查会话是否存在,如果存在就不会添加,所以是安全的
450461
- // 但是,setConversationId 也会更新 currentConversationInfo,这可能会触发重新初始化
450462
- // 所以我们需要延迟更新,或者找到其他方式更新 chatCore 的 conversationId
450463
- // 暂时不更新 currentConversationInfo,让 DONE 事件时再更新
450464
- // 这样可以避免触发重新初始化,但会话列表中的新会话不会立即显示为选中状态
450465
- // 这是可以接受的,因为用户正在查看消息流,不会立即点击会话列表
450465
+ const isErrorEvent = parseEvent.type === "event" && parseEvent.event === "error";
450466
+ if (isErrorEvent && refStreamAlreadySucceeded.current) return undefined;
450467
+ const result = originalParser(parseEvent, method);
450468
+ const { type, event } = parseEvent;
450469
+ const isChatCreatedEvent = type === "event" && event === "conversation.chat.created";
450470
+ const isDoneEvent = type === "event" && event === "done";
450471
+ // 空会话首条消息时 workflow 可能不推送 conversation.chat.created,流结束只有 DONE,chat-core 收不到 ack 会触发 MESSAGE_SEND_FAIL。在 DONE 且存在 pending 时补发合成 ack,使 sendMessage 正常 resolve
450472
+ const shouldReturnSyntheticAck = isDoneEvent && pendingInfo;
450473
+ // pending 时:在 CHAT_CREATED 时更新会话列表
450474
+ if (pendingInfo && isChatCreatedEvent && !hasUpdatedConversationList && pendingInfo.conversationId) {
450475
+ hasUpdatedConversationList = true;
450476
+ console.log("onGetMessageStreamParser: Updating conversation list and currentConversationInfo after CHAT_CREATED", {
450477
+ conversationId: pendingInfo.conversationId
450478
+ });
450479
+ const existingConversation = refConversations.current.find((c)=>c.id === pendingInfo.conversationId);
450480
+ if (!existingConversation) {
450481
+ const chatType = refChatConfig.current.type;
450482
+ const isAppType = chatType === client_ChatType.APP;
450483
+ const newConversation = {
450484
+ id: pendingInfo.conversationId,
450485
+ last_section_id: pendingInfo.sectionId,
450486
+ name: pendingInfo.conversationName || "",
450487
+ created_at: Math.floor(Date.now() / 1000),
450488
+ updated_at: Math.floor(Date.now() / 1000),
450489
+ meta_data: {},
450490
+ ...isAppType && pendingInfo.conversationName && {
450491
+ title: pendingInfo.conversationName
450492
+ }
450493
+ };
450494
+ if (refUpdateConversations.current) refUpdateConversations.current([
450495
+ newConversation
450496
+ ], "add");
450466
450497
  }
450467
- // 在消息流完成(DONE)时更新 currentConversationInfo 和 chatCore 的 conversationId
450468
- // 注意:不更新 name,让 useUpdateConversationNameByMessage hook 在收到第一条消息后自动更新
450469
- // 这样可以避免 name 的变化触发 useRequestInit 的依赖变化,防止重新初始化
450470
- if (isDoneEvent && !hasUpdatedChatCore && pendingInfo.conversationId) {
450498
+ }
450499
+ // DONE 时:若有 pending 则更新 currentConversationInfo 和 chatCore;并始终刷新知识库列表(含发送带文件消息后)
450500
+ if (isDoneEvent) {
450501
+ var _refChatFunc_current_getConversationId, _refChatFunc_current, _refChatFunc_current_getSectionId, _refChatFunc_current1, _refChatConfig_current_appInfo, _refChatConfig_current, _refChatConfig_current1;
450502
+ const conversationId = (pendingInfo === null || pendingInfo === void 0 ? void 0 : pendingInfo.conversationId) || (refChatFunc === null || refChatFunc === void 0 ? void 0 : (_refChatFunc_current = refChatFunc.current) === null || _refChatFunc_current === void 0 ? void 0 : (_refChatFunc_current_getConversationId = _refChatFunc_current.getConversationId) === null || _refChatFunc_current_getConversationId === void 0 ? void 0 : _refChatFunc_current_getConversationId.call(_refChatFunc_current));
450503
+ const sectionId = (pendingInfo === null || pendingInfo === void 0 ? void 0 : pendingInfo.sectionId) || (refChatFunc === null || refChatFunc === void 0 ? void 0 : (_refChatFunc_current1 = refChatFunc.current) === null || _refChatFunc_current1 === void 0 ? void 0 : (_refChatFunc_current_getSectionId = _refChatFunc_current1.getSectionId) === null || _refChatFunc_current_getSectionId === void 0 ? void 0 : _refChatFunc_current_getSectionId.call(_refChatFunc_current1));
450504
+ const appId = ((_refChatConfig_current = refChatConfig.current) === null || _refChatConfig_current === void 0 ? void 0 : (_refChatConfig_current_appInfo = _refChatConfig_current.appInfo) === null || _refChatConfig_current_appInfo === void 0 ? void 0 : _refChatConfig_current_appInfo.appId) || ((_refChatConfig_current1 = refChatConfig.current) === null || _refChatConfig_current1 === void 0 ? void 0 : _refChatConfig_current1.bot_id) || "";
450505
+ if (cozeApiSdk && conversationId && sectionId && appId && setConversationKnowledgeIds) getConversationKnowledges({
450506
+ cozeApiSdk,
450507
+ conversationId,
450508
+ sectionId,
450509
+ appId
450510
+ }).then((knowledgeIds)=>{
450511
+ // 仅当接口返回非空时更新 store,避免返回 [] 时清空已有知识库导致第二次发送缺少 KNOWLEDGE_IDS
450512
+ if (Array.isArray(knowledgeIds) && knowledgeIds.length > 0) setConversationKnowledgeIds(knowledgeIds);
450513
+ }).catch((e)=>{
450514
+ console.warn("Failed to refresh conversation knowledges after chat:", e);
450515
+ });
450516
+ if (pendingInfo && !hasUpdatedChatCore && pendingInfo.conversationId) {
450471
450517
  var _refCurrentConversationInfo_current;
450472
450518
  hasUpdatedChatCore = true;
450473
450519
  console.log("onGetMessageStreamParser: Updating currentConversationInfo and chatCore after stream done", {
450474
450520
  conversationId: pendingInfo.conversationId
450475
450521
  });
450476
- // 检查当前的 currentConversationInfo.id 是否已经是我们要设置的 conversationId
450477
450522
  const currentId = (_refCurrentConversationInfo_current = refCurrentConversationInfo.current) === null || _refCurrentConversationInfo_current === void 0 ? void 0 : _refCurrentConversationInfo_current.id;
450478
450523
  if (currentId === pendingInfo.conversationId) {
450479
450524
  console.log("onGetMessageStreamParser: Conversation ID already matches, only updating chatCore", {
450480
450525
  conversationId: pendingInfo.conversationId
450481
450526
  });
450482
- // 即使 ID 相同,也要更新 chatCore 的 conversationId
450483
450527
  if (refChatFunc === null || refChatFunc === void 0 ? void 0 : refChatFunc.current) refChatFunc.current.setConversationId(pendingInfo.conversationId, pendingInfo.sectionId);
450484
450528
  refPendingConversationInfo.current = null;
450485
450529
  return result;
450486
450530
  }
450487
- // 使用 setTimeout 确保在消息发送流程完全完成后更新状态
450488
450531
  setTimeout(()=>{
450489
450532
  if (refUpdateCurrentConversationInfo.current) {
450490
- // 保留当前的 conversationListVisible 和 isLargeWidth,避免会话列表被收起
450491
450533
  const currentInfo = refCurrentConversationInfo.current;
450492
450534
  refUpdateCurrentConversationInfo.current({
450493
450535
  id: pendingInfo.conversationId,
450494
450536
  last_section_id: pendingInfo.sectionId,
450495
- // 不设置 name,让 useUpdateConversationNameByMessage hook 自动更新
450496
450537
  name: "",
450497
450538
  created_at: Math.floor(Date.now() / 1000),
450498
450539
  updated_at: Math.floor(Date.now() / 1000),
450499
450540
  meta_data: {},
450500
- // 保留当前的 conversationListVisible,避免会话列表被收起
450501
450541
  conversationListVisible: (currentInfo === null || currentInfo === void 0 ? void 0 : currentInfo.conversationListVisible) ?? false,
450502
- // 保留当前的 isLargeWidth
450503
450542
  isLargeWidth: (currentInfo === null || currentInfo === void 0 ? void 0 : currentInfo.isLargeWidth) ?? false
450504
450543
  });
450505
450544
  }
450506
450545
  if (refChatFunc === null || refChatFunc === void 0 ? void 0 : refChatFunc.current) refChatFunc.current.setConversationId(pendingInfo.conversationId, pendingInfo.sectionId);
450507
- // 清除 pending 信息
450508
450546
  refPendingConversationInfo.current = null;
450509
450547
  }, 0);
450510
450548
  }
450511
- return result;
450512
- };
450513
- }
450514
- return originalParser;
450549
+ }
450550
+ if (shouldReturnSyntheticAck && pendingInfo) {
450551
+ const localMessageId = (requestMessageRawBody === null || requestMessageRawBody === void 0 ? void 0 : requestMessageRawBody.local_message_id) || "";
450552
+ const replyId = pendingInfo.conversationId || `--ack--${localMessageId}`;
450553
+ refStreamAlreadySucceeded.current = true;
450554
+ const extraInfo = {
450555
+ local_message_id: localMessageId,
450556
+ input_tokens: "",
450557
+ output_tokens: "",
450558
+ token: "",
450559
+ plugin_status: "",
450560
+ time_cost: "",
450561
+ workflow_tokens: "",
450562
+ bot_state: "",
450563
+ plugin_request: "",
450564
+ tool_name: "",
450565
+ plugin: "",
450566
+ execute_display_name: ""
450567
+ };
450568
+ const syntheticAck = {
450569
+ event: "message",
450570
+ data: {
450571
+ index: 0,
450572
+ seq_id: 0,
450573
+ is_finish: true,
450574
+ message: {
450575
+ type: "ack",
450576
+ message_id: replyId,
450577
+ reply_id: replyId,
450578
+ section_id: pendingInfo.sectionId || "",
450579
+ content_type: types_ContentType.Text,
450580
+ content: "",
450581
+ extra_info: extraInfo,
450582
+ role: "user"
450583
+ }
450584
+ }
450585
+ };
450586
+ return syntheticAck;
450587
+ }
450588
+ return result;
450589
+ };
450515
450590
  }
450516
450591
  }
450517
450592
  };
@@ -450535,19 +450610,20 @@ class MessageParser {
450535
450610
  */
450536
450611
 
450537
450612
  const useClearHistoryAdapter = (param)=>{
450538
- let { refChatFunc } = param;
450613
+ let { refChatFunc, onAfterCreateConversation } = param;
450539
450614
  var _chatConfig_auth;
450540
450615
  const { chatConfig } = context_useChatAppProps();
450541
450616
  const refConnectorId = (0,react_.useRef)("");
450542
450617
  refConnectorId.current = (chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_auth = chatConfig.auth) === null || _chatConfig_auth === void 0 ? void 0 : _chatConfig_auth.connectorId) || "";
450543
450618
  return (0,react_.useMemo)(()=>{
450544
450619
  const onAfterResponse = [
450545
- (response)=>{
450620
+ async (response)=>{
450546
450621
  var _refChatFunc_current;
450547
450622
  const { data: resCreateConversation } = response;
450548
450623
  const { code, data: conversationData } = resCreateConversation;
450549
450624
  const { id: conversationId, last_section_id: sectionId } = conversationData || {};
450550
450625
  refChatFunc === null || refChatFunc === void 0 || (_refChatFunc_current = refChatFunc.current) === null || _refChatFunc_current === void 0 || _refChatFunc_current.setConversationId(conversationId, sectionId);
450626
+ if (conversationId && sectionId && onAfterCreateConversation) await onAfterCreateConversation(conversationId, sectionId);
450551
450627
  return {
450552
450628
  ...response,
450553
450629
  data: {
@@ -450578,7 +450654,9 @@ const useClearHistoryAdapter = (param)=>{
450578
450654
  }
450579
450655
  };
450580
450656
  return config;
450581
- }, []);
450657
+ }, [
450658
+ onAfterCreateConversation
450659
+ ]);
450582
450660
  };
450583
450661
 
450584
450662
  ;// CONCATENATED MODULE: ../open-chat/src/components/studio-open-chat/provider/coz-sdk/api-adapter/use-common-hooks.ts
@@ -450719,24 +450797,47 @@ const useBreakMessage = ()=>(0,react_.useMemo)(()=>{
450719
450797
 
450720
450798
 
450721
450799
 
450800
+
450722
450801
  const useCoreManager = (param)=>{
450723
450802
  let { refChatFunc } = param;
450803
+ var _chatConfig_appInfo;
450724
450804
  const userInfo = useUserInfo();
450725
- const { refreshToken } = context_useChatCozeSdk();
450805
+ const { refreshToken, cozeApiSdk } = context_useChatCozeSdk();
450806
+ const { chatConfig, requestManagerOptions } = context_useChatAppProps();
450807
+ const setConversationKnowledgeIds = context_useChatAppStore((s)=>s.setConversationKnowledgeIds);
450726
450808
  // 获取 apiUrl
450727
450809
  const { apiUrl } = context_useChatAppStore(shallow_useShallow((s)=>({
450728
450810
  apiUrl: s.apiUrl
450729
450811
  })));
450812
+ // 删除对话记录(创建新 conversation)成功后,重新拉取 workflows/conversation/knowledges 更新知识库列表
450813
+ const onAfterCreateConversation = (0,react_.useCallback)(async (conversationId, sectionId)=>{
450814
+ var _chatConfig_appInfo;
450815
+ if (!cozeApiSdk) return;
450816
+ const appId = (chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo = chatConfig.appInfo) === null || _chatConfig_appInfo === void 0 ? void 0 : _chatConfig_appInfo.appId) || (chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.bot_id) || "";
450817
+ if (!appId) return;
450818
+ const knowledgeIds = await getConversationKnowledges({
450819
+ cozeApiSdk,
450820
+ conversationId,
450821
+ sectionId,
450822
+ appId
450823
+ });
450824
+ setConversationKnowledgeIds(knowledgeIds);
450825
+ }, [
450826
+ cozeApiSdk,
450827
+ chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig_appInfo = chatConfig.appInfo) === null || _chatConfig_appInfo === void 0 ? void 0 : _chatConfig_appInfo.appId,
450828
+ chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.bot_id,
450829
+ setConversationKnowledgeIds
450830
+ ]);
450730
450831
  const clearMessageContextAdapter = useClearMessageContextAdapter();
450731
450832
  const sendMessageAdapter = useSendMessageAdapter(userInfo || undefined, refChatFunc);
450732
450833
  const clearHistoryAdapter = useClearHistoryAdapter({
450733
- refChatFunc
450834
+ refChatFunc,
450835
+ onAfterCreateConversation
450734
450836
  });
450735
450837
  const commonOnBeforeRequestHooks = useCommonOnBeforeRequestHooks();
450736
450838
  const commonOnAfterResponseHooks = useCommonOnAfterResponseHooks(refreshToken);
450737
450839
  const commonErrorResponseHooks = useCommonErrorResponseHooks(refreshToken);
450738
450840
  const messageListAdapter = useMessageList();
450739
- const { requestManagerOptions } = context_useChatAppProps();
450740
450841
  const breakMessageAdapter = useBreakMessage();
450741
450842
  // 计算最终的 baseURL
450742
450843
  const finalBaseURL = apiUrl || openApiHostByRegionWithToken;
@@ -465395,6 +465496,8 @@ const StudioChatArea = (param)=>{
465395
465496
  const refContainer = (0,react_.useRef)(null);
465396
465497
  const { readonly } = context_useChatAppProps();
465397
465498
  const currentConversationInfo = context_useChatAppStore((state)=>state.currentConversationInfo);
465499
+ const updateConversations = context_useChatAppStore((state)=>state.updateConversations);
465500
+ const conversations = context_useChatAppStore((state)=>state.conversations);
465398
465501
  // Get apiUrl from store for knowledge upload
465399
465502
  const apiUrl = context_useChatAppStore((state)=>state.apiUrl);
465400
465503
  // Get updateCurrentConversationInfo from store for knowledge upload
@@ -465486,7 +465589,6 @@ const StudioChatArea = (param)=>{
465486
465589
  // Pass updateCurrentConversationInfo callback so file upload can update the store
465487
465590
  updateCurrentConversationInfo: (info)=>{
465488
465591
  // Update currentConversationInfo with the new conversation info
465489
- // Merge with existing to preserve other fields
465490
465592
  updateCurrentConversationInfo({
465491
465593
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- currentConversationInfo may have additional fields not in type definition
465492
465594
  ...currentConversationInfo,
@@ -465494,6 +465596,20 @@ const StudioChatArea = (param)=>{
465494
465596
  last_section_id: info.last_section_id,
465495
465597
  name: info.name
465496
465598
  });
465599
+ // 上传文件创建新会话时,将会话加入会话历史列表,否则列表中看不到新会话
465600
+ if (info.id && !conversations.some((c)=>c.id === info.id)) {
465601
+ const timestamp = Math.floor(Date.now() / 1000);
465602
+ updateConversations([
465603
+ {
465604
+ id: info.id,
465605
+ last_section_id: info.last_section_id ?? "",
465606
+ name: info.name ?? "",
465607
+ created_at: timestamp,
465608
+ updated_at: timestamp,
465609
+ meta_data: {}
465610
+ }
465611
+ ], "add");
465612
+ }
465497
465613
  }
465498
465614
  }
465499
465615
  }