@glodon-aiot/chat-app-sdk 0.0.7 → 0.0.8

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
@@ -395273,7 +395273,9 @@ const DeferredMessageBoxProvider = (param)=>{
395273
395273
  } : originalMeta, [
395274
395274
  originalMeta
395275
395275
  ]);
395276
- return /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
395276
+ return(// 使用 renderIndex 作为 CSS order 值
395277
+ // 正数区域(正常渲染):renderIndex 越大,order 越大,元素越靠上
395278
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
395277
395279
  style: {
395278
395280
  order: renderIndex ?? 0
395279
395281
  },
@@ -395288,7 +395290,7 @@ const DeferredMessageBoxProvider = (param)=>{
395288
395290
  },
395289
395291
  children: children
395290
395292
  })
395291
- });
395293
+ }));
395292
395294
  };
395293
395295
  // 正常消息的 MessageBoxProvider,确保第一个正常消息显示头像
395294
395296
  const NormalMessageBoxProvider = (param)=>{
@@ -395315,7 +395317,9 @@ const NormalMessageBoxProvider = (param)=>{
395315
395317
  originalMeta,
395316
395318
  isFirstNormalMessage
395317
395319
  ]);
395318
- return /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
395320
+ return(// 使用 renderIndex 作为 CSS order 值
395321
+ // 正数区域(正常渲染):renderIndex 越大,order 越大,元素越靠上
395322
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
395319
395323
  style: {
395320
395324
  order: renderIndex ?? 0
395321
395325
  },
@@ -395330,7 +395334,7 @@ const NormalMessageBoxProvider = (param)=>{
395330
395334
  },
395331
395335
  children: children
395332
395336
  })
395333
- });
395337
+ }));
395334
395338
  };
395335
395339
  // Hook for debugging message meta info
