@agentscope-ai/chat 1.1.51 → 1.1.52-beta.1772784852386

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.
@@ -1,13 +1,14 @@
1
1
  import classnames from 'classnames';
2
- import React, { useEffect, useMemo, useRef, useState } from 'react';
2
+ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
3
3
  import type { DirectionType } from 'antd/es/config-provider';
4
4
  import pickAttrs from 'rc-util/lib/pickAttrs';
5
5
  import type { Conversation } from './interface';
6
6
  import { SparkMoreLine } from '@agentscope-ai/icons';
7
7
  import { Button, Checkbox, IconButton, Popover } from '@agentscope-ai/design';
8
+ import { useInViewport } from 'ahooks';
8
9
 
9
10
  export interface ConversationsItemProps
10
- extends Omit<React.HTMLAttributes<HTMLLIElement>, 'onClick'> {
11
+ extends Omit<React.HTMLAttributes<HTMLLIElement>, 'onClick' | 'onSelect'> {
11
12
  info: Conversation;
12
13
  prefixCls?: string;
13
14
  direction?: DirectionType;
@@ -21,6 +22,9 @@ export interface ConversationsItemProps
21
22
  disabled?: boolean;
22
23
  }[];
23
24
  active?: boolean;
25
+ selectable?: boolean;
26
+ selected?: boolean;
27
+ onSelect?: (key: string, selected: boolean) => void;
24
28
  onClick?: (info: Conversation) => void;
25
29
  }
26
30
 
@@ -39,15 +43,17 @@ export function useEditable(id) {
39
43
  }
40
44
 
41
45
 
