@agentscope-ai/chat 1.1.43 → 1.1.44-beta.1766022966609

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.
@@ -0,0 +1,75 @@
1
+ # agentscope-runtime-starter-webui
2
+
3
+ ## node version
4
+
5
+ > =22
6
+
7
+ ## install
8
+
9
+ ```
10
+ $ npm run install
11
+ ```
12
+
13
+ ## dev
14
+
15
+ ```
16
+ $ npm run dev
17
+ ```
18
+
19
+ ## build
20
+
21
+ ```
22
+ $ npm run build
23
+ ```
24
+
25
+ ## Core Code
26
+ ```tsx
27
+ import { AgentScopeRuntimeWebUI } from '@agentscope-ai/chat';
28
+
29
+ const options = {
30
+ theme: {
31
+ colorPrimary: '#615CED',
32
+ darkMode: true,
33
+ prefix: 'agentscope-runtime-webui',
34
+ leftHeader: {
35
+ logo: 'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
36
+ title: 'Runtime WebUI',
37
+ },
38
+ },
39
+ sender: {
40
+ maxLength: 10000,
41
+ disclaimer:
42
+ 'AI can also make mistakes, so please check carefully and use it with caution',
43
+ },
44
+
45
+ welcome: {
46
+ greeting: 'Hello, how can I help you today?',
47
+ description:
48
+ 'I am a helpful assistant that can help you with your questions.',
49
+ avatar:
50
+ 'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
51
+ prompts: [
52
+ {
53
+ value: 'Hello',
54
+ },
55
+ {
56
+ value: 'How are you?',
57
+ },
58
+ {
59
+ value: 'What can you do?',
60
+ },
61
+ ],
62
+ },
63
+ api: {
64
+ baseURL: 'YOUR_API_URL',
65
+ token: 'YOUR_API_TOKEN', // is not required
66
+ },
67
+ };
68
+
69
+
70
+ <AgentScopeRuntimeWebUI
71
+ options={options}
72
+ />
73
+
74
+
75
+ ```
@@ -0,0 +1,28 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from 'typescript-eslint'
6
+
7
+ export default tseslint.config(
8
+ { ignores: ['dist'] },
9
+ {
10
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
11
+ files: ['**/*.{ts,tsx}'],
12
+ languageOptions: {
13
+ ecmaVersion: 2020,
14
+ globals: globals.browser,
15
+ },
16
+ plugins: {
17
+ 'react-hooks': reactHooks,
18
+ 'react-refresh': reactRefresh,
19
+ },
20
+ rules: {
21
+ ...reactHooks.configs.recommended.rules,
22
+ 'react-refresh/only-export-components': [
23
+ 'warn',
24
+ { allowConstantExport: true },
25
+ ],
26
+ },
27
+ },
28
+ )
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>AgentScope Runtime Starter WebUI</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "agentscope-runtime-starter-webui",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite --host",
8
+ "build": "tsc -b && vite build",
9
+ "lint": "eslint .",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "@agentscope-ai/icons": "^1.0.46",
14
+ "@agentscope-ai/chat": "^1.1.37",
15
+ "@agentscope-ai/design": "^1.0.19",
16
+ "antd": "^5.29.1",
17
+ "antd-style": "^3.7.1",
18
+ "react": "^18",
19
+ "react-dom": "^18"
20
+ },
21
+ "devDependencies": {
22
+ "@eslint/js": "^9.25.0",
23
+ "@types/react": "^18",
24
+ "@types/react-dom": "^18",
25
+ "@vitejs/plugin-react": "^4.4.1",
26
+ "eslint": "^9.25.0",
27
+ "eslint-plugin-react-hooks": "^5.2.0",
28
+ "eslint-plugin-react-refresh": "^0.4.19",
29
+ "globals": "^16.0.0",
30
+ "typescript": "~5.8.3",
31
+ "typescript-eslint": "^8.30.1",
32
+ "vite": "^6.3.5"
33
+ }
34
+ }
@@ -0,0 +1,20 @@
1
+ import Chat from './components/Chat';
2
+
3
+ import { createGlobalStyle } from 'antd-style';
4
+
5
+
6
+ const GlobalStyle = createGlobalStyle`
7
+ * {
8
+ margin: 0;
9
+ box-sizing: border-box;
10
+ }
11
+ `;
12
+
13
+ function App() {
14
+ return <>
15
+ <GlobalStyle />
16
+ <Chat />
17
+ </>
18
+ }
19
+
20
+ export default App
@@ -0,0 +1,37 @@
1
+ import { Form } from 'antd';
2
+ import { createStyles } from 'antd-style';
3
+
4
+
5
+ interface FormItemProps {
6
+ name: string | string[];
7
+ label: string;
8
+ isList?: boolean;
9
+ children: any;
10
+ normalize?: (value: any) => any;
11
+ }
12
+
13
+
14
+ const useStyles = createStyles(({ token }) => ({
15
+ label: {
16
+ marginBottom: 6,
17
+ fontSize: 12,
18
+ color: token.colorTextSecondary,
19
+ },
20
+
21
+ }));
22
+
23
+ export default function FormItem(props: FormItemProps) {
24
+ const { styles } = useStyles();
25
+
26
+
27
+ const node = props.isList ?
28
+ <Form.List name={props.name}>{props.children}</Form.List> :
29
+ <Form.Item name={props.name} normalize={props.normalize}>{props.children}</Form.Item>;
30
+
31
+
32
+ return <div>
33
+ {props.label && <div className={styles.label}>{props.label}</div>}
34
+ {node}
35
+ </div>
36
+
37
+ }
@@ -0,0 +1,160 @@
1
+ import React from 'react';
2
+ import { Form, Input, ColorPicker, Flex, Divider, InputNumber } from 'antd';
3
+ import { createStyles } from 'antd-style';
4
+ import { Button, IconButton, Switch } from '@agentscope-ai/design'
5
+ import { SparkDeleteLine, SparkPlusLine } from '@agentscope-ai/icons';
6
+ import FormItem from './FormItem';
7
+ import defaultConfig from './defaultConfig';
8
+
9
+ const useStyles = createStyles(({ token }) => ({
10
+ container: {
11
+ height: '100%',
12
+ display: 'flex',
13
+ flexDirection: 'column',
14
+ },
15
+
16
+ form: {
17
+ height: 0,
18
+ flex: 1,
19
+ padding: '8px 16px 16px 16px',
20
+ overflow: 'auto',
21
+ },
22
+ actions: {
23
+ padding: 16,
24
+ display: 'flex',
25
+ borderTop: `1px solid ${token.colorBorderSecondary}`,
26
+ justifyContent: 'flex-end',
27
+ gap: 16,
28
+ }
29
+
30
+ }));
31
+
32
+ interface OptionsEditorProps {
33
+ value?: any;
34
+ onChange?: any;
35
+ }
36
+
37
+ const OptionsEditor: React.FC<OptionsEditorProps> = ({
38
+ value,
39
+ onChange,
40
+ }) => {
41
+ const { styles } = useStyles();
42
+ const [form] = Form.useForm();
43
+
44
+
45
+ const handleSave = () => {
46
+ form.validateFields().then((values) => {
47
+ onChange(values);
48
+ });
49
+ };
50
+
51
+ const handleReset = () => {
52
+ form.setFieldsValue(defaultConfig);
53
+ };
54
+
55
+ return (
56
+ <div className={styles.container}>
57
+ <Form
58
+ className={styles.form}
59
+ form={form}
60
+ layout="vertical"
61
+ initialValues={value}
62
+ >
63
+
64
+
65
+ <Divider orientation="left">Theme</Divider>
66
+
67
+ <FormItem name={['theme', 'colorPrimary']} label="colorPrimary" normalize={value => value.toHexString()}>
68
+ <ColorPicker />
69
+ </FormItem>
70
+
71
+ <FormItem name={['theme', 'colorBgBase']} label="colorBgBase" normalize={value => value.toHexString()}>
72
+ <ColorPicker />
73
+ </FormItem>
74
+
75
+ <FormItem name={['theme', 'colorTextBase']} label="colorTextBase" normalize={value => value.toHexString()}>
76
+ <ColorPicker />
77
+ </FormItem>
78
+
79
+ <FormItem name={['theme', 'darkMode']} label="darkMode" >
80
+ <Switch />
81
+ </FormItem>
82
+
83
+ <FormItem name={['theme', 'leftHeader', 'logo']} label="leftHeader.logo" >
84
+ <Input />
85
+ </FormItem>
86
+
87
+ <FormItem name={['theme', 'leftHeader', 'title']} label="leftHeader.title" >
88
+ <Input />
89
+ </FormItem>
90
+
91
+ <Divider orientation="left">Sender</Divider>
92
+
93
+
94
+ <FormItem name={['sender', 'disclaimer']} label="disclaimer" >
95
+ <Input />
96
+ </FormItem>
97
+
98
+
99
+
100
+
101
+ <FormItem name={['sender', 'maxLength']} label="maxLength" >
102
+ <InputNumber min={1000} />
103
+ </FormItem>
104
+
105
+ <Divider orientation="left">Welcome</Divider>
106
+
107
+
108
+ <FormItem name={['welcome', 'greeting']} label="greeting" >
109
+ <Input />
110
+ </FormItem>
111
+
112
+ <FormItem name={['welcome', 'description']} label="description" >
113
+ <Input />
114
+ </FormItem>
115
+
116
+ <FormItem name={['welcome', 'avatar']} label="avatar" >
117
+ <Input />
118
+ </FormItem>
119
+
120
+
121
+ <FormItem name={['welcome', 'prompts']} isList label="prompts" >
122
+ {(fields: { key: string, name: string }[], { add, remove }: { add: (item: any) => void, remove: (name: string) => void }) => {
123
+ return <div>
124
+ {fields.map(field => {
125
+ return <Flex key={field.key} gap={6}>
126
+ <Form.Item style={{ flex: 1 }} key={field.key} name={[field.name, 'value']}>
127
+ <Input />
128
+ </Form.Item>
129
+ <IconButton icon={<SparkPlusLine />} onClick={() => add({})}></IconButton>
130
+ <IconButton icon={<SparkDeleteLine />} onClick={() => remove(field.name)}></IconButton>
131
+ </Flex>
132
+ })}
133
+ </div>
134
+ }}
135
+ </FormItem>
136
+
137
+
138
+ <Divider orientation="left">API</Divider>
139
+
140
+ <FormItem name={['api', 'baseURL']} label="baseURL" >
141
+ <Input />
142
+ </FormItem>
143
+
144
+ <FormItem name={['api', 'token']} label="token" >
145
+ <Input />
146
+ </FormItem>
147
+ </Form>
148
+
149
+ <div className={styles.actions}>
150
+ <Button onClick={handleReset}>Reset</Button>
151
+ <Button type="primary" onClick={handleSave}>
152
+ Save & Copy
153
+ </Button>
154
+ </div>
155
+ </div>
156
+ );
157
+ };
158
+
159
+ export default OptionsEditor;
160
+
@@ -0,0 +1,41 @@
1
+ export default {
2
+ theme: {
3
+ colorPrimary: '#615CED',
4
+ darkMode: true,
5
+ prefix: 'agentscope-runtime-webui',
6
+ leftHeader: {
7
+ logo: 'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
8
+ title: 'Runtime WebUI',
9
+ },
10
+ },
11
+ sender: {
12
+ attachments: false,
13
+ maxLength: 10000,
14
+ disclaimer:
15
+ 'AI can also make mistakes, so please check carefully and use it with caution',
16
+ },
17
+
18
+ welcome: {
19
+ greeting: 'Hello, how can I help you today?',
20
+ description:
21
+ 'I am a helpful assistant that can help you with your questions.',
22
+ avatar:
23
+ 'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
24
+ prompts: [
25
+ {
26
+ value: 'Hello',
27
+ },
28
+ {
29
+ value: 'How are you?',
30
+ },
31
+ {
32
+ value: 'What can you do?',
33
+ },
34
+ ],
35
+ },
36
+ api: {
37
+ baseURL: BASE_URL,
38
+ token: TOKEN,
39
+ },
40
+ };
41
+
@@ -0,0 +1,27 @@
1
+ import { SparkSettingLine } from "@agentscope-ai/icons";
2
+ import { IconButton, Drawer } from "@agentscope-ai/design";
3
+ import { useState } from "react";
4
+ import OptionsEditor from "./OptionsEditor";
5
+
6
+ interface OptionsPanelProps {
7
+ value?: any;
8
+ onChange?: any;
9
+ }
10
+
11
+ export default function OptionsPanel(props: OptionsPanelProps) {
12
+ const [open, setOpen] = useState(false);
13
+
14
+ return <>
15
+ <IconButton onClick={() => setOpen(true)} icon={<SparkSettingLine />} bordered={false} />
16
+ <Drawer
17
+ destroyOnHidden
18
+ open={open}
19
+ onClose={() => setOpen(false)}
20
+ styles={{ body: { padding: 0 }, header: { padding: 8 } }}>
21
+ <OptionsEditor value={props.value} onChange={(v: typeof props.value) => {
22
+ setOpen(false);
23
+ props.onChange(v);
24
+ }} />
25
+ </Drawer>
26
+ </>
27
+ }
@@ -0,0 +1,45 @@
1
+ import { AgentScopeRuntimeWebUI, IAgentScopeRuntimeWebUIOptions } from '@agentscope-ai/chat';
2
+ import OptionsPanel from './OptionsPanel';
3
+ import { useMemo } from 'react';
4
+ import sessionApi from './sessionApi';
5
+ import { useLocalStorageState } from 'ahooks';
6
+ import defaultConfig from './OptionsPanel/defaultConfig';
7
+
8
+ export default function () {
9
+ const [optionsConfig, setOptionsConfig] = useLocalStorageState('agent-scope-runtime-webui-options', {
10
+ defaultValue: defaultConfig,
11
+ listenStorageChange: true,
12
+ });
13
+
14
+ const options = useMemo(() => {
15
+ const rightHeader = <OptionsPanel value={optionsConfig} onChange={(v: typeof optionsConfig) => {
16
+ setOptionsConfig(prev => ({
17
+ ...prev,
18
+ ...v,
19
+ }));
20
+ }} />;
21
+
22
+
23
+
24
+ return {
25
+ ...optionsConfig,
26
+ session: {
27
+ multiple: true,
28
+ api: sessionApi,
29
+ },
30
+ theme: {
31
+ ...optionsConfig.theme,
32
+ rightHeader,
33
+ },
34
+ };
35
+ }, [optionsConfig]);
36
+
37
+
38
+
39
+
40
+ return <div style={{ height: '100vh' }}>
41
+ <AgentScopeRuntimeWebUI
42
+ options={options as unknown as IAgentScopeRuntimeWebUIOptions}
43
+ />
44
+ </div>;
45
+ }
@@ -0,0 +1,53 @@
1
+ import {
2
+ IAgentScopeRuntimeWebUISession,
3
+ IAgentScopeRuntimeWebUISessionAPI,
4
+ } from '@agentscope-ai/chat';
5
+
6
+ class SessionApi implements IAgentScopeRuntimeWebUISessionAPI {
7
+ private lsKey: string;
8
+ private sessionList: IAgentScopeRuntimeWebUISession[];
9
+
10
+ constructor() {
11
+ this.lsKey = 'agent-scope-runtime-webui-sessions';
12
+ this.sessionList = [];
13
+ }
14
+
15
+ async getSessionList() {
16
+ this.sessionList = JSON.parse(localStorage.getItem(this.lsKey) || '[]');
17
+ return [...this.sessionList];
18
+ }
19
+
20
+ async getSession(sessionId: string) {
21
+ return this.sessionList.find((session) => session.id === sessionId) as IAgentScopeRuntimeWebUISession;
22
+ }
23
+
24
+ async updateSession(session: Partial<IAgentScopeRuntimeWebUISession>) {
25
+ const index = this.sessionList.findIndex((item) => item.id === session.id);
26
+ if (index > -1) {
27
+ this.sessionList[index] = {
28
+ ...this.sessionList[index],
29
+ ...session,
30
+ };
31
+ localStorage.setItem(this.lsKey, JSON.stringify(this.sessionList));
32
+ }
33
+
34
+ return [...this.sessionList];
35
+ }
36
+
37
+ async createSession(session: Partial<IAgentScopeRuntimeWebUISession>) {
38
+ session.id = Date.now().toString();
39
+ this.sessionList.unshift(session as IAgentScopeRuntimeWebUISession);
40
+ localStorage.setItem(this.lsKey, JSON.stringify(this.sessionList));
41
+ return [...this.sessionList];
42
+ }
43
+
44
+ async removeSession(session: Partial<IAgentScopeRuntimeWebUISession>) {
45
+ this.sessionList = this.sessionList.filter(
46
+ (item) => item.id !== session.id,
47
+ );
48
+ localStorage.setItem(this.lsKey, JSON.stringify(this.sessionList));
49
+ return [...this.sessionList];
50
+ }
51
+ }
52
+
53
+ export default new SessionApi();
@@ -0,0 +1,9 @@
1
+ import { StrictMode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import App from './App.tsx'
4
+
5
+ createRoot(document.getElementById('root')!).render(
6
+ <StrictMode>
7
+ <App />
8
+ </StrictMode>,
9
+ )
@@ -0,0 +1,4 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ declare const BASE_URL: string;
4
+ declare const TOKEN: string;
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2020",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "skipLibCheck": true,
9
+
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "moduleDetection": "force",
13
+ "noEmit": true,
14
+ "jsx": "react-jsx",
15
+
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "erasableSyntaxOnly": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noUncheckedSideEffectImports": true
22
+ },
23
+ "include": ["src"]
24
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ "moduleResolution": "bundler",
10
+ "allowImportingTsExtensions": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "erasableSyntaxOnly": true,
18
+ "noFallthroughCasesInSwitch": true,
19
+ "noUncheckedSideEffectImports": true
20
+ },
21
+ "include": ["vite.config.ts"]
22
+ }
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ export default defineConfig({
5
+ define: {
6
+ BASE_URL: JSON.stringify(process.env.BASE_URL || ''),
7
+ TOKEN: JSON.stringify(process.env.TOKEN || ''),
8
+ MOBILE: false,
9
+ },
10
+ plugins: [react()],
11
+ })
@@ -13,7 +13,7 @@ export default function useAttachments(
13
13
  }
