@ray-js/t-agent-ui-ray 0.0.5-beta-1 → 0.0.6-beta-1
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/dist/ChatContainer/index.js +1 -2
- package/dist/EchartsBlockRender/index.js +2 -2
- package/dist/MarkdownRender/index.js +2 -4
- package/dist/MessageInput/AsrInput.d.ts +3 -1
- package/dist/MessageInput/AsrInput.js +10 -5
- package/dist/MessageInput/index.js +62 -22
- package/dist/MessageInput/index.less +4 -1
- package/dist/MessageList/index.d.ts +3 -3
- package/dist/MessageList/index.js +7 -4
- package/dist/MessageRender/index.d.ts +1 -1
- package/dist/MessageRender/index.js +1 -0
- package/dist/TileRender/index.d.ts +1 -1
- package/dist/cards/WorkflowReplyCard/index.js +1 -0
- package/dist/hooks/context.js +1 -1
- package/dist/hooks/index.d.ts +3 -1
- package/dist/hooks/index.js +4 -2
- package/dist/hooks/useAsrInput.d.ts +2 -3
- package/dist/hooks/useAsrInput.js +3 -4
- package/dist/hooks/{useBlockInput.d.ts → useAttachmentInput.d.ts} +1 -3
- package/dist/hooks/{useBlockInput.js → useAttachmentInput.js} +7 -22
- package/dist/hooks/useIsUnmounted.d.ts +1 -0
- package/dist/hooks/useIsUnmounted.js +10 -0
- package/dist/hooks/useSleep.d.ts +1 -0
- package/dist/hooks/useSleep.js +25 -0
- package/dist/tiles/BubbleTile/index.js +8 -7
- package/dist/tiles/ButtonsTile/index.js +1 -0
- package/dist/tiles/DocumentsTile/index.js +1 -0
- package/dist/tiles/RecommendationsTile/index.js +1 -0
- package/dist/tiles/TextTile/index.js +1 -2
- package/dist/tiles/WorkflowTile/index.js +1 -0
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
|
@@ -6,7 +6,6 @@ import './index.less';
|
|
|
6
6
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
7
7
|
import { View } from '@ray-js/components';
|
|
8
8
|
import { getWebSocketStatusSync, SocketStatus } from '@ray-js/t-agent-plugin-assistant';
|
|
9
|
-
import { getSystemInfoSync } from '@ray-js/ray';
|
|
10
9
|
import { ChatAgentContext, MessageContext, RenderContext } from '../contexts';
|
|
11
10
|
import { defaultRenderOptions } from '../renderOption';
|
|
12
11
|
import logger from '../logger';
|
|
@@ -66,7 +65,7 @@ export default function ChatContainer(props) {
|
|
|
66
65
|
break;
|
|
67
66
|
case 'update':
|
|
68
67
|
setMessages(prev => {
|
|
69
|
-
if (getSystemInfoSync().platform === 'android') {
|
|
68
|
+
if (ty.getSystemInfoSync().platform === 'android') {
|
|
70
69
|
var _prev;
|
|
71
70
|
// Android 上有兼容问题,需要手动滚动到底部
|
|
72
71
|
if (((_prev = prev[prev.length - 1]) === null || _prev === void 0 ? void 0 : _prev.id) === message.id) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Render from './index.rjs';
|
|
2
2
|
import logger from '../logger';
|
|
3
|
-
import { getSystemInfoSync } from '@ray-js/ray';
|
|
4
3
|
|
|
5
4
|
// eslint-disable-next-line no-undef
|
|
6
5
|
Component({
|
|
@@ -47,7 +46,8 @@ Component({
|
|
|
47
46
|
});
|
|
48
47
|
const data = JSON.parse(content);
|
|
49
48
|
if (data.option) {
|
|
50
|
-
|
|
49
|
+
// eslint-disable-next-line no-undef
|
|
50
|
+
const pixelRatio = ty.getSystemInfoSync().pixelRatio;
|
|
51
51
|
this.rjs.update(this.data.canvasId, pixelRatio, data.option);
|
|
52
52
|
this.setData({
|
|
53
53
|
loading: false,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "core-js/modules/esnext.iterator.constructor.js";
|
|
1
2
|
import "core-js/modules/esnext.iterator.map.js";
|
|
2
3
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
3
4
|
import './index.less';
|
|
@@ -27,10 +28,7 @@ const MarkdownRender = props => {
|
|
|
27
28
|
}, [text, parser]);
|
|
28
29
|
const sendAction = useSendAction();
|
|
29
30
|
return /*#__PURE__*/React.createElement(View, {
|
|
30
|
-
className: "t-agent-markdown-render"
|
|
31
|
-
onClick: event => {
|
|
32
|
-
console.log('click', event);
|
|
33
|
-
}
|
|
31
|
+
className: "t-agent-markdown-render"
|
|
34
32
|
}, blocks.map(block => {
|
|
35
33
|
const {
|
|
36
34
|
id,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import './index.less';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
interface Props {
|
|
4
|
+
text: string;
|
|
5
|
+
setText: (text: string) => void;
|
|
4
6
|
onBack: () => void;
|
|
5
7
|
sendDisabled: boolean;
|
|
6
|
-
onSend: (
|
|
8
|
+
onSend: () => Promise<any>;
|
|
7
9
|
onError: (error: Error) => void;
|
|
8
10
|
onMoreClick: () => void;
|
|
9
11
|
closeMore: () => void;
|
|
@@ -9,15 +9,15 @@ export default function AsrInput(props) {
|
|
|
9
9
|
onMoreClick,
|
|
10
10
|
moreOpen,
|
|
11
11
|
closeMore,
|
|
12
|
-
hasMore
|
|
12
|
+
hasMore,
|
|
13
|
+
text,
|
|
14
|
+
setText
|
|
13
15
|
} = props;
|
|
14
16
|
const {
|
|
15
17
|
state,
|
|
16
18
|
press,
|
|
17
19
|
release,
|
|
18
20
|
clear,
|
|
19
|
-
text,
|
|
20
|
-
setText,
|
|
21
21
|
currentText,
|
|
22
22
|
incomingText
|
|
23
23
|
} = useAsrInput(props);
|
|
@@ -26,15 +26,18 @@ export default function AsrInput(props) {
|
|
|
26
26
|
}, (state === 'recording' || state === 'pending') && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
27
27
|
className: "t-agent-message-input-voice-mask"
|
|
28
28
|
}), /*#__PURE__*/React.createElement(View, {
|
|
29
|
-
className: "t-agent-message-input-voice-bubble"
|
|
29
|
+
className: "t-agent-message-input-voice-bubble",
|
|
30
|
+
"data-testid": "t-agent-message-input-asr-bubble"
|
|
30
31
|
}, state === 'recording' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, currentText), /*#__PURE__*/React.createElement(Text, {
|
|
31
32
|
className: "t-agent-message-input-voice-bubble-predicted"
|
|
32
33
|
}, incomingText)) : /*#__PURE__*/React.createElement(Textarea, {
|
|
34
|
+
"data-testid": "t-agent-message-input-asr-bubble-input",
|
|
33
35
|
autoHeight: true,
|
|
34
36
|
className: "t-agent-message-input-voice-bubble-input",
|
|
35
37
|
value: text,
|
|
36
38
|
onInput: event => setText(event.value)
|
|
37
39
|
}))), /*#__PURE__*/React.createElement(Button, {
|
|
40
|
+
"data-testid": "t-agent-message-input-asr-button-left",
|
|
38
41
|
className: cx('t-agent-message-input-button', {
|
|
39
42
|
't-agent-message-input-button-text': state === 'init',
|
|
40
43
|
't-agent-message-input-button-hide': state === 'recording',
|
|
@@ -49,6 +52,7 @@ export default function AsrInput(props) {
|
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
}), /*#__PURE__*/React.createElement(Button, {
|
|
55
|
+
"data-testid": "t-agent-message-input-asr-button-middle",
|
|
52
56
|
className: "t-agent-message-input-button t-agent-message-input-button-voice-active",
|
|
53
57
|
disabled: sendDisabled,
|
|
54
58
|
onTouchStart: () => {
|
|
@@ -60,6 +64,7 @@ export default function AsrInput(props) {
|
|
|
60
64
|
onTouchEnd: release
|
|
61
65
|
}), /*#__PURE__*/React.createElement(Button, {
|
|
62
66
|
disabled: sendDisabled,
|
|
67
|
+
"data-testid": "t-agent-message-input-asr-button-right",
|
|
63
68
|
className: cx('t-agent-message-input-button', {
|
|
64
69
|
't-agent-message-input-button-voice-send': state === 'pending',
|
|
65
70
|
't-agent-message-input-button-hide': state === 'recording',
|
|
@@ -70,7 +75,7 @@ export default function AsrInput(props) {
|
|
|
70
75
|
if (state === 'init' && hasMore) {
|
|
71
76
|
onMoreClick();
|
|
72
77
|
} else {
|
|
73
|
-
props.onSend(
|
|
78
|
+
props.onSend();
|
|
74
79
|
clear();
|
|
75
80
|
}
|
|
76
81
|
}
|
|
@@ -5,7 +5,7 @@ import "core-js/modules/web.dom-collections.iterator.js";
|
|
|
5
5
|
import './index.less';
|
|
6
6
|
import { Button, View } from '@ray-js/components';
|
|
7
7
|
import React, { useState } from 'react';
|
|
8
|
-
import { Image, Input, ScrollView
|
|
8
|
+
import { Image, Input, ScrollView } from '@ray-js/ray';
|
|
9
9
|
import { Asr, SocketStatus } from '@ray-js/t-agent-plugin-assistant';
|
|
10
10
|
import cx from 'clsx';
|
|
11
11
|
import PrivateImage from '../PrivateImage';
|
|
@@ -13,24 +13,24 @@ import imageSvg from './icons/image.svg';
|
|
|
13
13
|
import videoSvg from './icons/video.svg';
|
|
14
14
|
import loadingSvg from './icons/loading.svg';
|
|
15
15
|
import closeCircleSvg from './icons/close-circle.svg';
|
|
16
|
-
import { useChatAgent, useEmitEvent, useOnEvent, useRenderOptions
|
|
16
|
+
import { useAttachmentInput, useChatAgent, useEmitEvent, useIsUnmounted, useOnEvent, useRenderOptions } from '../hooks';
|
|
17
17
|
import AsrInput from './AsrInput';
|
|
18
18
|
export default function MessageInput(props) {
|
|
19
19
|
const [moreOpen, setMoreOpen] = useState(false);
|
|
20
|
+
const [text, setText] = useState('');
|
|
21
|
+
const [asrText, setAsrText] = useState('');
|
|
22
|
+
const attachmentInput = useAttachmentInput();
|
|
20
23
|
const {
|
|
21
|
-
text,
|
|
22
|
-
setText,
|
|
23
24
|
uploading,
|
|
24
25
|
uploaded,
|
|
25
26
|
setUploaded,
|
|
26
|
-
blocks,
|
|
27
|
-
loadBlocks,
|
|
28
27
|
upload
|
|
29
|
-
} =
|
|
28
|
+
} = attachmentInput;
|
|
30
29
|
const [responding, setResponding] = useState(false);
|
|
31
30
|
const [mode, setMode] = useState('text');
|
|
32
31
|
const agent = useChatAgent();
|
|
33
32
|
const emitEvent = useEmitEvent();
|
|
33
|
+
const isUnmounted = useIsUnmounted();
|
|
34
34
|
useOnEvent('updateSocketStatus', status => {
|
|
35
35
|
if ((status === SocketStatus.FAILED || status === SocketStatus.CONNECTING) && responding) {
|
|
36
36
|
setResponding(false);
|
|
@@ -38,17 +38,19 @@ export default function MessageInput(props) {
|
|
|
38
38
|
});
|
|
39
39
|
const hasMore = !!agent.plugins.assistant.options.multiModal;
|
|
40
40
|
const isMore = !text.length && hasMore;
|
|
41
|
-
const send = async
|
|
42
|
-
if (!
|
|
41
|
+
const send = async inputBlocks => {
|
|
42
|
+
if (!(inputBlocks !== null && inputBlocks !== void 0 && inputBlocks.length) || attachmentInput.uploading || responding) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
setUploaded([]);
|
|
46
46
|
setText('');
|
|
47
47
|
setResponding(true);
|
|
48
48
|
try {
|
|
49
|
-
await agent.pushInputBlocks(
|
|
49
|
+
await agent.pushInputBlocks(inputBlocks);
|
|
50
50
|
} finally {
|
|
51
|
-
|
|
51
|
+
if (!isUnmounted()) {
|
|
52
|
+
setResponding(false);
|
|
53
|
+
}
|
|
52
54
|
}
|
|
53
55
|
};
|
|
54
56
|
useOnEvent('sendMessage', async _ref => {
|
|
@@ -65,7 +67,9 @@ export default function MessageInput(props) {
|
|
|
65
67
|
try {
|
|
66
68
|
await agent.pushInputBlocks(blocks);
|
|
67
69
|
} finally {
|
|
68
|
-
|
|
70
|
+
if (!isUnmounted()) {
|
|
71
|
+
setResponding(false);
|
|
72
|
+
}
|
|
69
73
|
}
|
|
70
74
|
});
|
|
71
75
|
useOnEvent('setInputBlocks', async _ref2 => {
|
|
@@ -75,7 +79,19 @@ export default function MessageInput(props) {
|
|
|
75
79
|
if (uploading || responding) {
|
|
76
80
|
return;
|
|
77
81
|
}
|
|
78
|
-
|
|
82
|
+
if (mode !== 'text') {
|
|
83
|
+
setMode('text');
|
|
84
|
+
}
|
|
85
|
+
attachmentInput.loadBlocks(blocks);
|
|
86
|
+
let t = '';
|
|
87
|
+
for (const block of blocks) {
|
|
88
|
+
if (block.type === 'text') {
|
|
89
|
+
t = block.text;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (t) {
|
|
93
|
+
setText(t);
|
|
94
|
+
}
|
|
79
95
|
setMoreOpen(false);
|
|
80
96
|
});
|
|
81
97
|
const openMoreClick = () => {
|
|
@@ -100,8 +116,14 @@ export default function MessageInput(props) {
|
|
|
100
116
|
value: text,
|
|
101
117
|
onInput: event => setText(event.detail.value),
|
|
102
118
|
placeholder: props.placeholder,
|
|
119
|
+
"data-testid": "t-agent-message-input-text-inner",
|
|
103
120
|
className: "t-agent-message-input-text-inner",
|
|
104
|
-
onConfirm: () =>
|
|
121
|
+
onConfirm: () => {
|
|
122
|
+
send([...attachmentInput.blocks, {
|
|
123
|
+
type: 'text',
|
|
124
|
+
text
|
|
125
|
+
}]);
|
|
126
|
+
},
|
|
105
127
|
maxLength: 200,
|
|
106
128
|
placeholderStyle: "color: var(--app-B1-N4)",
|
|
107
129
|
onFocus: () => {
|
|
@@ -111,15 +133,17 @@ export default function MessageInput(props) {
|
|
|
111
133
|
});
|
|
112
134
|
}
|
|
113
135
|
}), /*#__PURE__*/React.createElement(Button, {
|
|
136
|
+
"data-testid": "t-agent-message-input-button-asr",
|
|
114
137
|
onClick: async () => {
|
|
115
138
|
const auth = await Asr.authorize();
|
|
116
139
|
if (!auth) {
|
|
117
|
-
showToast({
|
|
140
|
+
ty.showToast({
|
|
118
141
|
icon: 'none',
|
|
119
142
|
title: I18n.t('chat.input.voice.requirePermission')
|
|
120
143
|
});
|
|
121
144
|
return;
|
|
122
145
|
}
|
|
146
|
+
setText('');
|
|
123
147
|
setMode('voice');
|
|
124
148
|
},
|
|
125
149
|
className: "t-agent-message-input-button t-agent-message-input-button-voice"
|
|
@@ -130,25 +154,41 @@ export default function MessageInput(props) {
|
|
|
130
154
|
't-agent-message-input-button-more-open': moreOpen && isMore,
|
|
131
155
|
't-agent-message-input-button-send': !isMore
|
|
132
156
|
}),
|
|
157
|
+
"data-testid": "t-agent-message-input-button-main",
|
|
133
158
|
onClick: async () => {
|
|
134
159
|
if (isMore) {
|
|
135
160
|
openMoreClick();
|
|
136
|
-
} else {
|
|
137
|
-
await send(
|
|
161
|
+
} else if (text) {
|
|
162
|
+
await send([...attachmentInput.blocks, {
|
|
163
|
+
type: 'text',
|
|
164
|
+
text
|
|
165
|
+
}]);
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
168
|
}));
|
|
141
169
|
} else {
|
|
142
170
|
container = /*#__PURE__*/React.createElement(AsrInput, {
|
|
143
|
-
|
|
171
|
+
text: asrText,
|
|
172
|
+
setText: setAsrText,
|
|
173
|
+
onBack: () => {
|
|
174
|
+
setText('');
|
|
175
|
+
setMode('text');
|
|
176
|
+
},
|
|
144
177
|
moreOpen: moreOpen,
|
|
145
178
|
closeMore: () => setMoreOpen(false),
|
|
146
179
|
onMoreClick: openMoreClick,
|
|
147
180
|
sendDisabled: responding || uploading,
|
|
148
|
-
onSend:
|
|
181
|
+
onSend: async () => {
|
|
182
|
+
if (asrText) {
|
|
183
|
+
await send([...attachmentInput.blocks, {
|
|
184
|
+
type: 'text',
|
|
185
|
+
text: asrText
|
|
186
|
+
}]);
|
|
187
|
+
}
|
|
188
|
+
},
|
|
149
189
|
hasMore: hasMore,
|
|
150
190
|
onError: error => {
|
|
151
|
-
showToast({
|
|
191
|
+
ty.showToast({
|
|
152
192
|
icon: 'error',
|
|
153
193
|
title: error.message
|
|
154
194
|
});
|
|
@@ -216,7 +256,7 @@ export default function MessageInput(props) {
|
|
|
216
256
|
try {
|
|
217
257
|
await upload('image', 1);
|
|
218
258
|
} catch (e) {
|
|
219
|
-
showToast({
|
|
259
|
+
ty.showToast({
|
|
220
260
|
icon: 'error',
|
|
221
261
|
title: I18n.t('common.upload.failed')
|
|
222
262
|
});
|
|
@@ -232,7 +272,7 @@ export default function MessageInput(props) {
|
|
|
232
272
|
try {
|
|
233
273
|
await upload('video', 1);
|
|
234
274
|
} catch (e) {
|
|
235
|
-
showToast({
|
|
275
|
+
ty.showToast({
|
|
236
276
|
icon: 'error',
|
|
237
277
|
title: I18n.t('common.upload.failed')
|
|
238
278
|
});
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
.t-agent-message-input {
|
|
11
|
+
padding-bottom: var(--t-agent-safe-bottom);
|
|
12
|
+
}
|
|
10
13
|
|
|
11
14
|
.t-agent-message-input-container {
|
|
12
15
|
--t-agent-input-border-color: var(--app-B1-N7);
|
|
13
|
-
padding-bottom: var(--t-agent-safe-bottom);
|
|
14
16
|
border-top: 2rpx solid var(--t-agent-input-border-color);
|
|
15
17
|
background: var(--app-B1);
|
|
16
18
|
}
|
|
@@ -259,6 +261,7 @@
|
|
|
259
261
|
color: var(--app-M1-N1);
|
|
260
262
|
font-size: 32rpx;
|
|
261
263
|
transition: height 0.2s ease-in-out;
|
|
264
|
+
white-space: pre-wrap;
|
|
262
265
|
|
|
263
266
|
&::after {
|
|
264
267
|
content: '';
|
|
@@ -3,9 +3,9 @@ import React from 'react';
|
|
|
3
3
|
interface Props {
|
|
4
4
|
className?: string;
|
|
5
5
|
roleSide?: {
|
|
6
|
-
user?: 'start' | 'end';
|
|
7
|
-
assistant?: 'start' | 'end';
|
|
8
|
-
[key: string]: 'start' | 'end';
|
|
6
|
+
user?: 'start' | 'end' | string;
|
|
7
|
+
assistant?: 'start' | 'end' | string;
|
|
8
|
+
[key: string]: 'start' | 'end' | string;
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
11
|
export default function MessageList(props: Props): React.JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "core-js/modules/es.array.reverse.js";
|
|
2
|
+
import "core-js/modules/esnext.iterator.constructor.js";
|
|
2
3
|
import "core-js/modules/esnext.iterator.map.js";
|
|
3
4
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
4
5
|
import './index.less';
|
|
@@ -6,7 +7,7 @@ import { View } from '@ray-js/components';
|
|
|
6
7
|
import React, { useMemo, useState } from 'react';
|
|
7
8
|
import { ScrollView } from '@ray-js/ray';
|
|
8
9
|
import MessageRender from '../MessageRender';
|
|
9
|
-
import { useAgentMessage, useOnEvent } from '../hooks';
|
|
10
|
+
import { useAgentMessage, useOnEvent, useSleep } from '../hooks';
|
|
10
11
|
export default function MessageList(props) {
|
|
11
12
|
const {
|
|
12
13
|
className,
|
|
@@ -18,25 +19,27 @@ export default function MessageList(props) {
|
|
|
18
19
|
const [scrollAnimation, setScrollAnimation] = useState(false);
|
|
19
20
|
// 最大整数位数,用于强制滚动到底部,收到连续 scrollToBottom 时,每 10 毫秒更新一次
|
|
20
21
|
const [scrollTop, setScrollTop] = useState(() => 1000000000000000 + Math.floor(Date.now() / 10));
|
|
22
|
+
const sleep = useSleep();
|
|
21
23
|
|
|
22
24
|
// 强制滚动到底部
|
|
23
25
|
useOnEvent('scrollToBottom', _ref => {
|
|
24
26
|
let {
|
|
25
27
|
animation
|
|
26
28
|
} = _ref;
|
|
27
|
-
|
|
29
|
+
sleep(100).then(() => {
|
|
28
30
|
setScrollAnimation(!!animation);
|
|
29
31
|
const top = 1000000000000000 + Math.floor(Date.now() / 10);
|
|
30
32
|
if (top !== scrollTop) {
|
|
31
33
|
setScrollTop(top);
|
|
32
34
|
}
|
|
33
|
-
}
|
|
35
|
+
});
|
|
34
36
|
});
|
|
35
37
|
|
|
36
38
|
// 使用翻转列表,让滚动和新消息出现在第一条,这样可以避免滚动到底部时的闪烁
|
|
37
39
|
const reversed = useMemo(() => [...messages].reverse(), [messages]);
|
|
38
40
|
return /*#__PURE__*/React.createElement(View, {
|
|
39
|
-
className: "t-agent-message-list"
|
|
41
|
+
className: "t-agent-message-list",
|
|
42
|
+
"data-testid": "t-agent-message-list"
|
|
40
43
|
}, /*#__PURE__*/React.createElement(ScrollView, {
|
|
41
44
|
className: "".concat(className || '', " t-agent-message-list-scroll"),
|
|
42
45
|
scrollWithAnimation: scrollAnimation,
|
|
@@ -4,7 +4,7 @@ import { ChatMessageObject } from '@ray-js/t-agent';
|
|
|
4
4
|
interface Props {
|
|
5
5
|
message: ChatMessageObject;
|
|
6
6
|
isLatestMessage: boolean;
|
|
7
|
-
side: 'start' | 'end';
|
|
7
|
+
side: 'start' | 'end' | string;
|
|
8
8
|
}
|
|
9
9
|
export default function MessageRender({ message, isLatestMessage, side }: Props): React.JSX.Element;
|
|
10
10
|
export {};
|
|
@@ -4,7 +4,7 @@ import { ChatMessageObject, ChatTileObject } from '@ray-js/t-agent';
|
|
|
4
4
|
interface Props {
|
|
5
5
|
tile: ChatTileObject;
|
|
6
6
|
message: ChatMessageObject;
|
|
7
|
-
side: 'start' | 'end';
|
|
7
|
+
side: 'start' | 'end' | string;
|
|
8
8
|
isLatestMessage?: boolean;
|
|
9
9
|
}
|
|
10
10
|
declare const _default: React.MemoExoticComponent<({ tile, message, isLatestMessage, side }: Props) => React.JSX.Element>;
|
package/dist/hooks/context.js
CHANGED
|
@@ -19,7 +19,7 @@ export const useOnEvent = (eventName, callback) => {
|
|
|
19
19
|
return agent.plugins.ui.onEvent(eventName, detail => {
|
|
20
20
|
callbackRef.current(detail);
|
|
21
21
|
});
|
|
22
|
-
}, [agent, eventName
|
|
22
|
+
}, [agent, eventName]);
|
|
23
23
|
};
|
|
24
24
|
export const useEmitEvent = () => {
|
|
25
25
|
const agent = useChatAgent();
|
package/dist/hooks/index.d.ts
CHANGED
package/dist/hooks/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
export declare enum AsrErrorCode {
|
|
3
2
|
SHORT_TIME = 0
|
|
4
3
|
}
|
|
@@ -7,6 +6,8 @@ export declare class AsrError extends Error {
|
|
|
7
6
|
constructor(errorCode: AsrErrorCode, message?: string);
|
|
8
7
|
}
|
|
9
8
|
export interface UseAsrInputOptions {
|
|
9
|
+
text: string;
|
|
10
|
+
setText: (text: string) => void;
|
|
10
11
|
onError: (error: Error) => void;
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
@@ -27,8 +28,6 @@ export interface UseAsrInputOptions {
|
|
|
27
28
|
+-------------------------+ +--------------------------+
|
|
28
29
|
*/
|
|
29
30
|
export declare function useAsrInput(options: UseAsrInputOptions): {
|
|
30
|
-
text: string;
|
|
31
|
-
setText: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
32
31
|
currentText: string;
|
|
33
32
|
incomingText: string;
|
|
34
33
|
state: "pending" | "recording" | "init";
|
|
@@ -40,17 +40,16 @@ export class AsrError extends Error {
|
|
|
40
40
|
*/
|
|
41
41
|
export function useAsrInput(options) {
|
|
42
42
|
const {
|
|
43
|
+
text,
|
|
44
|
+
setText,
|
|
43
45
|
onError
|
|
44
46
|
} = options;
|
|
45
47
|
const asrRef = useRef(null);
|
|
46
|
-
const [text, setText] = useState('');
|
|
47
48
|
const [currentText, setCurrentText] = useState('');
|
|
48
49
|
const [incomingText, setIncomingText] = useState('');
|
|
49
50
|
const [state, setState] = useState('init');
|
|
50
51
|
const startAt = useRef(0);
|
|
51
52
|
return {
|
|
52
|
-
text,
|
|
53
|
-
setText,
|
|
54
53
|
currentText,
|
|
55
54
|
incomingText,
|
|
56
55
|
state,
|
|
@@ -99,7 +98,7 @@ export function useAsrInput(options) {
|
|
|
99
98
|
onError(new AsrError(AsrErrorCode.SHORT_TIME));
|
|
100
99
|
setState('init');
|
|
101
100
|
}
|
|
102
|
-
if (Date.now() - startAt.current <
|
|
101
|
+
if (Date.now() - startAt.current < 500 && text.length === 0) {
|
|
103
102
|
onError(new AsrError(AsrErrorCode.SHORT_TIME));
|
|
104
103
|
}
|
|
105
104
|
if (asrRef.current) {
|
|
@@ -6,9 +6,7 @@ export interface UploadFile {
|
|
|
6
6
|
url?: string;
|
|
7
7
|
thumbUrl?: string;
|
|
8
8
|
}
|
|
9
|
-
export declare function
|
|
10
|
-
text: string;
|
|
11
|
-
setText: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
9
|
+
export declare function useAttachmentInput(): {
|
|
12
10
|
blocks: InputBlock[];
|
|
13
11
|
uploaded: UploadFile[];
|
|
14
12
|
setUploaded: import("react").Dispatch<import("react").SetStateAction<UploadFile[]>>;
|
|
@@ -7,19 +7,15 @@ import { useCallback, useMemo, useState } from 'react';
|
|
|
7
7
|
import { chooseImage, chooseVideo, uploadImage, uploadVideo } from '@ray-js/t-agent-plugin-assistant';
|
|
8
8
|
import { generateId } from '@ray-js/t-agent';
|
|
9
9
|
import { useRenderOptions } from './context';
|
|
10
|
-
export function
|
|
11
|
-
const [text, setText] = useState('');
|
|
10
|
+
export function useAttachmentInput() {
|
|
12
11
|
const [uploaded, setUploaded] = useState([]);
|
|
13
12
|
const uploading = useMemo(() => uploaded.some(file => file.type === 'loading'), [uploaded]);
|
|
14
13
|
const blocks = useMemo(() => {
|
|
15
|
-
const
|
|
16
|
-
text,
|
|
17
|
-
type: 'text'
|
|
18
|
-
}];
|
|
14
|
+
const b = [];
|
|
19
15
|
if (uploaded.length) {
|
|
20
16
|
for (const uploadFile of uploaded) {
|
|
21
17
|
if (uploadFile.type === 'image') {
|
|
22
|
-
|
|
18
|
+
b.push({
|
|
23
19
|
type: 'image_url',
|
|
24
20
|
image_url: {
|
|
25
21
|
url: uploadFile.url
|
|
@@ -27,7 +23,7 @@ export function useBlockInput() {
|
|
|
27
23
|
});
|
|
28
24
|
}
|
|
29
25
|
if (uploadFile.type === 'video') {
|
|
30
|
-
|
|
26
|
+
b.push({
|
|
31
27
|
type: 'video_url',
|
|
32
28
|
video_url: {
|
|
33
29
|
url: uploadFile.url,
|
|
@@ -36,12 +32,10 @@ export function useBlockInput() {
|
|
|
36
32
|
});
|
|
37
33
|
}
|
|
38
34
|
}
|
|
39
|
-
setUploaded([]);
|
|
40
35
|
}
|
|
41
|
-
return
|
|
42
|
-
}, [uploaded
|
|
36
|
+
return b;
|
|
37
|
+
}, [uploaded]);
|
|
43
38
|
const loadBlocks = useCallback((blocks, append) => {
|
|
44
|
-
let t = '';
|
|
45
39
|
const uploaded = [];
|
|
46
40
|
for (const block of blocks) {
|
|
47
41
|
if (block.type === 'image_url') {
|
|
@@ -59,17 +53,10 @@ export function useBlockInput() {
|
|
|
59
53
|
thumbUrl: block.video_url.thumb_url
|
|
60
54
|
});
|
|
61
55
|
}
|
|
62
|
-
if (block.type === 'text') {
|
|
63
|
-
t = block.text;
|
|
64
|
-
}
|
|
65
56
|
}
|
|
66
57
|
if (append) {
|
|
67
|
-
|
|
68
|
-
setText(t);
|
|
69
|
-
}
|
|
70
|
-
setUploaded(prev => uploaded.length ? [...prev, ...uploaded] : prev);
|
|
58
|
+
setUploaded(prev => [...prev, ...uploaded]);
|
|
71
59
|
} else {
|
|
72
|
-
setText(t);
|
|
73
60
|
setUploaded(uploaded);
|
|
74
61
|
}
|
|
75
62
|
}, []);
|
|
@@ -136,8 +123,6 @@ export function useBlockInput() {
|
|
|
136
123
|
}
|
|
137
124
|
}, [getStaticResourceBizType]);
|
|
138
125
|
return {
|
|
139
|
-
text,
|
|
140
|
-
setText,
|
|
141
126
|
blocks,
|
|
142
127
|
uploaded,
|
|
143
128
|
setUploaded,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useIsUnmounted(): () => boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
export function useIsUnmounted() {
|
|
3
|
+
const unmounted = useRef(false);
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
return () => {
|
|
6
|
+
unmounted.current = true;
|
|
7
|
+
};
|
|
8
|
+
}, []);
|
|
9
|
+
return useCallback(() => unmounted.current, []);
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useSleep(): (ms: number) => Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "core-js/modules/esnext.iterator.constructor.js";
|
|
2
|
+
import "core-js/modules/esnext.iterator.filter.js";
|
|
3
|
+
import "core-js/modules/esnext.iterator.for-each.js";
|
|
4
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
5
|
+
export function useSleep() {
|
|
6
|
+
const ids = useRef([]);
|
|
7
|
+
const sleep = useCallback(ms => {
|
|
8
|
+
return new Promise(resolve => {
|
|
9
|
+
const id = setTimeout(() => {
|
|
10
|
+
resolve();
|
|
11
|
+
ids.current = ids.current.filter(i => i !== id);
|
|
12
|
+
}, ms);
|
|
13
|
+
ids.current.push(id);
|
|
14
|
+
});
|
|
15
|
+
}, []);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
return () => {
|
|
18
|
+
ids.current.forEach(id => {
|
|
19
|
+
clearTimeout(id);
|
|
20
|
+
});
|
|
21
|
+
ids.current = [];
|
|
22
|
+
};
|
|
23
|
+
}, []);
|
|
24
|
+
return sleep;
|
|
25
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import "core-js/modules/es.json.stringify.js";
|
|
2
|
+
import "core-js/modules/esnext.iterator.constructor.js";
|
|
2
3
|
import "core-js/modules/esnext.iterator.map.js";
|
|
3
4
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
4
5
|
import './index.less';
|
|
5
6
|
import { Text, View } from '@ray-js/components';
|
|
6
7
|
import React, { useEffect, useState } from 'react';
|
|
7
|
-
import {
|
|
8
|
+
import { Image } from '@ray-js/ray';
|
|
8
9
|
import { BubbleTileStatus, ChatMessageStatus, safeParseJSON } from '@ray-js/t-agent';
|
|
9
10
|
import { getCurrentHomeInfo, submitEvaluation } from '@ray-js/t-agent-plugin-assistant';
|
|
10
11
|
import TileRender from '../../TileRender';
|
|
@@ -34,7 +35,7 @@ const BubbleTile = props => {
|
|
|
34
35
|
const [feedbackLoaded, setFeedbackLoaded] = useState(false);
|
|
35
36
|
const [feedbackValue, setFeedbackValue] = useState(null);
|
|
36
37
|
useEffect(() => {
|
|
37
|
-
getStorage({
|
|
38
|
+
ty.getStorage({
|
|
38
39
|
key: 'latestMessageFeedbackValue',
|
|
39
40
|
success: res => {
|
|
40
41
|
if (res.data) {
|
|
@@ -65,9 +66,9 @@ const BubbleTile = props => {
|
|
|
65
66
|
return /*#__PURE__*/React.createElement(View, {
|
|
66
67
|
className: "t-agent-bubble-tile t-agent-bubble-tile-".concat(side),
|
|
67
68
|
onLongPress: () => {
|
|
68
|
-
showToast({
|
|
69
|
-
|
|
70
|
-
});
|
|
69
|
+
// ty.showToast({
|
|
70
|
+
// title: 'long press',
|
|
71
|
+
// });
|
|
71
72
|
}
|
|
72
73
|
}, bubbleStatus === BubbleTileStatus.ERROR && side === 'end' && /*#__PURE__*/React.createElement(Image, {
|
|
73
74
|
onClick: showInfo,
|
|
@@ -102,14 +103,14 @@ const BubbleTile = props => {
|
|
|
102
103
|
score: value,
|
|
103
104
|
channel
|
|
104
105
|
});
|
|
105
|
-
setStorage({
|
|
106
|
+
ty.setStorage({
|
|
106
107
|
key: 'latestMessageFeedbackValue',
|
|
107
108
|
data: JSON.stringify({
|
|
108
109
|
requestId: message.meta.requestId,
|
|
109
110
|
value
|
|
110
111
|
})
|
|
111
112
|
});
|
|
112
|
-
showToast({
|
|
113
|
+
ty.showToast({
|
|
113
114
|
title: I18n.t('chat.feedback.success'),
|
|
114
115
|
icon: 'none'
|
|
115
116
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import { View } from '@ray-js/components';
|
|
3
3
|
import './index.less';
|
|
4
|
-
import { getSystemInfoSync } from '@ray-js/ray';
|
|
5
4
|
import MarkdownRender from '../../MarkdownRender';
|
|
6
5
|
import { useRenderOptions } from '../../hooks';
|
|
7
6
|
const TextTile = props => {
|
|
@@ -13,7 +12,7 @@ const TextTile = props => {
|
|
|
13
12
|
renderCustomBlockAs,
|
|
14
13
|
customBlockTypes
|
|
15
14
|
} = useRenderOptions();
|
|
16
|
-
const theme = useMemo(() => getSystemInfoSync().theme, []);
|
|
15
|
+
const theme = useMemo(() => ty.getSystemInfoSync().theme, []);
|
|
17
16
|
return markdown ? /*#__PURE__*/React.createElement(MarkdownRender, {
|
|
18
17
|
theme: theme,
|
|
19
18
|
text: text,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChatAgent, ChatCardObject, ChatMessageObject, ChatTileObject } from '@ray-js/t-agent';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
export interface TileProps<T = any, P = any> {
|
|
4
|
-
side: 'start' | 'end';
|
|
4
|
+
side: 'start' | 'end' | string;
|
|
5
5
|
message: ChatMessageObject;
|
|
6
6
|
tile: ChatTileObject<T>;
|
|
7
7
|
emitEvent: (payload: P) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ray-js/t-agent-ui-ray",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6-beta-1",
|
|
4
4
|
"author": "Tuya.inc",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"@types/echarts": "^4.9.22",
|
|
42
42
|
"@types/markdown-it": "^14.1.1"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "942a1aeceb65c55ba935409d386bc09f9874e283"
|
|
45
45
|
}
|