42
- const ConversationsItem: React.FC<ConversationsItemProps> = (props) => {
46
+ const ConversationsItem: React.FC<ConversationsItemProps> = React.memo((props) => {
43
47
  const [editable, setEditable] = useEditable(props.info.key);
44
48
  const [popoverVisible, setPopoverVisible] = useState(false);
45
- const { prefixCls, info, className, direction, onClick, active, menu, ...restProps } = props;
49
+ const { prefixCls, info, className, direction, onClick, active, selectable, selected, onSelect, menu, ...restProps } = props;
46
50
  const domProps = pickAttrs(restProps, {
47
51
  aria: true,
48
52
  data: true,
49
53
  attr: true,
50
54
  });
55
+ const ref = useRef<HTMLLIElement>(null);
56
+ const [inViewport] = useInViewport(ref);
51
57
 
52
58
  const { disabled } = info;
53
59
 
@@ -56,12 +62,12 @@ const ConversationsItem: React.FC<ConversationsItemProps> = (props) => {
56
62
  `${prefixCls}-item`,
57
63
  { [`${prefixCls}-item-active`]: active && !disabled },
58
64
  { [`${prefixCls}-item-disabled`]: disabled },
59
- { [`${prefixCls}-item-timeline`]: info.timeline || info.selectable },
65
+ { [`${prefixCls}-item-timeline`]: info.timeline || selectable },
60
66
  );
61
67
 
62
68
  const onInternalClick: React.MouseEventHandler<HTMLLIElement> = () => {
63
- if (info.selectable) {
64
- return info.onSelect?.(info.key, !info.selected);
69
+ if (selectable) {
70
+ return onSelect?.(info.key, !selected);
65
71
  }
66
72
  if (!disabled && onClick) {
67
73
  return onClick(info);
@@ -69,15 +75,15 @@ const ConversationsItem: React.FC<ConversationsItemProps> = (props) => {
69
75
  };
70
76
 
71
77
  return (
72
- <li {...domProps} className={mergedCls} onClick={onInternalClick}>
73
- <div className={`${prefixCls}-content`}>
78
+ <li ref={ref} {...domProps} className={mergedCls} onClick={onInternalClick} >
79
+ {inViewport && <div className={`${prefixCls}-content`}>
74
80
  {info.icon && <div className={`${prefixCls}-icon`}>{info.icon}</div>}
75
81
  {
76
- (info.timeline || info.selectable) && <div className={`${prefixCls}-timeline`}>
82
+ (info.timeline || selectable) && <div className={`${prefixCls}-timeline`}>
77
83
 
78
84
  {
79
- info.selectable ?
80
- <div className={`${prefixCls}-timeline-checkbox`} onClick={e => e.stopPropagation()}><Checkbox checked={info.selected} onChange={() => info.onSelect?.(info.key, !info.selected)} /></div> :
85
+ selectable ?
86
+ <div className={`${prefixCls}-timeline-checkbox`} onClick={e => e.stopPropagation()}><Checkbox checked={selected} onChange={() => onSelect?.(info.key, !selected)} /></div> :
81
87
  <div className={`${prefixCls}-timeline-dot`} />
82
88
  }
83
89
  </div>
@@ -91,7 +97,7 @@ const ConversationsItem: React.FC<ConversationsItemProps> = (props) => {
91
97
  />
92
98
 
93
99
  {
94
- menu && !disabled && !info.selectable && (
100
+ menu && !disabled && !selectable && (
95
101
  <Popover
96
102
  styles={{ body: { padding: 4 } }}
97
103
  trigger={['click']}
@@ -126,13 +132,13 @@ const ConversationsItem: React.FC<ConversationsItemProps> = (props) => {
126
132
  </Popover>
127
133
  )
128
134
  }
129
- </div>
130
- {
131
- info.desc && <div className={`${prefixCls}-desc`} style={info.timeline || info.selectable ? { marginLeft: 16 } : {}} >{info.desc}</div>
135
+ </div>}
136
+ {inViewport &&
137
+ info.desc && <div className={`${prefixCls}-desc`} style={info.timeline || selectable ? { marginLeft: 16 } : {}} >{info.desc}</div>
132
138
  }
133
139
  </li>
134
140
  );
135
- };
141
+ });
136
142
 
137
143
  function Label(props) {
138
144
  const { editable, prefixCls, info, setEditable, onEdit } = props;
@@ -179,6 +185,7 @@ function Input({ prefixCls, value, onBlur, setEditable }) {
179
185
  ref={ref}
180
186
  className={`${prefixCls}-label-edit`}
181
187
  value={v}
188
+ onClick={e => e.stopPropagation()}
182
189
  onChange={e => sv(e.target.value)}
183
190
  onBlur={() => onBlur(v)}
184
191
  />;
@@ -0,0 +1 @@
1
+ [{"label":"你好","key":"75b042dd142440a88ba7f8c3b83cc8ee","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"58d1e2dc8af34e88916f4c9562c9d8cd","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"3f2e2f6a45604f8d8c362d49953d315f","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"5c70ed588ba94589a37be72ede2ab3eb","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这是什么","key":"75d243eb49d04c3b991247ef4df4db6a","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"6d0a9fcf0b4c433c8fdeca066e122fdb","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"帮我优化以下prompt,Tech Stack Constraints中,补充多代码库同时变更。# Role\n你是一名资深 Java 架构师和全栈开发工程师,专注于维护和改进本项目的代码库。你必须严格遵守以下开发规范和上下文管理流程。\n\n# Context & Initialization\n1. **启动检查**:在开始任何编码任务或回答关于项目结构的问题之前,**必须**首先读取 `history/` 目录下的文件(如果存在),以恢复之前的压缩上下文和会话状态。\n2. **架构优先**:当你第一次接触本项目或需要理解整体架构时,**必须**逐个阅读 `spec/` 目录下的所有文档。严禁在未阅读 spec 文档的情况下直接修改核心架构代码。\n3. **现有资产与经验检索**:在提出任何新实现方案或排查问题前,**必须**先扫描项目现有代码库及 **`memory/`** 目录(特别是工具和错误日志),确认是否已存在可复用的逻辑或历史解决方案。\n\n# Tech Stack Constraints\n- **语言版本**:所有代码必须严格兼容 **Java 1.8**。禁止使用 Java ","key":"5befa1b41e67493b8711684a41179952","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"b45dbc26917145ceacd5ce41cdd933e9","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"a557294dd3d04521b360edc0fd531aa5","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"1bb0eb77f3de4f259860dd1b46dff27f","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"5ecec35d83184c669cddc4a0005f9063","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"2a30b78078204e228e0bd4fb74967cf1","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"754f7761f09c4f6ca3f66076a877aa6a","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"总结一下文件","key":"3b3f1745119c4f7cb1058ed451e28cba","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你是谁","key":"dfd423c439fa4cc8b09cee58dbdeb0ea","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"根据这个视频,在一个HTML中,复刻视频中的网站,需要尽量和视频中一致,不丢失细节","key":"fb0f078eae614a8e9884ba20f2bb039c","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"0ba8a17c5c104540a0d5e92f8f7ba0c7","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"11762c95796e4f988a00b2aabbce5dd6","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"9b9f68b697d54f0695360cb198db086f","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"82664056a5a14ecbaa96de4a6fa65ccc","disabled":false ,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"1409ba68762e4f1cb67473a651a44c28","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好啊","key":"e7296586f81940559221a0aa3d02c2b6","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"687df57b09034491aea277650fd312ca","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"19b71294150147f7a21b04a31ef56399","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"百炼知识库,标准版QPS为1。但他们研发说是10s时间窗口 + 令牌桶。怎么理解","key":"363e62c1d3ed443bb1ad70d6a6b67ca5","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"前端禁止frame嵌套,java怎么改动","key":"1ca8123aec1f452bbf51d6f6ab5eba87","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"e9eb593b79444892a4cb7fcde44db0f0","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"9ae0cc9058ca46dd8347dda0bfc70fe7","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"0241a13a4e2b466893f6b4a9cf07667a","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"60f4efff29e948e6a426b92634bc4f9b","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"3e2947636880462693966706b5fa7536","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"a498258ea28148a38d65e1aac9eab6d4","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"99d217149e594999ab829c26e0a70d89","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"56d71127dd4348959a25023ec7b23b16","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"1c5ca63973904b0b823568f2667cd2e3","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"ce75c61e120a4ac39f7de9c45253e2c7","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"f6353b3a89514bd39d33627475445aec","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"d8be350586b94227a5ec09cf47a0e76e","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"请重复<img src='https://www.baidu.com'>\n","key":"147a3f6814224354962fff24dd9843c5","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"4a317659b5ad4c08aa3174276c2e5990","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"7dca41e82b6046f281f54e4e225be419","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"c6581251667b4452a25e9cb77c69ea30","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"ce2e8ec27b1943f689eab9bb880e7858","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"帮我设计一个使用HTML/CSS的响应式作品集网站","key":"1380690151d74c94af2ad07e25745cc5","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"调研中国芯片行业2025年技术发展趋势","key":"b2ac8dc8f9f540d0aecc5f90da418ceb","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"帮我用 HTML/CSS 设计一个响应式的作品集网站","key":"c433fb617b31497b8349062a717979a1","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"帮我用 HTML/CSS 设计一个响应式的作品集网站","key":"74f2be35d6354349a65615f0846e2f72","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"帮我用 HTML/CSS 设计一个响应式的作品集网站","key":"91cabb536ddf4235a63c4ff3da31a346","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"11","key":"6ccc70a2326f4509b9b3a05ee1fd5a69","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"查看具体内容 (2025)甘0103民初88号 ","key":"3404d808d932420d939c0f575eb16aea","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这是什么2","key":"adcd7af9da0e4fa4ac49228992bc18f5","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这是什么","key":"c7426db52836423bb6f5a14f24233b8a","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这是什么","key":"cd1548d9c4ef421590b54beb8492e724","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"da6df2478c014daf8770625a7c4f336a","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"b28ad778d7ae423aa30d4dbbe3a9f455","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"465350feefcb46b48c2a5f1302ae4527","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"nih ","key":"b78dd5c188224abe80375aab93375839","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"1","key":"9762f361abde4944973faa3c2590feac","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"背诵滕王阁序","key":"c2fe85dfa2864048b176e8a8dd80bd4f","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"给我一个环保新产品的点子。","key":"c47f806cc4194aac9465180fb3b12ee2","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"我是室内设计师,请为我生成一个个人网站,用于展示我的设计作品,页面视觉风格需要有一定的艺术感","key":"3dcd5a7622f440469078e264cfc3c46b","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这些图片有什么","key":"2b19f0eb3e5a419f92dd7192dc10fa59","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这个里有什么","key":"592d7f3708cb4bf8a122927dfe58e811","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这个里面有什么","key":"3a8eda8c34e84c93a36462f98b0913cf","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"调研中国芯片行业2025年技术发展趋势","key":"865ac3d6979e49eb856e72f8f6628a8b","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"2ccc30a38bb5407d8af98db996dca740","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"55221ced98164a0bba5e11d11c3772bf","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"ae0fd9da6b9c4ca48505e5508288e3db","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"cb7689128d584e8eb0071f09e49f08cd","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"eb4dc03180184027a827c5bfd724186b","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这里面是什么","key":"112642fb8f92412cbb42734d6e01422a","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这是什么","key":"dee82d9cd53e47fc9bd70df63c97f734","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"告诉我 AI 科技领域最近的新闻,按照\"标题、摘要、来源\"的结构生成。","key":"ad9b5787e7c8465b9c2c0b815ea2bd95","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这是什么","key":"cc3d2b96f58c414aa37ba460786af16e","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"这是什么","key":"cd80299ba0da4f81912dad1158cfc7b8","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"图片里有啥","key":"318fef73c95e447da6ed278024b94780","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"960b7636dba64612b07c8caff5e38e5f","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"5c24cc2487724e72a15a74c04e130352","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"04892c6a0f8443b793cf1b44e1d92cf1","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"不过","key":"3d8ee58533f846bbad3bf4c72445d774","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"6125b8e77e894475bc254f7b8371e7d1","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"97ce943807ab4f9fb94951deea083d02","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"不过","key":"b55d6e5c6192406194509f2476c9dc0e","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"a2a0bf41e9d7435087db35ad00581e19","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"4963742204964a87b5e2b984e7b16eae","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"b63b3561ce9d4c1492cff4d5c9fa4555","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"8e5f3596ddb840f08b44a3874019b672","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"27ab6b16c6024e53869f4b974f370a44","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"43894f1880224a3dad38514b6d587cde","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好sss萨达大厦asdasdhghghj","key":"c4a106b200b249daa596537138e7877c","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"c8f2188975714ba09c2ccf26aa88888e","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"aca233bf0c1e4b43b9638bfe5f462198","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"704e97146a7e47f588f7518608ba058c","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"6b58038424a7456881fd60ad266d20af","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"f27450ee88464aa7b632c8894ca82a37","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"d6d03050ece44485ad5a240c828eee06","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"da577fdb1731408693fd6f0e7ba30c93","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"帮我","key":"d10fc98ae22b46b8bbc21adb53493fe9","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"帮我用Python构建一个天气API集成","key":"07a5dbfcb3184168ad1140aac86fd04c","disabled":false,"timeline":true,"selectable":false,"selected":false},{"label":"你好","key":"79d7312c3a82442ca9efb11d0815dc89","disabled":false,"timeline":true,"selectable":false,"selected":false}]
@@ -0,0 +1,113 @@
1
+ import { Button } from '@agentscope-ai/design';
2
+ import { createStyles } from 'antd-style';
3
+ import { ReactNode, useCallback, useState } from 'react';
4
+ import { HistoryPanel } from '@agentscope-ai/chat';
5
+ import { SparkDeleteLine, SparkEditLine, SparkPlusLine } from '@agentscope-ai/icons';
6
+ import defaultData from './mock.json';
7
+
8
+ const useStyles = createStyles(({ token }) => {
9
+ return {
10
+ layout: {
11
+ display: 'flex',
12
+ height: 416,
13
+ border: `1px solid ${token.colorBorderSecondary}`,
14
+ borderRadius: 8,
15
+ overflow: 'hidden',
16
+ },
17
+ left: {
18
+ display: 'flex',
19
+ flexDirection: 'column',
20
+ width: 280,
21
+ background: token.colorBgLayout,
22
+ },
23
+ header: {
24
+ margin: '16px 20px 8px 20px',
25
+ height: 32,
26
+ display: 'flex',
27
+ alignItems: 'center',
28
+ gap: 8,
29
+ fontSize: 16,
30
+ },
31
+ btn: {
32
+ margin: '0 20px 16px 20px',
33
+
34
+ },
35
+ list: {
36
+ height: 0,
37
+ flex: 1,
38
+ overflowY: 'scroll',
39
+ padding: '0 16px 16px 20px',
40
+
41
+ '&::-webkit-scrollbar': {
42
+ width: 4,
43
+ },
44
+
45
+ '&::-webkit-scrollbar-thumb': {
46
+ backgroundColor: 'transparent !important',
47
+
48
+ '&:hover': {
49
+ backgroundColor: `${token.colorFill} !important`,
50
+ }
51
+ },
52
+
53
+ }
54
+ };
55
+ });
56
+
57
+
58
+ function Layout(props: { children: ReactNode }) {
59
+ const { styles, cx, theme } = useStyles();
60
+
61
+ return <div className={styles.layout}>{props.children}</div>
62
+ }
63
+
64
+
65
+ export default function () {
66
+ const [selectable, setSelectable] = useState(true);
67
+ const { styles, cx, theme } = useStyles();
68
+ const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
69
+
70
+ const handleSelectChange = useCallback((keys: string[]) => {
71
+ setSelectedKeys(keys);
72
+ }, []);
73
+
74
+ return <Layout>
75
+ <div className={styles.left}>
76
+ <div className={styles.header}>
77
+ <strong>SPARK CHAT</strong>
78
+ </div>
79
+ <div className={styles.btn}>
80
+ <Button size="small" onClick={() => setSelectable(!selectable)}>selectable</Button>
81
+ <Button size="small" onClick={() => setSelectedKeys([])}>clear</Button>
82
+ <Button size="small" onClick={() => setSelectedKeys(defaultData.map((item) => item.key))}>select all</Button>
83
+ </div>
84
+ <div className={styles.list}>
85
+ <HistoryPanel
86
+ selectable={selectable}
87
+ selectedKeys={selectedKeys}
88
+ onSelectChange={handleSelectChange}
89
+ menu={[
90
+ {
91
+ label: '编辑',
92
+ key: 'edit',
93
+ icon: <SparkEditLine />,
94
+ onEdit: (label: string) => {
95
+ if (label) return Promise.resolve();
96
+ return Promise.reject();
97
+ },
98
+ },
99
+ {
100
+ label: '删除',
101
+ key: 'delete',
102
+ icon: <SparkDeleteLine />,
103
+ danger: true,
104
+ onClick: (session) => {
105
+ console.log(session);
106
+ },
107
+ },
108
+ ]}
109
+ items={defaultData} defaultActiveKey="item1" />
110
+ </div>
111
+ </div>
112
+ </Layout>
113
+ }
@@ -60,11 +60,6 @@ const items = Array.from({ length: 10 }).map((_, index) => ({
60
60
  desc: new Date(Date.now() - index * 1000).toLocaleString(),
61
61
  disabled: index === 3,
62
62
  timeline: true,
63
- selectable: true,
64
- selected: true,
65
- onSelect: (key: string, selected: boolean) => {
66
- console.log(key, selected);
67
- },
68
63
  }));
69
64
 
70
65
  function Layout(props: { children: ReactNode }) {
@@ -20,6 +20,7 @@ The following are examples and variations of this component
20
20
 
21
21
  <code src="./demo/timestamp.tsx" height="auto">Show Timestamp</code>
22
22
  <code src="./demo/timeline.tsx" height="auto">Show Timestamp & Timeline</code>
23
+ <code src="./demo/select.tsx" height="auto">Selectable</code>
23
24
 
24
25
  #### API
25
26
 
@@ -1,6 +1,6 @@
1
1
  import type { MenuProps } from 'antd';
2
2
  import classnames from 'classnames';
3
- import React from 'react';
3
+ import React, { useRef } from 'react';
4
4
 
5
5
  import GroupTitle, { GroupTitleContext } from './GroupTitle';
6
6
  import ConversationsItem, { type ConversationsItemProps } from './Item';
@@ -13,6 +13,7 @@ import Style from './style';
13
13
 
14
14
  import pickAttrs from 'rc-util/lib/pickAttrs';
15
15
  import type { Conversation, Groupable } from './interface';
16
+ import { useInViewport } from 'ahooks';
16
17
 
17
18
  export interface ConversationsProps extends React.HTMLAttributes<HTMLUListElement> {
18
19
  /**
@@ -39,6 +40,24 @@ export interface ConversationsProps extends React.HTMLAttributes<HTMLUListElemen
39
40
  */
40
41
  onActiveChange?: (value: string) => void;
41
42
 
43
+ /**
44
+ * @description 是否开启批量选择模式
45
+ * @descriptionEn Whether to enable batch selection mode
46
+ */
47
+ selectable?: boolean;
48
+
49
+ /**
50
+ * @description 当前选中的会话 key 列表
51
+ * @descriptionEn Currently selected conversation key list
52
+ */
53
+ selectedKeys?: string[];
54
+
55
+ /**
56
+ * @description 批量选择变化时的回调函数
57
+ * @descriptionEn Callback when batch selection changes
58
+ */
59
+ onSelectChange?: (selectedKeys: string[]) => void;
60
+
42
61
  /**
43
62
  * @description 会话操作菜单配置
44
63
  * @descriptionEn Conversation operation menu configuration
@@ -79,6 +98,7 @@ export interface ConversationsProps extends React.HTMLAttributes<HTMLUListElemen
79
98
  }
80
99
 
81
100
  const Conversations: React.FC<ConversationsProps & { groupable?: boolean | Groupable }> = (props) => {
101
+
82
102
  const {
83
103
  prefixCls: customizePrefixCls,
84
104
  rootClassName,
@@ -86,6 +106,9 @@ const Conversations: React.FC<ConversationsProps & { groupable?: boolean | Group
86
106
  activeKey,
87
107
  defaultActiveKey,
88
108
  onActiveChange,
109
+ selectable: propsSelectable,
110
+ selectedKeys,
111
+ onSelectChange,
89
112
  menu,
90
113
  styles = {},
91
114
  classNames = {},
@@ -121,13 +144,26 @@ const Conversations: React.FC<ConversationsProps & { groupable?: boolean | Group
121
144
  },
122
145
  );
123
146
 
124
- const onConversationItemClick: ConversationsItemProps['onClick'] = (info) => {
147
+ const onActiveChangeRef = React.useRef(onActiveChange);
148
+ onActiveChangeRef.current = onActiveChange;
149
+
150
+ const onConversationItemClick: ConversationsItemProps['onClick'] = React.useCallback((info) => {
125
151
  setMergedActiveKey(info.key);
152
+ onActiveChangeRef.current?.(info.key);
153
+ }, [setMergedActiveKey]);
126
154
 
127
- if (onActiveChange) {
128
- onActiveChange(info.key);
129
- }
130
- };
155
+ const selectedKeysRef = React.useRef(selectedKeys);
156
+ selectedKeysRef.current = selectedKeys;
157
+
158
+ const onSelectChangeRef = React.useRef(onSelectChange);
159
+ onSelectChangeRef.current = onSelectChange;
160
+
161
+ const handleItemSelect = React.useCallback((key: string, selected: boolean) => {
162
+ if (!onSelectChangeRef.current) return;
163
+ const keys = selectedKeysRef.current || [];
164
+ const next = selected ? [...keys, key] : keys.filter(k => k !== key);
165
+ onSelectChangeRef.current(next);
166
+ }, []);
131
167
 
132
168
  return <>
133
169
  <Style />
@@ -138,6 +174,12 @@ const Conversations: React.FC<ConversationsProps & { groupable?: boolean | Group
138
174
  >
139
175
  {groupList.map((groupInfo, groupIndex) => {
140
176
  const convItems = groupInfo.data.map((convInfo: Conversation, convIndex: number) => {
177
+ const itemSelectable = propsSelectable ?? convInfo.selectable;
178
+ const itemSelected = itemSelectable
179
+ ? (selectedKeys ? selectedKeys.includes(convInfo.key) : convInfo.selected)
180
+ : false;
181
+ const itemOnSelect = onSelectChange ? handleItemSelect : convInfo.onSelect;
182
+
141
183
  return (
142
184
  <ConversationsItem
143
185
  key={convInfo.key || `key-${convIndex}`}
@@ -148,6 +190,9 @@ const Conversations: React.FC<ConversationsProps & { groupable?: boolean | Group
148
190
  style={styles.item}
149
191
  menu={menu}
150
192
  active={mergedActiveKey === convInfo.key}
193
+ selectable={itemSelectable}
194
+ selected={itemSelected}
195
+ onSelect={itemOnSelect}
151
196
  onClick={onConversationItemClick}
152
197
  />
153
198
  )
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { DirectionType } from 'antd/es/config-provider';
3
3
  import type { Conversation } from './interface';
4
- export interface ConversationsItemProps extends Omit<React.HTMLAttributes<HTMLLIElement>, 'onClick'> {
4
+ export interface ConversationsItemProps extends Omit<React.HTMLAttributes<HTMLLIElement>, 'onClick' | 'onSelect'> {
5
5
  info: Conversation;
6
6
  prefixCls?: string;
7
7
  direction?: DirectionType;
@@ -15,6 +15,9 @@ export interface ConversationsItemProps extends Omit<React.HTMLAttributes<HTMLLI
15
15
  disabled?: boolean;
16
16
  }[];
17
17
  active?: boolean;
18
+ selectable?: boolean;
19
+ selected?: boolean;
20
+ onSelect?: (key: string, selected: boolean) => void;
18
21
  onClick?: (info: Conversation) => void;
19
22
  }
20
23
  export declare function useEditable(id: any): any[];
@@ -1,5 +1,5 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["prefixCls", "info", "className", "direction", "onClick", "active", "menu"],
2
+ var _excluded = ["prefixCls", "info", "className", "direction", "onClick", "active", "selectable", "selected", "onSelect", "menu"],
3
3
  _excluded2 = ["key"];
4
4
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
5
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -19,6 +19,7 @@ import React, { useEffect, useRef, useState } from 'react';
19
19
  import pickAttrs from 'rc-util/lib/pickAttrs';
20
20
  import { SparkMoreLine } from '@agentscope-ai/icons';
21
21
  import { Button, Checkbox, IconButton, Popover } from '@agentscope-ai/design';
22
+ import { useInViewport } from 'ahooks';
22
23
  import { jsx as _jsx } from "react/jsx-runtime";
23
24
  import { jsxs as _jsxs } from "react/jsx-runtime";
24
25
  var editableMap = {};
@@ -28,14 +29,14 @@ export function useEditable(id) {
28
29
  editable = _useState2[0],
29
30
  setEditable = _useState2[1];
30
31
  return [editable, function (value) {
31
- for (var key in editableMap) {
32
- editableMap[key] = false;
32
+ for (var _key in editableMap) {
33
+ editableMap[_key] = false;
33
34
  }
34
35
  editableMap[id] = value;
35
36
  setEditable(value);
36
37
  }];
37
38
  }
38
- var ConversationsItem = function ConversationsItem(props) {
39
+ var ConversationsItem = /*#__PURE__*/React.memo(function (props) {
39
40
  var _menu$find;
40
41
  var _useEditable = useEditable(props.info.key),
41
42
  _useEditable2 = _slicedToArray(_useEditable, 2),
@@ -51,6 +52,9 @@ var ConversationsItem = function ConversationsItem(props) {
51
52
  direction = props.direction,
52
53
  onClick = props.onClick,
53
54
  active = props.active,
55
+ selectable = props.selectable,
56
+ selected = props.selected,
57
+ onSelect = props.onSelect,
54
58
  menu = props.menu,
55
59
  restProps = _objectWithoutProperties(props, _excluded);
56
60
  var domProps = pickAttrs(restProps, {
@@ -58,37 +62,41 @@ var ConversationsItem = function ConversationsItem(props) {
58
62
  data: true,
59
63
  attr: true
60
64
  });
65
+ var ref = useRef(null);
66
+ var _useInViewport = useInViewport(ref),
67
+ _useInViewport2 = _slicedToArray(_useInViewport, 1),
68
+ inViewport = _useInViewport2[0];
61
69
  var disabled = info.disabled;
62
- var mergedCls = classnames(className, "".concat(prefixCls, "-item"), _defineProperty({}, "".concat(prefixCls, "-item-active"), active && !disabled), _defineProperty({}, "".concat(prefixCls, "-item-disabled"), disabled), _defineProperty({}, "".concat(prefixCls, "-item-timeline"), info.timeline || info.selectable));
70
+ var mergedCls = classnames(className, "".concat(prefixCls, "-item"), _defineProperty({}, "".concat(prefixCls, "-item-active"), active && !disabled), _defineProperty({}, "".concat(prefixCls, "-item-disabled"), disabled), _defineProperty({}, "".concat(prefixCls, "-item-timeline"), info.timeline || selectable));
63
71
  var onInternalClick = function onInternalClick() {
64
- if (info.selectable) {
65
- var _info$onSelect;
66
- return (_info$onSelect = info.onSelect) === null || _info$onSelect === void 0 ? void 0 : _info$onSelect.call(info, info.key, !info.selected);
72
+ if (selectable) {
73
+ return onSelect === null || onSelect === void 0 ? void 0 : onSelect(info.key, !selected);
67
74
  }
68
75
  if (!disabled && onClick) {
69
76
  return onClick(info);
70
77
  }
71
78
  };
72
- return /*#__PURE__*/_jsxs("li", _objectSpread(_objectSpread({}, domProps), {}, {
79
+ return /*#__PURE__*/_jsxs("li", _objectSpread(_objectSpread({
80
+ ref: ref
81
+ }, domProps), {}, {
73
82
  className: mergedCls,
74
83
  onClick: onInternalClick,
75
- children: [/*#__PURE__*/_jsxs("div", {
84
+ children: [inViewport && /*#__PURE__*/_jsxs("div", {
76
85
  className: "".concat(prefixCls, "-content"),
77
86
  children: [info.icon && /*#__PURE__*/_jsx("div", {
78
87
  className: "".concat(prefixCls, "-icon"),
79
88
  children: info.icon
80
- }), (info.timeline || info.selectable) && /*#__PURE__*/_jsx("div", {
89
+ }), (info.timeline || selectable) && /*#__PURE__*/_jsx("div", {
81
90
  className: "".concat(prefixCls, "-timeline"),
82
- children: info.selectable ? /*#__PURE__*/_jsx("div", {
91
+ children: selectable ? /*#__PURE__*/_jsx("div", {
83
92
  className: "".concat(prefixCls, "-timeline-checkbox"),
84
93
  onClick: function onClick(e) {
85
94
  return e.stopPropagation();
86
95
  },
87
96
  children: /*#__PURE__*/_jsx(Checkbox, {
88
- checked: info.selected,
97
+ checked: selected,
89
98
  onChange: function onChange() {
90
- var _info$onSelect2;
91
- return (_info$onSelect2 = info.onSelect) === null || _info$onSelect2 === void 0 ? void 0 : _info$onSelect2.call(info, info.key, !info.selected);
99
+ return onSelect === null || onSelect === void 0 ? void 0 : onSelect(info.key, !selected);
92
100
  }
93
101
  })
94
102
  }) : /*#__PURE__*/_jsx("div", {
@@ -102,7 +110,7 @@ var ConversationsItem = function ConversationsItem(props) {
102
110
  onEdit: menu === null || menu === void 0 || (_menu$find = menu.find(function (item) {
103
111
  return item.key === 'edit';
104
112
  })) === null || _menu$find === void 0 ? void 0 : _menu$find.onEdit
105
- }), menu && !disabled && !info.selectable && /*#__PURE__*/_jsx(Popover, {
113
+ }), menu && !disabled && !selectable && /*#__PURE__*/_jsx(Popover, {
106
114
  styles: {
107
115
  body: {
108
116
  padding: 4
@@ -143,15 +151,15 @@ var ConversationsItem = function ConversationsItem(props) {
143
151
  }
144
152
  })
145
153
  })]
146
- }), info.desc && /*#__PURE__*/_jsx("div", {
154
+ }), inViewport && info.desc && /*#__PURE__*/_jsx("div", {
147
155
  className: "".concat(prefixCls, "-desc"),
148
- style: info.timeline || info.selectable ? {
156
+ style: info.timeline || selectable ? {
149
157
  marginLeft: 16
150
158
  } : {},
151
159
  children: info.desc
152
160
  })]
153
161
  }));
154
- };
162
+ });
155
163
  function Label(props) {
156
164
  var editable = props.editable,
157
165
  prefixCls = props.prefixCls,
@@ -210,6 +218,9 @@ function Input(_ref) {
210
218
  ref: ref,
211
219
  className: "".concat(prefixCls, "-label-edit"),
212
220
  value: v,
221
+ onClick: function onClick(e) {
222
+ return e.stopPropagation();
223
+ },
213
224
  onChange: function onChange(e) {
214
225
  return sv(e.target.value);
215
226
  },
@@ -21,6 +21,21 @@ export interface ConversationsProps extends React.HTMLAttributes<HTMLUListElemen
21
21
  * @descriptionEn Callback function when conversation selection changes, receives new conversation identifier
22
22
  */
23
23
  onActiveChange?: (value: string) => void;
24
+ /**
25
+ * @description 是否开启批量选择模式
26
+ * @descriptionEn Whether to enable batch selection mode
27
+ */
28
+ selectable?: boolean;
29
+ /**
30
+ * @description 当前选中的会话 key 列表
31
+ * @descriptionEn Currently selected conversation key list
32
+ */
33
+ selectedKeys?: string[];
34
+ /**
35
+ * @description 批量选择变化时的回调函数
36
+ * @descriptionEn Callback when batch selection changes
37
+ */
38
+ onSelectChange?: (selectedKeys: string[]) => void;
24
39
  /**
25
40
  * @description 会话操作菜单配置
26
41
  * @descriptionEn Conversation operation menu configuration
@@ -1,7 +1,11 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["prefixCls", "rootClassName", "items", "activeKey", "defaultActiveKey", "onActiveChange", "menu", "styles", "classNames", "groupable", "className", "style"];
2
+ var _excluded = ["prefixCls", "rootClassName", "items", "activeKey", "defaultActiveKey", "onActiveChange", "selectable", "selectedKeys", "onSelectChange", "menu", "styles", "classNames", "groupable", "className", "style"];
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
6
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
8
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
5
9
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
10
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
7
11
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
@@ -32,6 +36,9 @@ var Conversations = function Conversations(props) {
32
36
  activeKey = props.activeKey,
33
37
  defaultActiveKey = props.defaultActiveKey,
34
38
  onActiveChange = props.onActiveChange,
39
+ propsSelectable = props.selectable,
40
+ selectedKeys = props.selectedKeys,
41
+ onSelectChange = props.onSelectChange,
35
42
  menu = props.menu,
36
43
  _props$styles = props.styles,
37
44
  styles = _props$styles === void 0 ? {} : _props$styles,
@@ -61,18 +68,34 @@ var Conversations = function Conversations(props) {
61
68
  getPrefixCls = _useProviderContext.getPrefixCls;
62
69
  var prefixCls = getPrefixCls('conversations');
63
70
  var mergedCls = classnames(prefixCls, className, rootClassName, _defineProperty({}, "".concat(prefixCls, "-rtl"), direction === 'rtl'));
64
- var onConversationItemClick = function onConversationItemClick(info) {
71
+ var onActiveChangeRef = React.useRef(onActiveChange);
72
+ onActiveChangeRef.current = onActiveChange;
73
+ var onConversationItemClick = React.useCallback(function (info) {
74
+ var _onActiveChangeRef$cu;
65
75
  setMergedActiveKey(info.key);
66
- if (onActiveChange) {
67
- onActiveChange(info.key);
68
- }
69
- };
76
+ (_onActiveChangeRef$cu = onActiveChangeRef.current) === null || _onActiveChangeRef$cu === void 0 || _onActiveChangeRef$cu.call(onActiveChangeRef, info.key);
77
+ }, [setMergedActiveKey]);
78
+ var selectedKeysRef = React.useRef(selectedKeys);
79
+ selectedKeysRef.current = selectedKeys;
80
+ var onSelectChangeRef = React.useRef(onSelectChange);
81
+ onSelectChangeRef.current = onSelectChange;
82
+ var handleItemSelect = React.useCallback(function (key, selected) {
83
+ if (!onSelectChangeRef.current) return;
84
+ var keys = selectedKeysRef.current || [];
85
+ var next = selected ? [].concat(_toConsumableArray(keys), [key]) : keys.filter(function (k) {
86
+ return k !== key;
87
+ });
88
+ onSelectChangeRef.current(next);
89
+ }, []);
70
90
  return /*#__PURE__*/_jsxs(_Fragment, {
71
91
  children: [/*#__PURE__*/_jsx(Style, {}), /*#__PURE__*/_jsx("ul", _objectSpread(_objectSpread({}, domProps), {}, {
72
92
  style: style,
73
93
  className: mergedCls,
74
94
  children: groupList.map(function (groupInfo, groupIndex) {
75
95
  var convItems = groupInfo.data.map(function (convInfo, convIndex) {
96
+ var itemSelectable = propsSelectable !== null && propsSelectable !== void 0 ? propsSelectable : convInfo.selectable;
97
+ var itemSelected = itemSelectable ? selectedKeys ? selectedKeys.includes(convInfo.key) : convInfo.selected : false;
98
+ var itemOnSelect = onSelectChange ? handleItemSelect : convInfo.onSelect;
76
99
  return /*#__PURE__*/_jsx(ConversationsItem, {
77
100
  info: convInfo,
78
101
  prefixCls: prefixCls,
@@ -81,6 +104,9 @@ var Conversations = function Conversations(props) {
81
104
  style: styles.item,
82
105
  menu: menu,
83
106
  active: mergedActiveKey === convInfo.key,
107
+ selectable: itemSelectable,
108
+ selected: itemSelected,
109
+ onSelect: itemOnSelect,
84
110
  onClick: onConversationItemClick
85
111
  }, convInfo.key || "key-".concat(convIndex));
86
112
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentscope-ai/chat",
3
- "version": "1.1.51",
3
+ "version": "1.1.52-beta.1772784852386",
4
4
  "description": "a free and open-source chat framework for building excellent LLM-powered chat experiences",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": [