14
14
  ) {
15
15
  const [fileList, setFileList, getFileList] = useGetState([]);
16
- const { trigger, ...rest } = attachments;
16
+ const { trigger, ...rest } = attachments || {};
17
17
 
18
18
  if (rest?.customRequest) {
19
19
  const uploadIconButton = <Upload
@@ -6,6 +6,10 @@ export default function () {
6
6
  <Rag
7
7
  query='GPT-5技术博客、行业分析、技术特性 AI原生 GPT-5技术博客、行业分析、技术特性 AI原生'
8
8
  subTitle="GPT-5技术博客、行业分析、技术特性"
9
+ images={[
10
+ 'https://gw.alicdn.com/imgextra/i1/O1CN01n7R7cy1MkE5OYeXV9_!!6000000001472-55-tps-24-24.svg',
11
+ 'https://gw.alicdn.com/imgextra/i1/O1CN01n7R7cy1MkE5OYeXV9_!!6000000001472-55-tps-24-24.svg',
12
+ ]}
9
13
  list={[
10
14
  {
11
15
  title: '【文档库】GPT-5 技术博客', content: 'Aliyun Bailianis a product offered by Alibaba Cloud, which is the cloud computing arm of Alibaba Group. Bailian is a high-performance AI development platform designed to help users build, deploy, and manage machine learning models and AI applications more efficiently.', footer: '来源文档:(真)拟定稿。GPT 的制度研究',
@@ -23,13 +23,18 @@ export interface IRagProps {
23
23
  * @descriptionEn Query
24
24
  */
25
25
  query: string;
26
-
27
26
  /**
28
27
  * @description 检索词前缀
29
28
  * @descriptionEn Query Title
30
29
  * @default '检索 Query:'
31
30
  */
32
31
  queryTitle?: string;
32
+ /**
33
+ * @description 检索图片列表
34
+ * @descriptionEn Query Images
35
+ * @default []
36
+ */
37
+ images?: string[];
33
38
  /**
34
39
  * @description 召回知识列表
35
40
  * @descriptionEn RAG List
@@ -68,9 +73,7 @@ function Images({ images }: { images: string[] }) {
68
73
  } as Locale}
69
74
  >
70
75
  <Image.PreviewGroup>
71
- <div className={`${prefixCls}-rag-item-images`}>
72
- {images.map((image, index) => <Image src={image} key={index} width={44} height={44} />)}
73
- </div>
76
+ {images.map((image, index) => <Image src={image} key={index} width={44} height={44} />)}
74
77
  </Image.PreviewGroup>
75
78
  </ConfigProvider>
76
79
 
@@ -106,7 +109,10 @@ function Item({ item }) {
106
109
  <div>{item.content}</div>
107
110
 
108
111
  {
109
- item.images && <Images images={item.images} />
112
+ item.images &&
113
+ <div className={`${prefixCls}-rag-item-images`}>
114
+ <Images images={item.images} />
115
+ </div>
110
116
  }
111
117
 
112
118
  {
@@ -130,6 +136,7 @@ export default function (props: IRagProps) {
130
136
  placeholder = '未查询到与提问相关知识库',
131
137
  query,
132
138
  queryTitle = '检索 Query:',
139
+ images,
133
140
  } = props;
134
141
  const { getPrefixCls } = useProviderContext();
135
142
  const prefixCls = getPrefixCls('operate-card');
@@ -156,8 +163,13 @@ export default function (props: IRagProps) {
156
163
  children: <>
157
164
  {query && <div className={`${prefixCls}-rag-query`}>
158
165
  <span className={`${prefixCls}-rag-query-title`}>{queryTitle}</span>
159
-
160
- {query}</div>}
166
+ {query}
167
+ </div>}
168
+ {
169
+ images?.length && <div className={`${prefixCls}-rag-query-images`}>
170
+ <Images images={images} />
171
+ </div>
172
+ }
161
173
  {children}
162
174
  </>
163
175
  }}
@@ -228,7 +228,7 @@ export default createGlobalStyle`
228
228
  }
229
229
 
230
230
  &-rag-query {
231
- margin: 0 12px 12px 12px;
231
+ margin: 0 12px 8px 12px;
232
232
  line-height: 20px;
233
233
  font-size: 12px;
234
234
  color: ${(p) => p.theme.colorTextSecondary};
@@ -236,6 +236,12 @@ export default createGlobalStyle`
236
236
  &-title {
237
237
  font-weight: 500;
238
238
  }
239
+
240
+ &-images {
241
+ margin: 0 12px 8px 12px;
242
+ display: flex;
243
+ gap: 8px;
244
+ }
239
245
  }
240
246
 
241
247
  &-rag-item {
@@ -26,8 +26,9 @@ export default function useAttachments(attachments, options) {
26
26
  fileList = _useGetState2[0],
27
27
  setFileList = _useGetState2[1],
28
28
  getFileList = _useGetState2[2];
29
- var trigger = attachments.trigger,
30
- rest = _objectWithoutProperties(attachments, _excluded);
29
+ var _ref = attachments || {},
30
+ trigger = _ref.trigger,
31
+ rest = _objectWithoutProperties(_ref, _excluded);
31
32
  if (rest !== null && rest !== void 0 && rest.customRequest) {
32
33
  var uploadIconButton = /*#__PURE__*/_jsx(Upload, _objectSpread(_objectSpread({
33
34
  fileList: fileList,
@@ -22,6 +22,12 @@ export interface IRagProps {
22
22
  * @default '检索 Query:'
23
23
  */
24
24
  queryTitle?: string;
25
+ /**
26
+ * @description 检索图片列表
27
+ * @descriptionEn Query Images
28
+ * @default []
29
+ */
30
+ images?: string[];
25
31
  /**
26
32
  * @description 召回知识列表
27
33
  * @descriptionEn RAG List
@@ -24,15 +24,12 @@ function Images(_ref) {
24
24
  }
25
25
  },
26
26
  children: /*#__PURE__*/_jsx(Image.PreviewGroup, {
27
- children: /*#__PURE__*/_jsx("div", {
28
- className: "".concat(prefixCls, "-rag-item-images"),
29
- children: images.map(function (image, index) {
30
- return /*#__PURE__*/_jsx(Image, {
31
- src: image,
32
- width: 44,
33
- height: 44
34
- }, index);
35
- })
27
+ children: images.map(function (image, index) {
28
+ return /*#__PURE__*/_jsx(Image, {
29
+ src: image,
30
+ width: 44,
31
+ height: 44
32
+ }, index);
36
33
  })
37
34
  })
38
35
  });
@@ -71,8 +68,11 @@ function Item(_ref2) {
71
68
  className: "".concat(prefixCls, "-rag-item-content"),
72
69
  children: [/*#__PURE__*/_jsx("div", {
73
70
  children: item.content
74
- }), item.images && /*#__PURE__*/_jsx(Images, {
75
- images: item.images
71
+ }), item.images && /*#__PURE__*/_jsx("div", {
72
+ className: "".concat(prefixCls, "-rag-item-images"),
73
+ children: /*#__PURE__*/_jsx(Images, {
74
+ images: item.images
75
+ })
76
76
  }), item.link ? /*#__PURE__*/_jsx("a", {
77
77
  onClick: function onClick() {
78
78
  window.open(item.link, '_blank');
@@ -98,7 +98,8 @@ export default function (props) {
98
98
  placeholder = _props$placeholder === void 0 ? '未查询到与提问相关知识库' : _props$placeholder,
99
99
  query = props.query,
100
100
  _props$queryTitle = props.queryTitle,
101
- queryTitle = _props$queryTitle === void 0 ? '检索 Query:' : _props$queryTitle;
101
+ queryTitle = _props$queryTitle === void 0 ? '检索 Query:' : _props$queryTitle,
102
+ images = props.images;
102
103
  var _useProviderContext3 = useProviderContext(),
103
104
  getPrefixCls = _useProviderContext3.getPrefixCls;
104
105
  var prefixCls = getPrefixCls('operate-card');
@@ -132,6 +133,11 @@ export default function (props) {
132
133
  className: "".concat(prefixCls, "-rag-query-title"),
133
134
  children: queryTitle
134
135
  }), query]
136
+ }), (images === null || images === void 0 ? void 0 : images.length) && /*#__PURE__*/_jsx("div", {
137
+ className: "".concat(prefixCls, "-rag-query-images"),
138
+ children: /*#__PURE__*/_jsx(Images, {
139
+ images: images
140
+ })
135
141
  }), children]
136
142
  })
137
143
  }
@@ -1,7 +1,7 @@
1
1
  var _templateObject;
2
2
  function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
3
3
  import { createGlobalStyle } from 'antd-style';
4
- export default createGlobalStyle(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n.", "-operate-card {\n width: 100%;\n border-radius: ", "px;\n overflow: hidden;\n background-color: ", ";\n\n &-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 12px;\n height: 32px;\n\n &-icon {\n font-size: 16px;\n }\n\n &-title {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n font-weight: 500;\n color: ", ";\n }\n\n &-description {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n color: ", ";\n }\n\n &-arrow {\n margin: 0 0 0 auto;\n }\n\n &-has-body {\n cursor: pointer;\n }\n }\n\n &-body {\n opacity: 0;\n animation: ", "-operate-card-body-open 0.2s ease-in-out forwards;\n \n @keyframes ", "-operate-card-body-open {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n \n }\n\n\n &-line-body {\n margin: 0 12px 12px 20px;\n border-left: 1px solid ", ";\n }\n\n &-thinking {\n padding-left: 16px;\n font-size: 12px;\n line-height: 20px;\n color: ", ";\n opacity: 0.85;\n white-space: pre-wrap;\n }\n\n\n &-todo-list {\n\n &-item {\n height: 32px;\n display: flex;\n align-items: center;\n padding: 0 12px;\n gap: 8px;\n \n color: ", ";\n\n\n &-done {\n color: ", ";\n }\n\n &-icon {\n font-size: 16px;\n }\n\n &-title {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n font-size: 12px;\n }\n\n &-done {\n \n }\n\n }\n \n }\n\n\n &-web-search-item {\n display: flex;\n height: 32px;\n align-items: center;\n padding: 0 12px;\n gap: 8px;\n color: ", ";\n cursor: pointer;\n\n &-icon {\n display: block;\n width: 16px;\n height: 16px;\n border: 1px solid ", ";\n border-radius: 99px;\n }\n\n &-title {\n font-size: 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: ", ";\n\n &:hover {\n color: ", ";\n \n }\n\n }\n\n &-subTitle {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n border-left: 1px solid ", ";\n font-size: 12px;\n line-height: 1;\n color: ", ";\n padding-left: 8px;\n margin-left: 4px;\n }\n\n }\n\n\n &-tool-call-block {\n margin-left: 16px;\n margin-top: 8px;\n\n \n &-title {\n font-size: 12px;\n color: ", ";\n line-height: 20px;\n margin-bottom: 4px;\n }\n\n }\n\n\n\n &-device-action {\n height: auto;\n align-items: flex-start;\n\n &-icon {\n margin-top: 6px;\n }\n\n &-time {\n margin-bottom: 4px;\n font-size: 12px;\n line-height: 20px;\n color: ", ";\n }\n\n &-content {\n \n width: 100%;\n display: flex;\n justify-content: space-between;\n }\n\n &-description {\n width: 0;\n flex: 1;\n margin: 8px 0 6px 0;\n }\n\n &-image {\n margin: 4px 0;\n height: 32px;\n margin-left: 8px;\n display: block;\n border-radius: 6px;\n overflow: hidden;\n border: 1px solid ", ";\n }\n\n\n \n }\n\n &-rag-empty-placeholder {\n padding: 16px 0;\n border: 1px solid ", ";\n border-radius: 6px;\n background-color: ", ";\n line-height: 20px;\n font-size: 12px;\n color: ", ";\n margin: 0 12px 12px 12px;\n }\n\n &-rag-query {\n margin: 0 12px 12px 12px;\n line-height: 20px;\n font-size: 12px;\n color: ", ";\n\n &-title {\n font-weight: 500;\n }\n }\n\n &-rag-item {\n margin-left: 16px;\n\n &-title {\n font-size: 12px;\n color: ", ";\n line-height: 20px;\n margin-bottom: 4px;\n display: flex;\n align-items: center;\n cursor: pointer;\n }\n\n &-content {\n padding: 8px;\n border-radius: 6px;\n background-color: ", ";\n }\n\n &-images {\n margin-top: 8px;\n padding: 8px;\n display: flex;\n gap: 8px;\n background-color: ", ";\n \n }\n\n &-footer {\n display: block;\n margin-top: 8px;\n font-size: 12px;\n line-height: 20px;\n color: ", ";\n }\n\n }\n\n &-rag-item ~ &-rag-item {\n margin-top: 8px;\n }\n}\n"])), function (p) {
4
+ export default createGlobalStyle(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n.", "-operate-card {\n width: 100%;\n border-radius: ", "px;\n overflow: hidden;\n background-color: ", ";\n\n &-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 12px;\n height: 32px;\n\n &-icon {\n font-size: 16px;\n }\n\n &-title {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n font-weight: 500;\n color: ", ";\n }\n\n &-description {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n color: ", ";\n }\n\n &-arrow {\n margin: 0 0 0 auto;\n }\n\n &-has-body {\n cursor: pointer;\n }\n }\n\n &-body {\n opacity: 0;\n animation: ", "-operate-card-body-open 0.2s ease-in-out forwards;\n \n @keyframes ", "-operate-card-body-open {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n \n }\n\n\n &-line-body {\n margin: 0 12px 12px 20px;\n border-left: 1px solid ", ";\n }\n\n &-thinking {\n padding-left: 16px;\n font-size: 12px;\n line-height: 20px;\n color: ", ";\n opacity: 0.85;\n white-space: pre-wrap;\n }\n\n\n &-todo-list {\n\n &-item {\n height: 32px;\n display: flex;\n align-items: center;\n padding: 0 12px;\n gap: 8px;\n \n color: ", ";\n\n\n &-done {\n color: ", ";\n }\n\n &-icon {\n font-size: 16px;\n }\n\n &-title {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n font-size: 12px;\n }\n\n &-done {\n \n }\n\n }\n \n }\n\n\n &-web-search-item {\n display: flex;\n height: 32px;\n align-items: center;\n padding: 0 12px;\n gap: 8px;\n color: ", ";\n cursor: pointer;\n\n &-icon {\n display: block;\n width: 16px;\n height: 16px;\n border: 1px solid ", ";\n border-radius: 99px;\n }\n\n &-title {\n font-size: 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: ", ";\n\n &:hover {\n color: ", ";\n \n }\n\n }\n\n &-subTitle {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n border-left: 1px solid ", ";\n font-size: 12px;\n line-height: 1;\n color: ", ";\n padding-left: 8px;\n margin-left: 4px;\n }\n\n }\n\n\n &-tool-call-block {\n margin-left: 16px;\n margin-top: 8px;\n\n \n &-title {\n font-size: 12px;\n color: ", ";\n line-height: 20px;\n margin-bottom: 4px;\n }\n\n }\n\n\n\n &-device-action {\n height: auto;\n align-items: flex-start;\n\n &-icon {\n margin-top: 6px;\n }\n\n &-time {\n margin-bottom: 4px;\n font-size: 12px;\n line-height: 20px;\n color: ", ";\n }\n\n &-content {\n \n width: 100%;\n display: flex;\n justify-content: space-between;\n }\n\n &-description {\n width: 0;\n flex: 1;\n margin: 8px 0 6px 0;\n }\n\n &-image {\n margin: 4px 0;\n height: 32px;\n margin-left: 8px;\n display: block;\n border-radius: 6px;\n overflow: hidden;\n border: 1px solid ", ";\n }\n\n\n \n }\n\n &-rag-empty-placeholder {\n padding: 16px 0;\n border: 1px solid ", ";\n border-radius: 6px;\n background-color: ", ";\n line-height: 20px;\n font-size: 12px;\n color: ", ";\n margin: 0 12px 12px 12px;\n }\n\n &-rag-query {\n margin: 0 12px 8px 12px;\n line-height: 20px;\n font-size: 12px;\n color: ", ";\n\n &-title {\n font-weight: 500;\n }\n\n &-images {\n margin: 0 12px 8px 12px;\n display: flex;\n gap: 8px;\n }\n }\n\n &-rag-item {\n margin-left: 16px;\n\n &-title {\n font-size: 12px;\n color: ", ";\n line-height: 20px;\n margin-bottom: 4px;\n display: flex;\n align-items: center;\n cursor: pointer;\n }\n\n &-content {\n padding: 8px;\n border-radius: 6px;\n background-color: ", ";\n }\n\n &-images {\n margin-top: 8px;\n padding: 8px;\n display: flex;\n gap: 8px;\n background-color: ", ";\n \n }\n\n &-footer {\n display: block;\n margin-top: 8px;\n font-size: 12px;\n line-height: 20px;\n color: ", ";\n }\n\n }\n\n &-rag-item ~ &-rag-item {\n margin-top: 8px;\n }\n}\n"])), function (p) {
5
5
  return p.theme.prefixCls;
6
6
  }, function (p) {
7
7
  return p.theme.borderRadiusLG;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentscope-ai/chat",
3
- "version": "1.1.43",
3
+ "version": "1.1.44-beta.1766022966609",
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": [