@ray-js/t-agent-ui-ray 0.2.0-beta-11 → 0.2.0-beta-13

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.
@@ -6,7 +6,7 @@ interface Props {
6
6
  disabled?: boolean;
7
7
  onConfirm: () => void;
8
8
  onRecord: () => void;
9
- onCancel: () => void;
9
+ onCancel: () => Promise<boolean>;
10
10
  onBack: () => void;
11
11
  onAbort: () => void;
12
12
  }
@@ -12,7 +12,7 @@ const AsrInput = props => {
12
12
  const t = useTranslate();
13
13
  const [active, setActive] = useState(false);
14
14
  const [cancel, setCancel] = useState(false);
15
- const onVoiceTouchEnd = event => {
15
+ const onVoiceTouchEnd = async event => {
16
16
  const touchY = event.changedTouches[0].pageY;
17
17
  setCancel(false);
18
18
  setActive(false);
@@ -30,11 +30,13 @@ const AsrInput = props => {
30
30
  startAt: 0,
31
31
  y: 0
32
32
  };
33
- props.onCancel();
34
- ty.showToast({
35
- icon: 'none',
36
- title: t('t-agent.input.asr.error.too-short')
37
- });
33
+ const result = await props.onCancel();
34
+ if (result) {
35
+ ty.showToast({
36
+ icon: 'none',
37
+ title: t('t-agent.input.asr.error.too-short')
38
+ });
39
+ }
38
40
  return;
39
41
  }
40
42
  props.onConfirm();
@@ -50,10 +52,14 @@ const AsrInput = props => {
50
52
  }, /*#__PURE__*/React.createElement(View, {
51
53
  className: cx('t-agent-message-input-ptt', {
52
54
  't-agent-message-input-ptt-active': active,
53
- 't-agent-message-input-ptt-cancel': cancel
55
+ 't-agent-message-input-ptt-cancel': cancel,
56
+ 't-agent-message-input-ptt-disabled': props.disabled
54
57
  }),
55
58
  onTouchStart: async event => {
56
59
  var _event$touches$;
60
+ if (props.disabled) {
61
+ return;
62
+ }
57
63
  touchRef.current = {
58
64
  startAt: Date.now(),
59
65
  y: (_event$touches$ = event.touches[0]) === null || _event$touches$ === void 0 ? void 0 : _event$touches$.pageY
@@ -5,40 +5,111 @@ import "core-js/modules/esnext.iterator.map.js";
5
5
  import "core-js/modules/web.dom-collections.iterator.js";
6
6
  import '../index.less';
7
7
  import { Button, View } from '@ray-js/components';
8
- import React, { useRef, useState } from 'react';
8
+ import React, { useRef, useState, useMemo } from 'react';
9
9
  import { Image, Input, ScrollView } from '@ray-js/ray';
10
10
  import { AbortController, authorize } from '@ray-js/t-agent-plugin-aistream';
11
- import { Emitter, EmitterEvent } from '@ray-js/t-agent';
11
+ import { Emitter, EmitterEvent, isAbortError } from '@ray-js/t-agent';
12
12
  import cx from 'clsx';
13
13
  import imageSvg from '../icons/image.svg';
14
14
  import videoSvg from '../icons/video.svg';
15
15
  import cameraSvg from '../icons/camera.svg';
16
16
  import { useAttachmentInput, useChatAgent, useEmitEvent, useIsUnmounted, useOnEvent, useTranslate } from '../../hooks';
17
17
  import AsrInput from './AsrInput';
18
- import { useSleep } from '../../hooks/useSleep';
18
+ import logger from '../../logger';
19
19
  const AMPLITUDE_COUNT = 60;
20
+ var InputState = /*#__PURE__*/function (InputState) {
21
+ InputState["PENDING"] = "pending";
22
+ InputState["RECORDING"] = "recording";
23
+ InputState["ASR"] = "asr";
24
+ InputState["RESPONDING"] = "responding";
25
+ InputState["ABORTING"] = "aborting";
26
+ return InputState;
27
+ }(InputState || {});
28
+ var InputAction = /*#__PURE__*/function (InputAction) {
29
+ InputAction["SEND"] = "send";
30
+ InputAction["RECORD"] = "record";
31
+ InputAction["RECORD_TIMEOUT"] = "record_timeout";
32
+ InputAction["RECORD_CANCEL"] = "record_cancel";
33
+ InputAction["RECORD_CONFIRM"] = "record_confirm";
34
+ InputAction["ASR_END"] = "asr_end";
35
+ InputAction["ASR_ERROR"] = "asr_error";
36
+ InputAction["ABORT"] = "abort";
37
+ InputAction["TEXT_END"] = "text_end";
38
+ InputAction["ABORT_DONE"] = "abort_done";
39
+ InputAction["NETWORK_CHANGE"] = "network_change";
40
+ return InputAction;
41
+ }(InputAction || {});
42
+ const transitions = {
43
+ [InputState.PENDING]: {
44
+ [InputAction.SEND]: InputState.RESPONDING,
45
+ [InputAction.RECORD]: InputState.RECORDING,
46
+ [InputAction.NETWORK_CHANGE]: InputState.PENDING,
47
+ // 这个变更是为了兼容 pushInputBlocks 结束的场景,没有实际意义
48
+ [InputAction.TEXT_END]: InputState.PENDING
49
+ },
50
+ [InputState.RECORDING]: {
51
+ [InputAction.RECORD_TIMEOUT]: InputState.ASR,
52
+ [InputAction.NETWORK_CHANGE]: InputState.PENDING,
53
+ [InputAction.RECORD_CANCEL]: InputState.PENDING,
54
+ [InputAction.RECORD_CONFIRM]: InputState.ASR,
55
+ [InputAction.ABORT]: InputState.ABORTING,
56
+ [InputAction.ASR_ERROR]: InputState.PENDING
57
+ },
58
+ [InputState.ASR]: {
59
+ [InputAction.ASR_END]: InputState.RESPONDING,
60
+ [InputAction.ASR_ERROR]: InputState.PENDING,
61
+ [InputAction.ABORT]: InputState.ABORTING,
62
+ [InputAction.NETWORK_CHANGE]: InputState.PENDING
63
+ },
64
+ [InputState.RESPONDING]: {
65
+ [InputAction.ABORT]: InputState.ABORTING,
66
+ [InputAction.TEXT_END]: InputState.PENDING,
67
+ [InputAction.NETWORK_CHANGE]: InputState.PENDING
68
+ },
69
+ [InputState.ABORTING]: {
70
+ [InputAction.ABORT_DONE]: InputState.PENDING,
71
+ [InputAction.NETWORK_CHANGE]: InputState.PENDING
72
+ }
73
+ };
20
74
  export default function MessageInputAIStream(props) {
21
75
  const [moreOpen, setMoreOpen] = useState(false);
22
76
  const t = useTranslate();
23
77
  const [text, setText] = useState('');
24
- const [record, setRecord] = useState({
25
- startAt: 0,
26
- recording: false,
27
- confirm: null,
28
- cancel: null
78
+ const [state, setState] = useState({
79
+ current: InputState.PENDING,
80
+ payload: {}
29
81
  });
30
- const attachmentOptions = {
31
- image: true,
32
- video: true,
33
- imageCount: 1,
34
- videoCount: 1
82
+ const dispatchRef = useRef(null);
83
+ dispatchRef.current = (event, payload) => {
84
+ var _transitions$state$cu;
85
+ const next = (_transitions$state$cu = transitions[state.current]) === null || _transitions$state$cu === void 0 ? void 0 : _transitions$state$cu[event];
86
+ if (next) {
87
+ logger.debug('MessageInputAIStream', "".concat(state.current, " ==").concat(event, "==> ").concat(next));
88
+ setState({
89
+ current: next,
90
+ payload
91
+ });
92
+ return true;
93
+ }
94
+ logger.error('MessageInputAIStream', "".concat(state.current, " ==").concat(event, "==> X not allowed"));
95
+ return false;
35
96
  };
36
- if (props.attachment === false) {
37
- attachmentOptions.image = false;
38
- attachmentOptions.video = false;
39
- } else if (typeof props.attachment === 'object') {
40
- Object.assign(attachmentOptions, props.attachment);
41
- }
97
+ const dispatch = (event, payload) => dispatchRef.current(event, payload);
98
+ const attachmentOptions = useMemo(() => {
99
+ const options = {
100
+ image: true,
101
+ video: true,
102
+ imageCount: 1,
103
+ videoCount: 1
104
+ };
105
+ if (props.attachment === false) {
106
+ options.image = false;
107
+ options.video = false;
108
+ } else if (typeof props.attachment === 'object') {
109
+ Object.assign(options, props.attachment);
110
+ }
111
+ return options;
112
+ }, [props.attachment]);
42
113
  const attachmentInput = useAttachmentInput({
43
114
  local: true
44
115
  });
@@ -48,8 +119,6 @@ export default function MessageInputAIStream(props) {
48
119
  setUploaded,
49
120
  upload
50
121
  } = attachmentInput;
51
- const abortRef = useRef(null);
52
- const [responding, setResponding] = useState(false);
53
122
  const [mode, setMode] = useState('text');
54
123
  const agent = useChatAgent();
55
124
  const emitEvent = useEmitEvent();
@@ -58,8 +127,8 @@ export default function MessageInputAIStream(props) {
58
127
  let {
59
128
  online
60
129
  } = _ref;
61
- if (!online && responding) {
62
- setResponding(false);
130
+ if (!online) {
131
+ dispatch(InputAction.NETWORK_CHANGE, {});
63
132
  }
64
133
  });
65
134
  const hasMore = attachmentOptions.image || attachmentOptions.video;
@@ -68,32 +137,31 @@ export default function MessageInputAIStream(props) {
68
137
  if (!(inputBlocks !== null && inputBlocks !== void 0 && inputBlocks.length)) {
69
138
  return;
70
139
  }
71
- setUploaded([]);
72
- setText('');
73
- setResponding(true);
74
140
  const controller = new AbortController();
75
141
  let abortResolve;
76
- abortRef.current = {
77
- controller,
78
- promise: new Promise(resolve => {
79
- abortResolve = resolve;
80
- })
81
- };
82
- controller.signal.addEventListener('abort', () => {
83
- var _abortRef$current;
84
- if (((_abortRef$current = abortRef.current) === null || _abortRef$current === void 0 ? void 0 : _abortRef$current.controller) === controller) {
85
- abortRef.current = null;
86
- setResponding(false);
87
- }
142
+ const abortPromise = new Promise(resolve => {
143
+ abortResolve = resolve;
88
144
  });
145
+ if (!dispatch(InputAction.SEND, {
146
+ abort: async () => {
147
+ if (dispatch(InputAction.ABORT, {})) {
148
+ controller.abort('User abort');
149
+ await abortPromise;
150
+ dispatch(InputAction.ABORT_DONE, {});
151
+ }
152
+ }
153
+ })) {
154
+ return;
155
+ }
156
+ setUploaded([]);
157
+ setMoreOpen(false);
158
+ setText('');
89
159
  try {
90
160
  await agent.pushInputBlocks(inputBlocks, controller.signal);
91
- if (controller.signal.aborted) {
92
- abortResolve();
93
- }
94
161
  } finally {
95
- if (!isUnmounted()) {
96
- setResponding(false);
162
+ abortResolve();
163
+ if (!isUnmounted() && !controller.signal.aborted) {
164
+ dispatch(InputAction.TEXT_END, {});
97
165
  }
98
166
  }
99
167
  };
@@ -101,43 +169,16 @@ export default function MessageInputAIStream(props) {
101
169
  let {
102
170
  blocks
103
171
  } = _ref2;
104
- if (uploading || responding) {
172
+ if (uploading) {
105
173
  return;
106
174
  }
107
- setText('');
108
- setMoreOpen(false);
109
- setUploaded([]);
110
- setResponding(true);
111
- const controller = new AbortController();
112
- let abortResolve;
113
- abortRef.current = {
114
- controller,
115
- promise: new Promise(resolve => {
116
- abortResolve = resolve;
117
- })
118
- };
119
- controller.signal.addEventListener('abort', () => {
120
- if (abortRef.current.controller === controller) {
121
- abortRef.current = null;
122
- }
123
- setResponding(false);
124
- });
125
- try {
126
- await agent.pushInputBlocks(blocks, controller.signal);
127
- if (controller.signal.aborted) {
128
- abortResolve();
129
- }
130
- } finally {
131
- if (!isUnmounted()) {
132
- setResponding(false);
133
- }
134
- }
175
+ send(blocks);
135
176
  });
136
177
  useOnEvent('setInputBlocks', async _ref3 => {
137
178
  let {
138
179
  blocks
139
180
  } = _ref3;
140
- if (uploading || responding) {
181
+ if (uploading || state.current !== InputState.PENDING) {
141
182
  return;
142
183
  }
143
184
  if (mode !== 'text') {
@@ -163,9 +204,10 @@ export default function MessageInputAIStream(props) {
163
204
  });
164
205
  }
165
206
  };
166
- useSleep();
167
207
  let container;
168
- const canSend = text.trim().length && !responding && !attachmentInput.uploading;
208
+ const canSend = text.trim().length && state.current === InputState.PENDING && !attachmentInput.uploading;
209
+ const canAbort = state.current === InputState.RESPONDING || state.current === InputState.ASR;
210
+ const recordingFlagRef = useRef(false);
169
211
  if (mode === 'text') {
170
212
  container = /*#__PURE__*/React.createElement(View, {
171
213
  className: "t-agent-message-input-text-bar"
@@ -217,15 +259,14 @@ export default function MessageInputAIStream(props) {
217
259
  className: cx('t-agent-message-input-button', {
218
260
  't-agent-message-input-button-more': isMore,
219
261
  't-agent-message-input-button-more-open': moreOpen && isMore,
220
- 't-agent-message-input-button-send': !isMore && !responding,
221
- 't-agent-message-input-button-stop': responding
262
+ 't-agent-message-input-button-send': !isMore && !canAbort,
263
+ 't-agent-message-input-button-stop': canAbort
222
264
  }),
223
265
  "data-testid": "t-agent-message-input-button-main",
224
266
  onClick: async () => {
225
- if (responding) {
226
- if (abortRef.current) {
227
- abortRef.current.controller.abort('User abort');
228
- }
267
+ if (canAbort) {
268
+ var _state$payload$abort, _state$payload;
269
+ await ((_state$payload$abort = (_state$payload = state.payload).abort) === null || _state$payload$abort === void 0 ? void 0 : _state$payload$abort.call(_state$payload));
229
270
  } else if (isMore) {
230
271
  openMoreClick();
231
272
  } else if (canSend) {
@@ -238,92 +279,144 @@ export default function MessageInputAIStream(props) {
238
279
  }));
239
280
  } else {
240
281
  container = /*#__PURE__*/React.createElement(AsrInput, {
241
- responding: responding,
242
- disabled: responding,
282
+ responding: canAbort,
283
+ disabled: state.current === InputState.ABORTING,
243
284
  amplitudeCount: AMPLITUDE_COUNT,
244
- recording: record.recording,
285
+ recording: state.current === InputState.RECORDING,
245
286
  onRecord: async () => {
287
+ logger.debug('MessageInputAIStream', 'AsrInput onRecord');
246
288
  if (attachmentInput.uploading) {
247
289
  return;
248
290
  }
249
- const abort = abortRef.current;
250
- if (responding && abort) {
251
- abort.controller.abort('User abort');
252
- // 中断后等待上次结束再开始
253
- await abort.promise;
291
+ recordingFlagRef.current = true;
292
+ if (canAbort) {
293
+ logger.debug('MessageInputAIStream', 'AsrInput onRecord canAbort');
294
+ await state.payload.abort();
295
+ logger.debug('MessageInputAIStream', 'AsrInput onRecord canAbort done');
254
296
  }
297
+ if (!recordingFlagRef.current) {
298
+ return;
299
+ }
300
+ recordingFlagRef.current = false;
301
+ // 有可能在中断完成前就触发了录音,所以需要检查一下状态
302
+ // 中断完成后,再检查一次状态,如果取消了,那么不再继续录音
303
+
255
304
  const emitter = new Emitter();
256
- const id = setTimeout(() => {
257
- if (r.recording) {
305
+ emitter.addEventListener('error', async error => {
306
+ logger.error('MessageInputAIStream', 'AsrInput error', error);
307
+ if (dispatch(InputAction.ASR_ERROR, {})) {
308
+ var _error$detail;
309
+ if (((_error$detail = error.detail) === null || _error$detail === void 0 ? void 0 : _error$detail.name) === 'AsrEmptyError') {
310
+ ty.showToast({
311
+ icon: 'error',
312
+ title: t('t-agent.input.asr.error.empty')
313
+ });
314
+ } else {
315
+ ty.showToast({
316
+ icon: 'error',
317
+ title: t('t-agent.input.asr.error.unknown')
318
+ });
319
+ }
320
+ }
321
+ });
322
+ emitter.addEventListener('finish', () => {
323
+ dispatch(InputAction.ASR_END, {
324
+ abort
325
+ });
326
+ });
327
+ const controller = new AbortController();
328
+ let abortResolve;
329
+ const abortPromise = new Promise(resolve => {
330
+ abortResolve = resolve;
331
+ });
332
+ const abort = async () => {
333
+ if (dispatch(InputAction.ABORT, {})) {
334
+ controller.abort('User abort');
335
+ await abortPromise;
336
+ dispatch(InputAction.ABORT_DONE, {});
337
+ }
338
+ };
339
+ const recordTimeOutId = setTimeout(async () => {
340
+ if (dispatch(InputAction.RECORD_TIMEOUT, {
341
+ abort
342
+ })) {
343
+ clearTimeout(recordTimeOutId);
344
+ emitter.dispatchEvent(new EmitterEvent('confirm'));
258
345
  ty.showToast({
259
346
  icon: 'none',
260
347
  title: t('t-agent.input.asr.error.timeout')
261
348
  });
262
- r.confirm();
263
349
  }
264
350
  }, props.maxAudioMs || 30000);
265
- const r = {
266
- startAt: Date.now(),
267
- recording: true,
268
- confirm: () => {
269
- r.recording = false;
270
- clearTimeout(id);
271
- emitter.dispatchEvent(new EmitterEvent('confirm'));
272
- setRecord({
273
- startAt: 0,
274
- recording: false,
275
- confirm: null,
276
- cancel: null
277
- });
278
- },
279
- cancel: () => {
280
- r.recording = false;
281
- clearTimeout(id);
282
- emitter.dispatchEvent(new EmitterEvent('cancel'));
283
- setRecord({
284
- startAt: 0,
285
- recording: false,
286
- confirm: null,
287
- cancel: null
288
- });
289
- }
290
- };
291
- setRecord(r);
292
- emitter.addEventListener('error', () => {
293
- ty.showToast({
294
- icon: 'error',
295
- title: t('t-agent.input.asr.error.empty')
296
- });
297
- setRecord({
298
- startAt: 0,
299
- recording: false,
300
- confirm: null,
301
- cancel: null
302
- });
303
- });
304
- await send([...attachmentInput.blocks, {
351
+ if (!dispatch(InputAction.RECORD, {
352
+ emitter,
353
+ recordTimeOutId,
354
+ recordStartAt: Date.now(),
355
+ abort
356
+ })) {
357
+ return;
358
+ }
359
+ setUploaded([]);
360
+ setMoreOpen(false);
361
+ setText('');
362
+ const inputBlocks = [...attachmentInput.blocks, {
305
363
  type: 'audio',
306
364
  audio_emitter: emitter,
307
365
  amplitude_count: AMPLITUDE_COUNT
308
- }]);
366
+ }];
367
+ try {
368
+ logger.debug('MessageInputAIStream', 'pushInputBlocks start');
369
+ await agent.pushInputBlocks(inputBlocks, controller.signal);
370
+ logger.debug('MessageInputAIStream', 'pushInputBlocks end');
371
+ } catch (error) {
372
+ if (!isAbortError(error)) {
373
+ throw error;
374
+ }
375
+ } finally {
376
+ abortResolve();
377
+ if (!isUnmounted() && !controller.signal.aborted) {
378
+ dispatch(InputAction.TEXT_END, {});
379
+ }
380
+ }
309
381
  },
310
- onConfirm: () => {
311
- var _record$confirm;
312
- (_record$confirm = record.confirm) === null || _record$confirm === void 0 || _record$confirm.call(record);
382
+ onConfirm: async () => {
383
+ logger.debug('MessageInputAIStream', 'AsrInput onConfirm');
384
+ recordingFlagRef.current = false;
385
+ if (state.current === InputState.ABORTING) {
386
+ return;
387
+ }
388
+ const payload = state.payload;
389
+ if (dispatch(InputAction.RECORD_CONFIRM, {
390
+ abort: payload.abort
391
+ })) {
392
+ clearTimeout(payload.recordTimeOutId);
393
+ payload.emitter.dispatchEvent(new EmitterEvent('confirm'));
394
+ }
313
395
  },
314
- onCancel: () => {
315
- var _record$cancel;
316
- (_record$cancel = record.cancel) === null || _record$cancel === void 0 || _record$cancel.call(record);
396
+ onCancel: async () => {
397
+ logger.debug('MessageInputAIStream', 'AsrInput onCancel');
398
+ recordingFlagRef.current = false;
399
+ if (state.current === InputState.ABORTING) {
400
+ return false;
401
+ }
402
+ const payload = state.payload;
403
+ if (dispatch(InputAction.RECORD_CANCEL, {})) {
404
+ clearTimeout(payload.recordTimeOutId);
405
+ logger.debug('MessageInputAIStream', 'AsrInput onCancel send cancel');
406
+ payload.emitter.dispatchEvent(new EmitterEvent('cancel'));
407
+ await payload.abort();
408
+ return true;
409
+ }
410
+ return false;
317
411
  },
318
412
  onBack: () => {
319
413
  setText('');
320
414
  setMode('text');
321
415
  setMoreOpen(false);
322
416
  },
323
- onAbort: () => {
324
- if (responding && abortRef.current) {
325
- abortRef.current.controller.abort('User abort');
326
- }
417
+ onAbort: async () => {
418
+ var _state$payload$abort2, _state$payload2;
419
+ await ((_state$payload$abort2 = (_state$payload2 = state.payload).abort) === null || _state$payload$abort2 === void 0 ? void 0 : _state$payload$abort2.call(_state$payload2));
327
420
  }
328
421
  });
329
422
  }
@@ -379,7 +472,7 @@ export default function MessageInputAIStream(props) {
379
472
  className: "t-agent-message-input-panel ".concat(moreOpen ? '' : 't-agent-message-input-panel-close')
380
473
  }, /*#__PURE__*/React.createElement(View, {
381
474
  className: "t-agent-message-input-panel-content"
382
- }, attachmentOptions.image && /*#__PURE__*/React.createElement(Button, {
475
+ }, (attachmentOptions === null || attachmentOptions === void 0 ? void 0 : attachmentOptions.image) && /*#__PURE__*/React.createElement(Button, {
383
476
  className: "t-agent-message-input-panel-button",
384
477
  onClick: async () => {
385
478
  try {
@@ -402,7 +495,7 @@ export default function MessageInputAIStream(props) {
402
495
  className: "t-agent-message-input-panel-button-icon"
403
496
  }, /*#__PURE__*/React.createElement(Image, {
404
497
  src: imageSvg
405
- }))), attachmentOptions.image && /*#__PURE__*/React.createElement(Button, {
498
+ }))), (attachmentOptions === null || attachmentOptions === void 0 ? void 0 : attachmentOptions.image) && /*#__PURE__*/React.createElement(Button, {
406
499
  className: "t-agent-message-input-panel-button",
407
500
  onClick: async () => {
408
501
  try {
@@ -425,7 +518,7 @@ export default function MessageInputAIStream(props) {
425
518
  className: "t-agent-message-input-panel-button-icon"
426
519
  }, /*#__PURE__*/React.createElement(Image, {
427
520
  src: cameraSvg
428
- }))), attachmentOptions.video && /*#__PURE__*/React.createElement(Button, {
521
+ }))), (attachmentOptions === null || attachmentOptions === void 0 ? void 0 : attachmentOptions.video) && /*#__PURE__*/React.createElement(Button, {
429
522
  className: "t-agent-message-input-panel-button",
430
523
  onClick: async () => {
431
524
  try {
@@ -349,6 +349,13 @@
349
349
  text-align: center;
350
350
  }
351
351
 
352
+ .t-agent-message-input-ptt-disabled {
353
+ .t-agent-message-input-ptt-text {
354
+ color: var(--app-B1-N3);
355
+ }
356
+ }
357
+
358
+
352
359
  .t-agent-message-input-ptt-overlay-cancel {
353
360
 
354
361
  }
@@ -8,7 +8,6 @@ import { View } from '@ray-js/components';
8
8
  import React, { useMemo, useRef, useState } from 'react';
9
9
  import { ScrollView } from '@ray-js/ray';
10
10
  import { generateId } from '@ray-js/t-agent';
11
- import { isVersionMatch } from '@ray-js/t-agent-plugin-aistream';
12
11
  import MessageRender from '../MessageRender';
13
12
  import { useAgentMessage, useAgentSessionValue, useOnEvent } from '../hooks';
14
13
  import { useDebouncedFn } from '../hooks/useDebouncedFn';
@@ -40,7 +39,7 @@ export default function MessageList(props) {
40
39
  } = systemInfo;
41
40
  return {
42
41
  // 在 2.27.2 版本之前,pageScrollTo 在某些场景不生效
43
- scroll: containerVersion && isVersionMatch('>=2.27.2', containerVersion)
42
+ scroll: false
44
43
  };
45
44
  }, []);
46
45
  const scroll = useDebouncedFn(animation => {
@@ -22,6 +22,7 @@ declare const _default: {
22
22
  't-agent.input.asr.ptt': string;
23
23
  't-agent.input.asr.error.too-short': string;
24
24
  't-agent.input.asr.error.empty': string;
25
+ 't-agent.input.asr.error.unknown': string;
25
26
  't-agent.input.asr.error.timeout': string;
26
27
  't-agent.message.feedback.success': string;
27
28
  't-agent.message.bubble.aborted': string;
@@ -165,6 +166,7 @@ declare const _default: {
165
166
  't-agent.input.asr.ptt': string;
166
167
  't-agent.input.asr.error.too-short': string;
167
168
  't-agent.input.asr.error.empty': string;
169
+ 't-agent.input.asr.error.unknown': string;
168
170
  't-agent.input.asr.error.timeout': string;
169
171
  't-agent.message.feedback.success': string;
170
172
  't-agent.message.bubble.aborted': string;
@@ -22,6 +22,7 @@ export default {
22
22
  't-agent.input.asr.ptt': '按住说话',
23
23
  't-agent.input.asr.error.too-short': '说话时间太短',
24
24
  't-agent.input.asr.error.empty': '未能从语音中识别到文字',
25
+ 't-agent.input.asr.error.unknown': '语音识别失败',
25
26
  't-agent.input.asr.error.timeout': '语音识别已达时长限制,将直接发送',
26
27
  't-agent.message.feedback.success': '反馈成功',
27
28
  't-agent.message.bubble.aborted': '用户中断',
@@ -165,6 +166,7 @@ export default {
165
166
  't-agent.input.asr.ptt': 'Press & hold to talk',
166
167
  't-agent.input.asr.error.too-short': 'Speaking time too short',
167
168
  't-agent.input.asr.error.empty': 'No text recognized from voice',
169
+ 't-agent.input.asr.error.unknown': 'Text recognized failed',
168
170
  't-agent.input.asr.error.timeout': 'Voice recognition has reached time limit, sending directly',
169
171
  't-agent.message.feedback.success': 'Feedback Successful',
170
172
  't-agent.message.bubble.aborted': 'User Aborted',
@@ -8,7 +8,6 @@ export default function ImageTile(props) {
8
8
  const {
9
9
  src
10
10
  } = props.tile.data;
11
- console.log('props.tile.data', props.tile.data);
12
11
  const {
13
12
  getStaticResourceBizType
14
13
  } = useRenderOptions();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/t-agent-ui-ray",
3
- "version": "0.2.0-beta-11",
3
+ "version": "0.2.0-beta-13",
4
4
  "author": "Tuya.inc",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -40,5 +40,5 @@
40
40
  "@types/echarts": "^4.9.22",
41
41
  "@types/markdown-it": "^14.1.1"
42
42
  },
43
- "gitHead": "dd56b31b0095fb82d0fb5d4f58581d00ae2970ee"
43
+ "gitHead": "ad4d4b4637a4a5396bcf5adf21adcbf215561436"
44
44
  }