395336
395340
  function useMessageDebugLog(normalMessages, deferredMessages) {
@@ -395409,7 +395413,8 @@ const DeferredMessages = (param)=>{
395409
395413
  const NormalMessages = (param)=>{
395410
395414
  let { normalMessages, deferredMessages, groupId, regenerateMessage, functionCallMessageIdList } = param;
395411
395415
  const regenerateMessagePromise = ()=>Promise.resolve(regenerateMessage());
395412
- // 找到 renderIndex 最大的消息(order 最大,会显示在最前面)
395416
+ // 找到 renderIndex 最大的消息(CSS order 最大)
395417
+ // 注意:由于 flex-direction: column-reverse,order 最大的消息在视觉上最靠上
395413
395418
  const maxRenderIndex = (0,react.useMemo)(()=>{
395414
395419
  if (normalMessages.length === 0) {
395415
395420
  return -Infinity;
@@ -395418,12 +395423,20 @@ const NormalMessages = (param)=>{
395418
395423
  }, [
395419
395424
  normalMessages
395420
395425
  ]);
395421
- // 找到第一个具有最大 renderIndex 的消息的索引
395426
+ // 找到最后一个具有最大 renderIndex 的消息的索引
395427
+ // 由于 flex-direction: column-reverse,数组中的最后一个元素在视觉上最靠上
395422
395428
  const maxRenderIndexMessageIndex = (0,react.useMemo)(()=>{
395423
395429
  if (normalMessages.length === 0) {
395424
395430
  return -1;
395425
395431
  }
395426
- return normalMessages.findIndex((m)=>m.renderIndex === maxRenderIndex);
395432
+ // 从后往前找,找到最后一个具有最大 renderIndex 的消息
395433
+ for(let i = normalMessages.length - 1; i >= 0; i--){
395434
+ const message = normalMessages[i];
395435
+ if (message && message.renderIndex === maxRenderIndex) {
395436
+ return i;
395437
+ }
395438
+ }
395439
+ return -1;
395427
395440
  }, [
395428
395441
  normalMessages,
395429
395442
  maxRenderIndex
@@ -395431,7 +395444,8 @@ const NormalMessages = (param)=>{
395431
395444
  return /*#__PURE__*/ (0,jsx_runtime.jsx)(jsx_runtime.Fragment, {
395432
395445
  children: normalMessages.map((param, index)=>{
395433
395446
  let { messageId, renderIndex } = param;
395434
- // order 最大的消息显示头像(renderIndex 最大的消息,如果有多个则只显示第一个)
395447
+ // CSS order 最大的消息,且在视觉上最靠上的(数组中的最后一个)显示头像
395448
+ // 由于 flex-direction: column-reverse,数组中的最后一个元素在视觉上最靠上
395435
395449
  const isFirstNormalMessage = renderIndex === maxRenderIndex && index === maxRenderIndexMessageIndex;
395436
395450
  const isFirst = isFirstNormalMessage;
395437
395451
  const isLast = index === 0 && deferredMessages.length === 0 && !functionCallMessageIdList.length;
@@ -395482,7 +395496,8 @@ const MessageGroupBody = /*#__PURE__*/ (0,react.memo)((param)=>{
395482
395496
  });
395483
395497
  // 分离正常渲染和延迟渲染的消息
395484
395498
  // 不再排序,使用 CSS order 属性来控制顺序
395485
- // renderIndex 值越小,order 越小,在 flex 容器中会显示越靠后
395499
+ // 正数区域(正常渲染):renderIndex 值越大,order 越大,在 flex 容器中会显示越靠上
395500
+ // 负数区域(延迟渲染):renderIndex 值越小(绝对值越大),order 越小,在 flex 容器中会显示越靠后
395486
395501
  const normalMessages = messagesWithRenderInfo.filter((item)=>!item.shouldDefer);
395487
395502
  const deferredMessages = messagesWithRenderInfo.filter((item)=>item.shouldDefer);
395488
395503
  // 打印正常消息和延迟消息的 meta 信息用于调试
@@ -405578,8 +405593,9 @@ const chatflowDraftConnectorId = '10000010';
405578
405593
  */
405579
405594
  var conversations_ConversationSort = /*#__PURE__*/ function(ConversationSort) {
405580
405595
  ConversationSort[ConversationSort["Today"] = 0] = "Today";
405581
- ConversationSort[ConversationSort["In30days"] = 1] = "In30days";
405582
- ConversationSort[ConversationSort["Others"] = 999] = "Others";
405596
+ ConversationSort[ConversationSort["Yesterday"] = 1] = "Yesterday";
405597
+ ConversationSort[ConversationSort["In30days"] = 2] = "In30days";
405598
+ ConversationSort[ConversationSort["MonthGroup"] = 999] = "MonthGroup";
405583
405599
  return ConversationSort;
405584
405600
  }({});
405585
405601
  const conversationSortMap = new Map([
@@ -405589,11 +405605,15 @@ const conversationSortMap = new Map([
405589
405605
  ],
405590
405606
  [
405591
405607
  1,
405608
+ intl_i18n.t('profile_history_yesterday', {}, '昨天')
405609
+ ],
405610
+ [
405611
+ 2,
405592
405612
  intl_i18n.t('log_pay_wall_date_filter_30_days', {}, '过去30天')
405593
405613
  ],
405594
405614
  [
405595
405615
  999,
405596
- intl_i18n.t('web_sdk_past', {}, '过往')
405616
+ ''
405597
405617
  ]
405598
405618
  ]);
405599
405619
 
@@ -406594,6 +406614,30 @@ const usePaginationRequest = (param)=>{
406594
406614
  }, [
406595
406615
  initialPageNum
406596
406616
  ]);
406617
+ const removeItem = (0,react.useCallback)((predicate)=>{
406618
+ setAllData((prev)=>prev.filter((item)=>!predicate(item)));
406619
+ }, []);
406620
+ const addItem = (0,react.useCallback)(function(item) {
406621
+ let position = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 'start';
406622
+ setAllData((prev)=>{
406623
+ // 检查是否已存在,避免重复添加
406624
+ if (prev.some((existing)=>{
406625
+ // 假设 T 有 id 属性,如果没有则使用对象引用比较
406626
+ const existingItem = existing;
406627
+ const newItem = item;
406628
+ return existingItem.id !== undefined && newItem.id !== undefined ? existingItem.id === newItem.id : existing === item;
406629
+ })) {
406630
+ return prev;
406631
+ }
406632
+ return position === 'start' ? [
406633
+ item,
406634
+ ...prev
406635
+ ] : [
406636
+ ...prev,
406637
+ item
406638
+ ];
406639
+ });
406640
+ }, []);
406597
406641
  // 组件挂载时自动加载第一页
406598
406642
  (0,react.useEffect)(()=>{
406599
406643
  if (autoLoad) {
@@ -406613,7 +406657,9 @@ const usePaginationRequest = (param)=>{
406613
406657
  loadMore,
406614
406658
  refresh,
406615
406659
  setPageNum,
406616
- reset
406660
+ reset,
406661
+ removeItem,
406662
+ addItem
406617
406663
  };
406618
406664
  };
406619
406665
 
@@ -406640,6 +406686,15 @@ const usePaginationRequest = (param)=>{
406640
406686
 
406641
406687
 
406642
406688
 
406689
+
406690
+
406691
+
406692
+
406693
+
406694
+
406695
+
406696
+
406697
+ // eslint-disable-next-line @coze-arch/max-line-per-function
406643
406698
  const useConversationList = (conversationListParams)=>{
406644
406699
  const { pageSize = 20, initialPageNum = 1, order = 'updated_at' } = conversationListParams ?? {};
406645
406700
  const { chatConfig: { bot_id: botId, appInfo, type: chatType, auth: { connectorId } = {} } } = useChatAppProps();
@@ -406656,6 +406711,9 @@ const useConversationList = (conversationListParams)=>{
406656
406711
  // draft_mode 转换为 create_env:draft_mode: true -> create_env: 1, draft_mode: false -> create_env: 2
406657
406712
  const createEnv = (appInfo === null || appInfo === void 0 ? void 0 : appInfo.draft_mode) !== undefined ? appInfo.draft_mode ? 1 : 2 : undefined;
406658
406713
  const hasValidId = isAppType ? !!appId && !!workflowId : !!botId;
406714
+ // 使用 ref 来跟踪是否正在同步,避免循环更新
406715
+ const isSyncingRef = (0,react.useRef)(false);
406716
+ const lastStoreIdsRef = (0,react.useRef)('');
406659
406717
  // App 模式:使用基于 before_updated_at 和 limit 的加载逻辑
406660
406718
  const [appModeData, setAppModeData] = (0,react.useState)([]);
406661
406719
  const [appModeLoading, setAppModeLoading] = (0,react.useState)(false);
@@ -406763,8 +406821,20 @@ const useConversationList = (conversationListParams)=>{
406763
406821
  beforeUpdatedAt,
406764
406822
  loadAppModeConversations
406765
406823
  ]);
406824
+ // App 模式:refresh 函数,重新加载第一页数据
406825
+ const appModeRefresh = (0,react.useCallback)(async ()=>{
406826
+ // 重置状态,确保可以重新加载
406827
+ setAppModeData([]);
406828
+ setBeforeUpdatedAt(undefined);
406829
+ setAppModeHasMore(true);
406830
+ setAppModeLoading(false);
406831
+ // 重新加载第一页数据
406832
+ await loadAppModeConversations();
406833
+ }, [
406834
+ loadAppModeConversations
406835
+ ]);
406766
406836
  // Bot 模式:继续使用原有的分页逻辑
406767
- const { data, hasMore, loadMore, loading } = usePaginationRequest({
406837
+ const { data, hasMore, loadMore, loading, refresh: refreshBotMode, removeItem: removeBotModeItem, addItem: addBotModeItem } = usePaginationRequest({
406768
406838
  requestFn: async (params)=>{
406769
406839
  if (!cozeApiSdk || !hasValidId) {
406770
406840
  return {
@@ -406796,18 +406866,146 @@ const useConversationList = (conversationListParams)=>{
406796
406866
  initialPageNum,
406797
406867
  autoLoad: !!cozeApiSdk && hasValidId && !isAppType
406798
406868
  });
406869
+ // 从本地数据源移除会话
406870
+ const removeConversation = (0,react.useCallback)((conversationId)=>{
406871
+ // 设置同步标志,防止 useEffect 干扰删除操作
406872
+ isSyncingRef.current = true;
406873
+ if (isAppType) {
406874
+ // App模式:直接更新本地状态
406875
+ setAppModeData((prev)=>prev.filter((c)=>c.id !== conversationId));
406876
+ } else {
406877
+ // Bot模式:从本地数据源移除
406878
+ removeBotModeItem((c)=>c.id === conversationId);
406879
+ }
406880
+ // 延迟重置同步标志,确保删除操作完成
406881
+ setTimeout(()=>{
406882
+ isSyncingRef.current = false;
406883
+ }, 100);
406884
+ }, [
406885
+ isAppType,
406886
+ removeBotModeItem
406887
+ ]);
406799
406888
  // 根据模式选择数据源
406800
406889
  const finalData = isAppType ? appModeData : data;
406801
406890
  const finalLoading = isAppType ? appModeLoading : loading;
406802
406891
  const finalHasMore = isAppType ? appModeHasMore : hasMore;
406803
406892
  const finalLoadMore = isAppType ? appModeLoadMore : loadMore;
406893
+ const finalRefresh = isAppType ? appModeRefresh : refreshBotMode;
406894
+ // 同步 finalData 到 store(只在本地数据源变化时更新 store,避免循环)
406895
+ // 注意:这个 useEffect 只在从服务器加载数据时触发,不会在 store 同步到本地数据源时触发
406804
406896
  (0,react.useEffect)(()=>{
406805
- if (finalData) {
406806
- updateConversations(finalData, 'replace');
406897
+ if (finalData && !isSyncingRef.current) {
406898
+ // 比较数据是否真的变化了,避免不必要的更新
406899
+ const currentIds = conversations.map((c)=>c.id).sort().join(',');
406900
+ const newIds = finalData.map((c)=>c.id).sort().join(',');
406901
+ if (currentIds !== newIds) {
406902
+ // 只有在本地数据源是从服务器加载的新数据时才更新 store
406903
+ // 如果是因为 store 同步导致的 finalData 变化,不应该再次更新 store
406904
+ isSyncingRef.current = true;
406905
+ updateConversations(finalData, 'replace');
406906
+ setTimeout(()=>{
406907
+ isSyncingRef.current = false;
406908
+ }, 0);
406909
+ }
406807
406910
  }
406808
406911
  }, [
406809
406912
  finalData,
406810
- updateConversations
406913
+ updateConversations,
406914
+ conversations
406915
+ ]);
406916
+ // 监听 store 的 conversations 变化,同步更新本地数据源
406917
+ // 只在 store 有新增会话时才同步,避免循环更新
406918
+ (0,react.useEffect)(()=>{
406919
+ const currentStoreIds = conversations.map((c)=>c.id).sort().join(',');
406920
+ // 如果 store 的 ID 列表没有变化,跳过
406921
+ if (currentStoreIds === lastStoreIdsRef.current) {
406922
+ return;
406923
+ }
406924
+ // 检查是否有新增(store 的数量增加了)
406925
+ const storeCount = conversations.length;
406926
+ const lastStoreCount = lastStoreIdsRef.current.split(',').filter(Boolean).length;
406927
+ const hasNewConversations = storeCount > lastStoreCount;
406928
+ const hasDeletedConversations = storeCount < lastStoreCount;
406929
+ // 更新 ref
406930
+ lastStoreIdsRef.current = currentStoreIds;
406931
+ // 如果有删除,同步到本地数据源
406932
+ if (hasDeletedConversations) {
406933
+ // 如果正在同步(可能是删除操作触发的),跳过
406934
+ if (isSyncingRef.current) {
406935
+ return;
406936
+ }
406937
+ if (isAppType) {
406938
+ const storeIds = new Set(conversations.map((c)=>c.id));
406939
+ const localIds = new Set(appModeData.map((c)=>c.id));
406940
+ const deletedIds = Array.from(localIds).filter((id)=>!storeIds.has(id));
406941
+ if (deletedIds.length > 0) {
406942
+ isSyncingRef.current = true;
406943
+ setAppModeData((prev)=>prev.filter((c)=>!deletedIds.includes(c.id)));
406944
+ setTimeout(()=>{
406945
+ isSyncingRef.current = false;
406946
+ }, 0);
406947
+ }
406948
+ } else {
406949
+ const storeIds = new Set(conversations.map((c)=>c.id));
406950
+ const localIds = new Set(data.map((c)=>c.id));
406951
+ const deletedIds = Array.from(localIds).filter((id)=>!storeIds.has(id));
406952
+ if (deletedIds.length > 0) {
406953
+ isSyncingRef.current = true;
406954
+ removeBotModeItem((c)=>deletedIds.includes(c.id));
406955
+ setTimeout(()=>{
406956
+ isSyncingRef.current = false;
406957
+ }, 0);
406958
+ }
406959
+ }
406960
+ return;
406961
+ }
406962
+ // 只在有新增会话时才同步,避免其他变化导致的循环
406963
+ if (!hasNewConversations && storeCount === lastStoreCount) {
406964
+ // 可能是更新,不需要同步
406965
+ return;
406966
+ }
406967
+ // 有新增会话,同步到本地数据源
406968
+ // 注意:即使 isSyncingRef.current 为 true,也要处理新增,因为删除和新增可能同时发生
406969
+ isSyncingRef.current = true;
406970
+ try {
406971
+ if (isAppType) {
406972
+ // App 模式:检查 store 中是否有新会话不在本地数据源中
406973
+ const localIds = new Set(appModeData.map((c)=>c.id));
406974
+ // 找出 store 中有但本地没有的会话(新添加的)
406975
+ const newConversations = conversations.filter((c)=>!localIds.has(c.id));
406976
+ if (newConversations.length > 0) {
406977
+ // 将新会话添加到本地数据源的开头(最新的会话应该在前面)
406978
+ setAppModeData((prev)=>[
406979
+ ...newConversations,
406980
+ ...prev
406981
+ ]);
406982
+ }
406983
+ } else {
406984
+ // Bot 模式:检查 store 中是否有新会话不在本地数据源中
406985
+ const localIds = new Set(data.map((c)=>c.id));
406986
+ // 找出 store 中有但本地没有的会话(新添加的)
406987
+ const newConversations = conversations.filter((c)=>!localIds.has(c.id));
406988
+ if (newConversations.length > 0) {
406989
+ // 将新会话添加到本地数据源的开头(最新的会话应该在前面)
406990
+ newConversations.forEach((conv)=>{
406991
+ addBotModeItem(conv, 'start');
406992
+ });
406993
+ }
406994
+ }
406995
+ } finally{
406996
+ // 使用 setTimeout 确保状态更新完成后再重置标志
406997
+ // 延迟时间稍微长一点,确保第一个 useEffect 不会触发
406998
+ setTimeout(()=>{
406999
+ isSyncingRef.current = false;
407000
+ }, 100);
407001
+ }
407002
+ }, [
407003
+ conversations,
407004
+ isAppType,
407005
+ appModeData,
407006
+ data,
407007
+ removeBotModeItem,
407008
+ addBotModeItem
406811
407009
  ]);
406812
407010
  (0,react.useEffect)(()=>{
406813
407011
  if (!currentConversationInfo) {
@@ -406846,53 +407044,80 @@ const useConversationList = (conversationListParams)=>{
406846
407044
  conversations,
406847
407045
  loading: finalLoading,
406848
407046
  hasMore: finalHasMore,
406849
- loadMore: finalLoadMore
407047
+ loadMore: finalLoadMore,
407048
+ refresh: finalRefresh,
407049
+ removeConversation
406850
407050
  };
406851
407051
  };
406852
407052
  const useGroupedConversations = (conversations)=>{
406853
407053
  const sortedConversations = (0,react.useMemo)(()=>{
406854
- const today = new Date();
406855
- const oneDay = 24 * 60 * 60 * 1000;
406856
- const thirtyDays = 30 * oneDay;
407054
+ const now = dayjs_min_default()();
407055
+ const today = now.startOf('day');
407056
+ const yesterday = today.subtract(1, 'day');
407057
+ const thirtyDaysAgo = today.subtract(30, 'day');
406857
407058
  const newConversationList = conversations.map((item)=>{
406858
- const dateString = item.updated_at || item.created_at || 0;
406859
- const date = dayjs_min_default().unix(Number(dateString)).toDate();
406860
- const diff = today.getTime() - date.getTime();
406861
- if (today.toLocaleDateString() === date.toLocaleDateString()) {
407059
+ // 使用 updated_at 排序
407060
+ const updatedAt = item.updated_at || item.created_at || 0;
407061
+ const date = dayjs_min_default().unix(Number(updatedAt));
407062
+ // 今天
407063
+ if (date.isSame(today, 'day')) {
406862
407064
  return {
406863
407065
  ...item,
406864
407066
  sort: conversations_ConversationSort.Today
406865
407067
  };
406866
- } else if (diff < thirtyDays) {
407068
+ } else if (date.isSame(yesterday, 'day')) {
407069
+ return {
407070
+ ...item,
407071
+ sort: conversations_ConversationSort.Yesterday
407072
+ };
407073
+ } else if (date.isAfter(thirtyDaysAgo)) {
406867
407074
  return {
406868
407075
  ...item,
406869
407076
  sort: conversations_ConversationSort.In30days
406870
407077
  };
406871
407078
  } else {
407079
+ const monthKey = date.format('YYYY-MM');
406872
407080
  return {
406873
407081
  ...item,
406874
- sort: conversations_ConversationSort.Others
407082
+ sort: conversations_ConversationSort.MonthGroup,
407083
+ monthKey
406875
407084
  };
406876
407085
  }
406877
407086
  }).sort((a, b)=>{
407087
+ // 先按分组排序
406878
407088
  if (a.sort !== b.sort) {
406879
407089
  return a.sort - b.sort;
406880
- } else {
406881
- return dayjs_min_default().unix(Number(b.updated_at || b.created_at || 0)).valueOf() - dayjs_min_default().unix(Number(a.updated_at || a.created_at || 0)).valueOf();
406882
407090
  }
407091
+ // 如果是月份分组,先按月份倒序排序(最新的月份在前)
407092
+ if (a.sort === conversations_ConversationSort.MonthGroup && 'monthKey' in a && 'monthKey' in b && a.monthKey && b.monthKey) {
407093
+ if (a.monthKey !== b.monthKey) {
407094
+ return b.monthKey.localeCompare(a.monthKey);
407095
+ }
407096
+ }
407097
+ // 同一分组内,按 updated_at 倒序排序(最新的在前)
407098
+ return dayjs_min_default().unix(Number(b.updated_at || b.created_at || 0)).valueOf() - dayjs_min_default().unix(Number(a.updated_at || a.created_at || 0)).valueOf();
406883
407099
  });
406884
407100
  return newConversationList;
406885
407101
  }, [
406886
407102
  conversations
406887
407103
  ]);
406888
407104
  const groupedConversations = (0,react.useMemo)(()=>{
407105
+ // 使用 Map<string, SortedConversationItem[]>,key 可以是 ConversationSort 或月份字符串
406889
407106
  const groups = new Map();
406890
407107
  sortedConversations.forEach((conversation)=>{
406891
407108
  var _groups_get;
406892
- if (!groups.has(conversation.sort)) {
406893
- groups.set(conversation.sort, []);
407109
+ let groupKey;
407110
+ if (conversation.sort === conversations_ConversationSort.MonthGroup && conversation.monthKey) {
407111
+ // 月份分组使用月份字符串作为 key
407112
+ groupKey = conversation.monthKey;
407113
+ } else {
407114
+ // 其他分组使用 ConversationSort 枚举值作为 key
407115
+ groupKey = String(conversation.sort);
406894
407116
  }
406895
- (_groups_get = groups.get(conversation.sort)) === null || _groups_get === void 0 ? void 0 : _groups_get.push(conversation);
407117
+ if (!groups.has(groupKey)) {
407118
+ groups.set(groupKey, []);
407119
+ }
407120
+ (_groups_get = groups.get(groupKey)) === null || _groups_get === void 0 ? void 0 : _groups_get.push(conversation);
406896
407121
  });
406897
407122
  return groups;
406898
407123
  }, [
@@ -407017,7 +407242,7 @@ var mobile_index_module_update = injectStylesIntoStyleTag_default()(mobile_index
407017
407242
 
407018
407243
 
407019
407244
  const MobileConversationItem = (param)=>{
407020
- let { isActive, item, shouldDisplayTime, onConversationChange, onRename, onDelete } = param;
407245
+ let { isActive, item, shouldDisplayTime, groupTitle, onConversationChange, onRename, onDelete } = param;
407021
407246
  const [visible, setVisible] = (0,react.useState)(false);
407022
407247
  const [isTouched, setIsTouched] = (0,react.useState)(false);
407023
407248
  const longPressTimerRef = (0,react.useRef)(null);
@@ -407064,7 +407289,7 @@ const MobileConversationItem = (param)=>{
407064
407289
  children: [
407065
407290
  shouldDisplayTime ? /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
407066
407291
  className: conversation_item_mobile_index_module["conversation-item-time"],
407067
- children: conversationSortMap.get(item.sort)
407292
+ children: groupTitle || conversationSortMap.get(item.sort)
407068
407293
  }) : null,
407069
407294
  /*#__PURE__*/ (0,jsx_runtime.jsx)(MobileConversationOperate, {
407070
407295
  onRename: ()=>{
@@ -407101,7 +407326,7 @@ const MobileConversationItem = (param)=>{
407101
407326
  ellipsis: {
407102
407327
  showTooltip: {
407103
407328
  opts: {
407104
- content: item.title || item.name,
407329
+ content: item.title || intl_i18n.t('web_sdk_conversation_default_name'),
407105
407330
  style: {
407106
407331
  wordBreak: 'break-all'
407107
407332
  },
@@ -407110,7 +407335,7 @@ const MobileConversationItem = (param)=>{
407110
407335
  }
407111
407336
  }
407112
407337
  },
407113
- children: item.title || item.name || intl_i18n.t('web_sdk_conversation_default_name', {}, '新创建的会话')
407338
+ children: item.title || intl_i18n.t('web_sdk_conversation_default_name')
407114
407339
  })
407115
407340
  })
407116
407341
  }),
@@ -407242,7 +407467,7 @@ var pc_index_module_update = injectStylesIntoStyleTag_default()(pc_index_module/
407242
407467
 
407243
407468
 
407244
407469
  const PcConversationItem = (param)=>{
407245
- let { isActive, item, shouldDisplayTime, onConversationChange, onRename, onDelete } = param;
407470
+ let { isActive, item, shouldDisplayTime, groupTitle, onConversationChange, onRename, onDelete } = param;
407246
407471
  const [visible, setVisible] = (0,react.useState)(false);
407247
407472
  const handleClick = (e)=>{
407248
407473
  e.stopPropagation();
@@ -407254,7 +407479,7 @@ const PcConversationItem = (param)=>{
407254
407479
  children: [
407255
407480
  shouldDisplayTime ? /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
407256
407481
  className: conversation_item_pc_index_module["conversation-item-time"],
407257
- children: conversationSortMap.get(item.sort)
407482
+ children: groupTitle || conversationSortMap.get(item.sort)
407258
407483
  }) : null,
407259
407484
  /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
407260
407485
  className: classnames_default()(conversation_item_pc_index_module["conversation-item-content"], {
@@ -407278,7 +407503,7 @@ const PcConversationItem = (param)=>{
407278
407503
  }
407279
407504
  }
407280
407505
  },
407281
- children: item.title || intl_i18n.t('web_sdk_conversation_default_name', {}, '新创建的会话')
407506
+ children: item.title || intl_i18n.t('web_sdk_conversation_default_name')
407282
407507
  }),
407283
407508
  /*#__PURE__*/ (0,jsx_runtime.jsx)(Operate, {
407284
407509
  onRename: ()=>{
@@ -407361,8 +407586,10 @@ var conversation_list_index_module_update = injectStylesIntoStyleTag_default()(c
407361
407586
 
407362
407587
 
407363
407588
 
407364
- const ConversationList = /*#__PURE__*/ (0,react.forwardRef)((param, ref)=>{
407365
- let { onRename, onDelete, loading, groupedConversations, conversations, hasMore, loadMore } = param;
407589
+
407590
+ const ConversationList = /*#__PURE__*/ (0,react.forwardRef)(// eslint-disable-next-line @coze-arch/max-line-per-function
407591
+ (param, ref)=>{
407592
+ let { onRename, onDelete, loading, groupedConversations, conversations, hasMore, loadMore, removeConversation } = param;
407366
407593
  const { currentConversationInfo, updateCurrentConversationInfo, cozeApi, updateConversations } = useChatAppStore(shallow_useShallow((state)=>({
407367
407594
  currentConversationInfo: state.currentConversationInfo,
407368
407595
  updateCurrentConversationInfo: state.updateCurrentConversationInfo,
@@ -407488,7 +407715,11 @@ const ConversationList = /*#__PURE__*/ (0,react.forwardRef)((param, ref)=>{
407488
407715
  if (res.code !== 0) {
407489
407716
  return false;
407490
407717
  }
407491
- await updateConversations([
407718
+ // 删除成功后,同时更新store和本地数据源
407719
+ // 先更新本地数据源,确保UI立即更新
407720
+ removeConversation(conversation.id);
407721
+ // 然后更新store,确保数据一致性
407722
+ updateConversations([
407492
407723
  conversation
407493
407724
  ], 'remove');
407494
407725
  return true;
@@ -407595,13 +407826,29 @@ const ConversationList = /*#__PURE__*/ (0,react.forwardRef)((param, ref)=>{
407595
407826
  className: conversation_list_sider_conversation_list_index_module["conversations-list"],
407596
407827
  children: [
407597
407828
  Array.from(groupedConversations.entries()).map((param)=>{
407598
- let [sort, conversationList] = param;
407829
+ let [sortKey, conversationList] = param;
407830
+ // 获取分组标题
407831
+ const sort = Number(sortKey);
407832
+ let groupTitle;
407833
+ if (!isNaN(sort)) {
407834
+ // 是 ConversationSort 枚举值
407835
+ groupTitle = conversationSortMap.get(sort) || '';
407836
+ } else {
407837
+ // 是月份字符串 (YYYY-MM)
407838
+ const [year, month] = sortKey.split('-');
407839
+ const monthDate = new Date(Number(year), Number(month) - 1);
407840
+ groupTitle = monthDate.toLocaleDateString('zh-CN', {
407841
+ year: 'numeric',
407842
+ month: 'long'
407843
+ });
407844
+ }
407599
407845
  return /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
407600
407846
  className: conversation_list_sider_conversation_list_index_module["conversations-list-group"],
407601
407847
  children: conversationList.map((conversation, index)=>isMobile ? /*#__PURE__*/ (0,jsx_runtime.jsx)(MobileConversationItem, {
407602
407848
  isActive: conversation.id === (currentConversationInfo === null || currentConversationInfo === void 0 ? void 0 : currentConversationInfo.id),
407603
407849
  item: conversation,
407604
407850
  shouldDisplayTime: index === 0,
407851
+ groupTitle: groupTitle,
407605
407852
  onConversationChange: handleConversationChange,
407606
407853
  onRename: onRename,
407607
407854
  onDelete: onDelete
@@ -407609,11 +407856,12 @@ const ConversationList = /*#__PURE__*/ (0,react.forwardRef)((param, ref)=>{
407609
407856
  isActive: conversation.id === (currentConversationInfo === null || currentConversationInfo === void 0 ? void 0 : currentConversationInfo.id),
407610
407857
  item: conversation,
407611
407858
  shouldDisplayTime: index === 0,
407859
+ groupTitle: groupTitle,
407612
407860
  onConversationChange: handleConversationChange,
407613
407861
  onRename: onRename,
407614
407862
  onDelete: onDelete
407615
407863
  }, conversation.id))
407616
- }, sort);
407864
+ }, sortKey);
407617
407865
  }),
407618
407866
  /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
407619
407867
  ref: loadMoreRef,
@@ -407701,7 +407949,7 @@ var conversation_list_sider_index_module_update = injectStylesIntoStyleTag_defau
407701
407949
  cozeApi: state.cozeApi
407702
407950
  })));
407703
407951
  const { chatConfig: { type: chatType } } = useChatAppProps();
407704
- const { loading, conversations, hasMore, loadMore } = useConversationList();
407952
+ const { loading, conversations, hasMore, loadMore, removeConversation } = useConversationList();
407705
407953
  const groupedConversations = useGroupedConversations(conversations);
407706
407954
  const [isModalLoading, setIsModalLoading] = (0,react.useState)(false);
407707
407955
  const [modalInfo, setModalInfo] = (0,react.useState)(null);
@@ -407840,7 +408088,8 @@ var conversation_list_sider_index_module_update = injectStylesIntoStyleTag_defau
407840
408088
  groupedConversations: groupedConversations,
407841
408089
  conversations: conversations,
407842
408090
  hasMore: hasMore,
407843
- loadMore: loadMore
408091
+ loadMore: loadMore,
408092
+ removeConversation: removeConversation
407844
408093
  }) : null,
407845
408094
  /*#__PURE__*/ (0,jsx_runtime.jsx)(react.Fragment, {
407846
408095
  children: children
@@ -407870,7 +408119,8 @@ var conversation_list_sider_index_module_update = injectStylesIntoStyleTag_defau
407870
408119
  groupedConversations: groupedConversations,
407871
408120
  conversations: conversations,
407872
408121
  hasMore: hasMore,
407873
- loadMore: loadMore
408122
+ loadMore: loadMore,
408123
+ removeConversation: removeConversation
407874
408124
  })
407875
408125
  }),
407876
408126
  /*#__PURE__*/ (0,jsx_runtime.jsx)(esm_webpack_exports_Modal, {
@@ -415903,9 +416153,14 @@ class MessageConverseToCoze {
415903
416153
  case 'object_string':
415904
416154
  {
415905
416155
  console.log('convertContent object_string');
416156
+ const mixContent = this.convertMixContent(content);
416157
+ // 如果 convertMixContent 返回 undefined(JSON 不完整),也返回 undefined
416158
+ if (mixContent === undefined) {
416159
+ return undefined;
416160
+ }
415906
416161
  return {
415907
416162
  content_type: types_ContentType.Mix,
415908
- content: this.convertMixContent(content)
416163
+ content: mixContent
415909
416164
  };
415910
416165
  }
415911
416166
  case 'card':
@@ -418387,7 +418642,7 @@ class MessageParser {
418387
418642
  }
418388
418643
  case "conversation.message.delta":
418389
418644
  {
418390
- const message = this.createMessage(data);
418645
+ const message = this.createMessage(data, false);
418391
418646
  if (!message) {
418392
418647
  return;
418393
418648
  }
@@ -418395,7 +418650,21 @@ class MessageParser {
418395
418650
  }
418396
418651
  case "conversation.message.completed":
418397
418652
  {
418398
- return this.createMessage(data, true);
418653
+ const messageResult = this.createMessage(data, true);
418654
+ // 清理流式 JSON 累积内容
418655
+ if (messageResult && typeof messageResult === 'object' && 'data' in messageResult) {
418656
+ const messageData = messageResult.data;
418657
+ // 检查是否是 ChunkRaw 类型(包含 message 字段)
418658
+ if (messageData && typeof messageData === 'object' && 'message' in messageData && messageData.message && typeof messageData.message === 'object') {
418659
+ const msg = messageData.message;
418660
+ const contentKey = msg.message_id || msg.reply_id || '';
418661
+ if (contentKey) {
418662
+ this.streamingJsonContent.delete(contentKey);
418663
+ this.lastValidJsonContent.delete(contentKey);
418664
+ }
418665
+ }
418666
+ }
418667
+ return messageResult;
418399
418668
  }
418400
418669
  case "conversation.chat.completed":
418401
418670
  case "done":
@@ -418446,10 +418715,53 @@ class MessageParser {
418446
418715
  const messageType = (dataValue === null || dataValue === void 0 ? void 0 : dataValue.type) || '';
418447
418716
  dataValue.chat_id = !dataValue.chat_id || dataValue.chat_id === '0' ? '' : dataValue.chat_id;
418448
418717
  dataValue.id = !dataValue.id || dataValue.id === '0' ? '' : dataValue.id;
418718
+ // 处理流式 JSON:当 content_type 是 object_string 且 type 是 answer 时
418719
+ const isStreamingJson = dataValue.content_type === 'object_string' && dataValue.type === 'answer';
418720
+ if (isStreamingJson && dataValue.content) {
418721
+ // 使用 messageId 或 chatId 作为 key 来累积内容
418722
+ const contentKey = dataValue.id || dataValue.chat_id || '';
418723
+ if (contentKey) {
418724
+ // 累积流式 JSON 内容
418725
+ const accumulatedContent = this.streamingJsonContent.get(contentKey) || '';
418726
+ const newContent = accumulatedContent + dataValue.content;
418727
+ this.streamingJsonContent.set(contentKey, newContent);
418728
+ // 尝试解析累积的内容
418729
+ const parsedContent = this.tryParseStreamingJson(newContent);
418730
+ if (parsedContent !== null) {
418731
+ // 如果解析成功,使用解析后的内容,并保存为最后一次有效内容
418732
+ dataValue.content = parsedContent;
418733
+ this.lastValidJsonContent.set(contentKey, parsedContent);
418734
+ } else {
418735
+ // 如果解析失败(JSON 不完整),使用上一次成功解析的内容(如果有)
418736
+ // 这样可以避免每次 delta 都创建新消息,导致重复渲染
418737
+ const lastValidContent = this.lastValidJsonContent.get(contentKey);
418738
+ if (lastValidContent) {
418739
+ // 使用上一次成功解析的内容,避免重复渲染
418740
+ dataValue.content = lastValidContent;
418741
+ } else {
418742
+ // 如果完全没有成功解析的内容,使用累积的原始内容
418743
+ // 但这样可能会导致 convertMixContent 失败,返回 undefined
418744
+ dataValue.content = newContent;
418745
+ }
418746
+ }
418747
+ }
418748
+ }
418449
418749
  const message = messageConverterToCoze.convertMessage(dataValue, this.botId);
418450
418750
  if (!message) {
418451
418751
  return;
418452
418752
  }
418753
+ // 对于流式 JSON,如果 convertMixContent 返回 undefined(JSON 不完整),
418754
+ // 且没有上一次成功解析的内容,不返回消息,避免重复渲染
418755
+ if (isStreamingJson && !isComplete && message.content_type === types_ContentType.Mix && (!message.content || message.content === 'undefined')) {
418756
+ const contentKey = dataValue.id || dataValue.chat_id || '';
418757
+ const lastValidContent = contentKey ? this.lastValidJsonContent.get(contentKey) : undefined;
418758
+ // 如果没有上一次成功解析的内容,不返回消息
418759
+ if (!lastValidContent) {
418760
+ return;
418761
+ }
418762
+ // 如果有上一次成功解析的内容,使用它
418763
+ message.content = lastValidContent;
418764
+ }
418453
418765
  if (isComplete && message.content_type === types_ContentType.Text && message.type === 'answer') {
418454
418766
  message.content = '';
418455
418767
  } else if (isComplete && message.content_type === types_ContentType.Mix && message.type === 'answer') {
@@ -418473,6 +418785,123 @@ class MessageParser {
418473
418785
  }
418474
418786
  };
418475
418787
  }
418788
+ /**
418789
+ * 尝试解析流式 JSON 内容
418790
+ * 如果 JSON 不完整,返回 null;如果解析成功,返回完整的 JSON 字符串
418791
+ */ tryParseStreamingJson(content) {
418792
+ if (!content || content.trim() === '') {
418793
+ return null;
418794
+ }
418795
+ const trimmed = content.trim();
418796
+ try {
418797
+ // 尝试解析为完整的 JSON
418798
+ const parsed = JSON.parse(trimmed);
418799
+ // 如果解析成功,返回格式化的 JSON 字符串
418800
+ return JSON.stringify(parsed);
418801
+ } catch (e) {
418802
+ // 如果解析失败,可能是 JSON 不完整
418803
+ // 检查是否以 [ 开头,可能是数组
418804
+ if (trimmed.startsWith('[')) {
418805
+ // 尝试找到最后一个完整的 JSON 对象或数组
418806
+ let bracketCount = 0;
418807
+ let braceCount = 0;
418808
+ let inString = false;
418809
+ let escapeNext = false;
418810
+ let lastValidIndex = -1;
418811
+ for(let i = 0; i < trimmed.length; i++){
418812
+ const char = trimmed[i];
418813
+ if (escapeNext) {
418814
+ escapeNext = false;
418815
+ continue;
418816
+ }
418817
+ if (char === '\\') {
418818
+ escapeNext = true;
418819
+ continue;
418820
+ }
418821
+ if (char === '"') {
418822
+ inString = !inString;
418823
+ continue;
418824
+ }
418825
+ if (inString) {
418826
+ continue;
418827
+ }
418828
+ if (char === '[') {
418829
+ bracketCount++;
418830
+ }
418831
+ if (char === ']') {
418832
+ bracketCount--;
418833
+ }
418834
+ if (char === '{') {
418835
+ braceCount++;
418836
+ }
418837
+ if (char === '}') {
418838
+ braceCount--;
418839
+ }
418840
+ // 如果所有括号都匹配了,说明找到了一个完整的 JSON
418841
+ if (bracketCount === 0 && braceCount === 0 && i > 0) {
418842
+ lastValidIndex = i;
418843
+ break;
418844
+ }
418845
+ }
418846
+ if (lastValidIndex > 0) {
418847
+ try {
418848
+ const partialContent = trimmed.substring(0, lastValidIndex + 1);
418849
+ JSON.parse(partialContent);
418850
+ return partialContent;
418851
+ } catch (parseError) {
418852
+ // JSON 解析失败,继续返回 null,表示 JSON 不完整
418853
+ void parseError;
418854
+ }
418855
+ }
418856
+ } else if (trimmed.startsWith('{')) {
418857
+ // 如果是对象,尝试找到最后一个完整的对象
418858
+ let braceCount = 0;
418859
+ let inString = false;
418860
+ let escapeNext = false;
418861
+ let lastValidIndex = -1;
418862
+ for(let i = 0; i < trimmed.length; i++){
418863
+ const char = trimmed[i];
418864
+ if (escapeNext) {
418865
+ escapeNext = false;
418866
+ continue;
418867
+ }
418868
+ if (char === '\\') {
418869
+ escapeNext = true;
418870
+ continue;
418871
+ }
418872
+ if (char === '"') {
418873
+ inString = !inString;
418874
+ continue;
418875
+ }
418876
+ if (inString) {
418877
+ continue;
418878
+ }
418879
+ if (char === '{') {
418880
+ braceCount++;
418881
+ }
418882
+ if (char === '}') {
418883
+ braceCount--;
418884
+ }
418885
+ if (braceCount === 0 && i > 0) {
418886
+ lastValidIndex = i;
418887
+ break;
418888
+ }
418889
+ }
418890
+ if (lastValidIndex > 0) {
418891
+ try {
418892
+ const partialContent = trimmed.substring(0, lastValidIndex + 1);
418893
+ JSON.parse(partialContent);
418894
+ return partialContent;
418895
+ } catch (parseError) {
418896
+ // JSON 解析失败,继续返回 null,表示 JSON 不完整
418897
+ void parseError;
418898
+ }
418899
+ }
418900
+ }
418901
+ // 如果无法解析,返回 null,表示 JSON 不完整,需要继续累积
418902
+ return null;
418903
+ }
418904
+ }
418476
418905
  createAckMessage(data) {
418477
418906
  var _dataValue_inserted_additional_messages_lastItem, _dataValue_inserted_additional_messages, _this_userInfo;
418478
418907
  const messageType = 'ack';
@@ -418566,6 +418995,10 @@ class MessageParser {
418566
418995
  message_parser_define_property(this, "botVersion", '');
418567
418996
  message_parser_define_property(this, "userInfo", void 0);
418568
418997
  message_parser_define_property(this, "onConversationUpdate", void 0);
418998
+ // 用于累积流式 JSON 内容,key 为 messageId 或 replyId
418999
+ message_parser_define_property(this, "streamingJsonContent", new Map());
419000
+ // 用于存储上一次成功解析的完整 JSON 内容,避免重复渲染
419001
+ message_parser_define_property(this, "lastValidJsonContent", new Map());
418569
419002
  this.conversationId = requestMessageRawBody.conversation_id;
418570
419003
  this.localMessageId = requestMessageRawBody.local_message_id;
418571
419004
  this.sendMessageContent = requestMessageRawBody.query;
@@ -418747,6 +419180,30 @@ class MessageParser {
418747
419180
  sectionId: conversationResult.sectionId || '',
418748
419181
  conversationName: conversationResult.conversationName
418749
419182
  };
419183
+ // 立即添加会话到列表,使用创建时返回的名称
419184
+ const existingConversation = refConversations.current.find((c)=>c.id === conversationResult.conversationId);
419185
+ if (!existingConversation && refUpdateConversations.current) {
419186
+ // 重用外部作用域已声明的 chatType 和 isAppType
419187
+ const newConversation = {
419188
+ id: conversationResult.conversationId,
419189
+ last_section_id: conversationResult.sectionId || '',
419190
+ name: conversationResult.conversationName || '',
419191
+ created_at: Math.floor(Date.now() / 1000),
419192
+ updated_at: Math.floor(Date.now() / 1000),
419193
+ meta_data: {},
419194
+ // App 模式需要 title 字段,但从空会话创建的新会话 title 应该为空
419195
+ ...isAppType && {
419196
+ title: ''
419197
+ }
419198
+ };
419199
+ refUpdateConversations.current([
419200
+ newConversation
419201
+ ], 'add');
419202
+ console.log('onBeforeSendMessage: Conversation added to list immediately', {
419203
+ conversationId: conversationResult.conversationId,
419204
+ conversationName: conversationResult.conversationName
419205
+ });
419206
+ }
418750
419207
  // 只更新 messageBody 中的 conversation_id
418751
419208
  // 不在这里更新 currentConversationInfo 或调用 setConversationId
418752
419209
  // 这些更新会在消息发送成功后通过消息解析器进行
@@ -418854,15 +419311,22 @@ class MessageParser {
418854
419311
  // 检查会话是否已经存在于列表中,避免重复添加
418855
419312
  const existingConversation = refConversations.current.find((c)=>c.id === pendingInfo.conversationId);
418856
419313
  // 如果会话不存在,才更新会话列表
419314
+ // 注意:会话已经在创建时添加到列表了,这里主要是为了兼容性检查
418857
419315
  if (!existingConversation) {
419316
+ const chatType = refChatConfig.current.type;
419317
+ const isAppType = chatType === client_ChatType.APP;
418858
419318
  const newConversation = {
418859
419319
  id: pendingInfo.conversationId,
418860
419320
  last_section_id: pendingInfo.sectionId,
418861
- // 不设置 name,让 useUpdateConversationNameByMessage hook 自动更新
418862
- name: '',
419321
+ // 使用创建时返回的名称
419322
+ name: pendingInfo.conversationName || '',
418863
419323
  created_at: Math.floor(Date.now() / 1000),
418864
419324
  updated_at: Math.floor(Date.now() / 1000),
418865
- meta_data: {}
419325
+ meta_data: {},
419326
+ // App 模式需要 title 字段
419327
+ ...isAppType && pendingInfo.conversationName && {
419328
+ title: pendingInfo.conversationName
419329
+ }
418866
419330
  };
418867
419331
  if (refUpdateConversations.current) {
418868
419332
  refUpdateConversations.current([