@ray-js/t-agent-ui-ray 0.2.8-beta.1 → 0.2.8-beta.3

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.
Files changed (45) hide show
  1. package/README-zh_CN.md +337 -87
  2. package/README.md +916 -706
  3. package/dist/LowCodeCardRender/index.js +1 -0
  4. package/dist/MessageInput/MessageInputAIStream/index.js +2 -24
  5. package/dist/MessageInput/index.js +1 -0
  6. package/dist/MessageList/ScrollBottomView.d.ts +2 -2
  7. package/dist/PrivateImage/index.js +7 -10
  8. package/dist/contexts.d.ts +0 -1
  9. package/dist/hooks/context.d.ts +1 -1
  10. package/dist/hooks/useAttachmentInput.d.ts +1 -2
  11. package/dist/i18n/strings.js +1 -0
  12. package/dist/index.js +1 -0
  13. package/dist/renderOption.js +7 -6
  14. package/dist/tiles/BubbleTile/index.d.ts +15 -1
  15. package/dist/tiles/BubbleTile/index.js +60 -68
  16. package/dist/tiles/BubbleToolTile/audio-play.svg +1 -0
  17. package/dist/tiles/BubbleToolTile/audio-playing.svg +24 -0
  18. package/dist/tiles/BubbleToolTile/copy.svg +1 -0
  19. package/dist/tiles/BubbleToolTile/index.d.ts +10 -0
  20. package/dist/tiles/BubbleToolTile/index.js +63 -0
  21. package/dist/tiles/BubbleToolTile/index.less +46 -0
  22. package/dist/tiles/CardTile/index.d.ts +1 -1
  23. package/dist/tiles/DividerTile/index.d.ts +1 -1
  24. package/dist/tiles/OperateCardTile/Expand.d.ts +1 -1
  25. package/dist/tiles/TextTile/index.d.ts +1 -1
  26. package/dist/tiles/TimeTile/index.js +17 -16
  27. package/dist/tiles/TipTile/index.d.ts +1 -1
  28. package/dist/tiles/map.js +3 -3
  29. package/dist/tiles/types.d.ts +1 -1
  30. package/dist/utils/abort.js +1 -0
  31. package/dist/utils/createSharedStore.d.ts +2 -2
  32. package/dist/utils/getMessageContent.d.ts +11 -0
  33. package/dist/utils/getMessageContent.js +49 -0
  34. package/dist/utils/index.d.ts +1 -0
  35. package/dist/utils/index.js +3 -1
  36. package/dist/utils/ttt.d.ts +1 -0
  37. package/dist/utils/ttt.js +24 -0
  38. package/package.json +5 -4
  39. package/dist/tiles/WorkflowTile/RollBack/index.d.ts +0 -5
  40. package/dist/tiles/WorkflowTile/RollBack/index.js +0 -27
  41. package/dist/tiles/WorkflowTile/RollBack/index.less +0 -20
  42. package/dist/tiles/WorkflowTile/RollBack/workflow-rollback.png +0 -0
  43. package/dist/tiles/WorkflowTile/index.d.ts +0 -21
  44. package/dist/tiles/WorkflowTile/index.js +0 -32
  45. package/dist/tiles/WorkflowTile/index.less +0 -31
@@ -1,3 +1,4 @@
1
+ /* istanbul ignore file */
1
2
  import './index.less';
2
3
  import { View } from '@ray-js/components';
3
4
  import React from 'react';
@@ -16,10 +16,9 @@ import cameraSvg from '../icons/camera.svg';
16
16
  import { useAttachmentInput, useChatAgent, useEmitEvent, useIsUnmounted, useOnEvent, useTranslate } from '../../hooks';
17
17
  import AsrInput from './AsrInput';
18
18
  import logger from '../../logger';
19
- import { systemInfo } from '../../utils';
20
19
  import { useSleep } from '../../hooks/useSleep';
21
20
  import { useStableCallback } from '../../hooks/useStableCallback';
22
- import { authorize } from '../../utils/ttt';
21
+ import { authorize, initAudioRecorder } from '../../utils/ttt';
23
22
  export let MessageInputState = /*#__PURE__*/function (MessageInputState) {
24
23
  MessageInputState["PENDING"] = "pending";
25
24
  MessageInputState["RECORDING"] = "recording";
@@ -258,28 +257,7 @@ export default function MessageInputAIStream(props) {
258
257
  }
259
258
  if (!initAudioRef.current) {
260
259
  initAudioRef.current = true;
261
- await new Promise(resolve => {
262
- if (!ty.aistream.initAudioRecorder || systemInfo.brand === 'devtools') {
263
- resolve();
264
- return;
265
- }
266
- try {
267
- logger.debug('MessageInputAIStream', 'initAudioRecorder');
268
- ty.aistream.initAudioRecorder({
269
- success: () => {
270
- logger.debug('MessageInputAIStream', 'initAudioRecorder success');
271
- resolve();
272
- },
273
- fail: error => {
274
- logger.error('MessageInputAIStream', 'initAudioRecorder error', error);
275
- resolve();
276
- }
277
- });
278
- } catch (error) {
279
- logger.error('MessageInputAIStream', 'initAudioRecorder error', error);
280
- resolve();
281
- }
282
- });
260
+ await initAudioRecorder();
283
261
  }
284
262
  setText('');
285
263
  setMode('voice');
@@ -1,3 +1,4 @@
1
+ /* istanbul ignore file */
1
2
  import MessageInputAIStream, { MessageInputState } from './MessageInputAIStream';
2
3
  export { MessageInputState };
3
4
  export default MessageInputAIStream;
@@ -10,8 +10,8 @@ interface ScrollBottomViewOptions {
10
10
  }
11
11
  export declare function useScrollBottomView(options: ScrollBottomViewOptions): {
12
12
  scrollToBottom: ({ animation, follow }: {
13
- animation?: boolean | undefined;
14
- follow?: boolean | undefined;
13
+ animation?: boolean;
14
+ follow?: boolean;
15
15
  }) => Promise<boolean>;
16
16
  scrollViewLoading: boolean;
17
17
  scrollIntoViewId: string;
@@ -3,8 +3,8 @@ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutPr
3
3
  const _excluded = ["src", "bizType"];
4
4
  import "core-js/modules/web.dom-collections.iterator.js";
5
5
  import React, { useMemo, useRef, useState } from 'react';
6
- import { Image, View } from '@ray-js/ray';
7
- import { getUrlByCloudKey, isLinkExpired, parseCloudKey, isFullLink } from '../utils/file';
6
+ import { Image } from '@ray-js/ray';
7
+ import { getUrlByCloudKey, isLinkExpired, parseCloudKey } from '../utils/file';
8
8
  import logger from '../logger';
9
9
  const PrivateImage = /*#__PURE__*/React.forwardRef((props, ref) => {
10
10
  const {
@@ -73,13 +73,10 @@ const PrivateImage = /*#__PURE__*/React.forwardRef((props, ref) => {
73
73
  // }
74
74
  // }, [expired, url, bizType]);
75
75
 
76
- if (loading || !url || !isFullLink(url)) {
77
- return /*#__PURE__*/React.createElement(View, {
78
- key: url,
79
- className: rest.className,
80
- style: rest.style
81
- });
82
- }
76
+ // if (loading || !url || !isFullLink(url)) {
77
+ // return <View key={url} className={rest.className} style={rest.style} />;
78
+ // }
79
+
83
80
  return /*#__PURE__*/React.createElement(Image, _extends({
84
81
  ref: ref,
85
82
  key: url,
@@ -107,7 +104,7 @@ const PrivateImage = /*#__PURE__*/React.forwardRef((props, ref) => {
107
104
  }
108
105
  (_props$onError = props.onError) === null || _props$onError === void 0 || _props$onError.call(props, event);
109
106
  },
110
- src: url
107
+ src: src
111
108
  }, rest));
112
109
  });
113
110
  export default PrivateImage;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ChatAgent, ChatMessageObject, UIPlugin } from '@ray-js/t-agent';
3
2
  import { RenderOptions, TileProps } from './types';
4
3
  import { ChatSession } from '@ray-js/t-agent';
@@ -7,5 +7,5 @@ export declare const useKeyboardHeight: () => number;
7
7
  export declare const useOnEvent: (eventName: string, callback: (details: any) => void) => void;
8
8
  export declare const useEmitEvent: () => <T extends keyof import("@ray-js/t-agent").UIEventMap>(eventName: T, detail: import("@ray-js/t-agent").UIEventMap[T]) => void;
9
9
  export declare const useTileProps: () => import("../types").TileProps<any, any>;
10
- export declare const useSendAction: () => (action: TTTAction) => void;
10
+ export declare const useSendAction: () => ((action: TTTAction) => void);
11
11
  export declare const useAgentSessionValue: <S = any>(key: string) => readonly [S, Dispatch<SetStateAction<S>>];
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { InputBlock } from '@ray-js/t-agent';
3
2
  export type UploadFile = {
4
3
  id: string;
@@ -18,5 +17,5 @@ export declare function useAttachmentInput({ local }?: {
18
17
  setUploaded: import("react").Dispatch<import("react").SetStateAction<UploadFile[]>>;
19
18
  uploading: boolean;
20
19
  loadBlocks: (blocks: InputBlock[], append?: boolean) => void;
21
- upload: (type: 'image' | 'video' | 'camera' | 'album', count?: any) => Promise<void>;
20
+ upload: (type: "image" | "video" | "camera" | "album", count?: any) => Promise<void>;
22
21
  };
@@ -1,3 +1,4 @@
1
+ /* istanbul ignore file */
1
2
  export default {
2
3
  'zh-Hans': {
3
4
  't-agent.build-in.button.create_scene_manually': '手动创建场景',
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ /* istanbul ignore file */
1
2
  import ChatContainer from './ChatContainer';
2
3
  import MessageInput from './MessageInput';
3
4
  import MessageList from './MessageList';
@@ -72,13 +72,14 @@ const defaultRenderLongPressAs = res => {
72
72
  return /*#__PURE__*/React.createElement(LongPressActionMenu, res.menuProps);
73
73
  };
74
74
  const i18nTranslate = key => I18n.t(key);
75
+ const formatErrorMessageAs = (message, code) => {
76
+ if (code) {
77
+ return translateWith("t-agent.error.".concat(code), i18nTranslate);
78
+ }
79
+ return message;
80
+ };
75
81
  export const defaultRenderOptions = {
76
- formatErrorMessageAs: (message, code) => {
77
- if (code) {
78
- return translateWith("t-agent.error.".concat(code), i18nTranslate);
79
- }
80
- return message;
81
- },
82
+ formatErrorMessageAs,
82
83
  renderTileAs: defaultChatTileAs,
83
84
  renderCustomBlockAs: defaultRenderCustomBlockAs,
84
85
  customBlockTypes: defaultCustomBlockTypes,
@@ -2,5 +2,19 @@ import './index.less';
2
2
  import React from 'react';
3
3
  import { BubbleTileData } from '@ray-js/t-agent';
4
4
  import { TileProps } from '../../types';
5
- declare const _default: React.MemoExoticComponent<(props: TileProps<BubbleTileData, any>) => React.JSX.Element>;
5
+ /** Unified props passed to every overridable slot component of BubbleTile. */
6
+ type BubbleTileSlotProps = TileProps<BubbleTileData>;
7
+ export interface BubbleTileProps extends TileProps<BubbleTileData> {
8
+ /** Rendered at the top of the bubble content, before the children. */
9
+ Header?: React.ComponentType<BubbleTileSlotProps>;
10
+ /** Rendered at the bottom of the bubble content, after the children. */
11
+ Footer?: React.ComponentType<BubbleTileSlotProps>;
12
+ /** Overrides the default error / warning side icon. */
13
+ ErrorNotice?: React.ComponentType<BubbleTileSlotProps>;
14
+ /** Overrides the default loading indicator. */
15
+ LoadingIndicator?: React.ComponentType<BubbleTileSlotProps>;
16
+ /** Overrides the standalone error-alert bubble (empty assistant error message). */
17
+ ErrorBubble?: React.ComponentType<BubbleTileSlotProps>;
18
+ }
19
+ declare const _default: React.MemoExoticComponent<(props: BubbleTileProps) => React.JSX.Element>;
6
20
  export default _default;
@@ -1,26 +1,31 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import "core-js/modules/esnext.iterator.constructor.js";
3
- import "core-js/modules/esnext.iterator.find.js";
4
3
  import "core-js/modules/esnext.iterator.map.js";
5
- import "core-js/modules/esnext.iterator.some.js";
6
4
  import './index.less';
7
5
  import { View } from '@ray-js/components';
8
- import React, { memo, useCallback, useMemo } from 'react';
6
+ import React, { memo, useMemo } from 'react';
9
7
  import { BubbleTileStatus, ChatMessageStatus } from '@ray-js/t-agent';
10
8
  import TileRender from '../../TileRender';
11
9
  import { useLongPress, useRenderOptions, useTranslate } from '../../hooks';
12
- import RollBack from '../WorkflowTile/RollBack';
10
+ import { getMessageContent as _getMessageContent } from '../../utils';
11
+ import { useStableCallback } from '../../hooks/useStableCallback';
12
+
13
+ /** Unified props passed to every overridable slot component of BubbleTile. */
14
+
13
15
  const BubbleTile = props => {
14
- var _workflowTile$data;
15
16
  const {
16
- renderLongPressAs,
17
- formatErrorMessageAs
17
+ renderLongPressAs
18
18
  } = useRenderOptions();
19
19
  const {
20
20
  message,
21
21
  tile,
22
22
  isLatestMessage,
23
- side
23
+ side,
24
+ Header,
25
+ Footer,
26
+ ErrorNotice = DefaultErrorNotice,
27
+ LoadingIndicator = DefaultLoadingIndicator,
28
+ ErrorBubble = DefaultErrorBubble
24
29
  } = props;
25
30
  const {
26
31
  status,
@@ -33,24 +38,7 @@ const BubbleTile = props => {
33
38
  const bubbleStatus = data.status || BubbleTileStatus.NORMAL;
34
39
  const t = useTranslate();
35
40
  const loading = status === ChatMessageStatus.START || status === ChatMessageStatus.UPDATING;
36
-
37
- // 获取消息内容的函数
38
- const getMessageContent = useCallback(() => {
39
- let messageContent = '';
40
- if (tile.children && tile.children.length > 0) {
41
- // 查找文本类型的tile
42
- const textTile = tile.children.find(child => child.type === 'text');
43
- if (textTile && textTile.data && typeof textTile.data === 'object' && 'text' in textTile.data) {
44
- messageContent = textTile.data.text;
45
- }
46
- }
47
-
48
- // 如果是文本类型的tile,直接获取文本内容
49
- if (tile.type === 'text' && tile.data && typeof tile.data === 'object' && 'text' in tile.data) {
50
- messageContent = tile.data.text;
51
- }
52
- return messageContent;
53
- }, [tile]);
41
+ const getMessageContent = useStableCallback(() => _getMessageContent(message));
54
42
  const longPressRes = useLongPress({
55
43
  message,
56
44
  actions: role === 'assistant' ? ['copy', 'multiSelect', 'delete', 'like', 'unlike'] : ['copy', 'multiSelect', 'delete'],
@@ -58,6 +46,7 @@ const BubbleTile = props => {
58
46
  disabled: loading
59
47
  });
60
48
  const longPressBlock = renderLongPressAs(longPressRes);
49
+ const slotProps = props;
61
50
  const isErrorBubble = useMemo(() => {
62
51
  let empty = true;
63
52
  for (let i = 0; i < children.length; i++) {
@@ -76,38 +65,13 @@ const BubbleTile = props => {
76
65
  }
77
66
  return empty && role === 'assistant' && bubbleStatus === BubbleTileStatus.ERROR && status === ChatMessageStatus.FINISH;
78
67
  }, [status, role, bubbleStatus, children]);
79
- if (isErrorBubble) {
80
- return /*#__PURE__*/React.createElement(View, _extends({
81
- className: "t-agent-bubble-tile t-agent-bubble-tile-error-alert",
82
- "data-testid": "t-agent-bubble-tile"
83
- }, longPressRes.longPressProps), /*#__PURE__*/React.createElement(View, {
84
- className: "t-agent-bubble-tile-error",
85
- "data-testid": "t-agent-bubble-tile-error"
86
- }), /*#__PURE__*/React.createElement(View, {
87
- className: "t-agent-bubble-tile-error-alert-text"
88
- }, formatErrorMessageAs(data.info, data.code) || t('t-agent.error.unknown-error')), longPressBlock);
89
- }
90
- const showInfo = () => {
91
- if (data.info) {
92
- ty.showToast({
93
- title: formatErrorMessageAs(data.info, data.code),
94
- icon: 'none'
95
- });
96
- }
97
- };
98
68
  const showAbortedMessage = bubbleStatus === BubbleTileStatus.ABORTED;
99
- const showRollBack = side === 'start' && children.some(child => child.type === 'workflow');
100
- const workflowTile = children.find(child => child.type === 'workflow');
101
- const workflowNode = workflowTile === null || workflowTile === void 0 || (_workflowTile$data = workflowTile.data) === null || _workflowTile$data === void 0 ? void 0 : _workflowTile$data.nodeId;
102
69
  return /*#__PURE__*/React.createElement(View, _extends({
103
- className: "t-agent-bubble-tile t-agent-bubble-tile-".concat(side),
70
+ className: "t-agent-bubble-tile t-agent-bubble-tile-".concat(side, " ").concat(isErrorBubble ? 't-agent-bubble-tile-error-alert' : ''),
104
71
  "data-testid": "t-agent-bubble-tile"
105
- }, longPressRes.longPressProps), side === 'end' && /*#__PURE__*/React.createElement(ErrorNotice, {
106
- bubbleStatus: bubbleStatus,
107
- showInfo: showInfo
108
- }), /*#__PURE__*/React.createElement(View, {
72
+ }, longPressRes.longPressProps), isErrorBubble ? /*#__PURE__*/React.createElement(ErrorBubble, slotProps) : /*#__PURE__*/React.createElement(React.Fragment, null, side === 'end' && /*#__PURE__*/React.createElement(ErrorNotice, slotProps), /*#__PURE__*/React.createElement(View, {
109
73
  className: "t-agent-bubble-tile-bubble ".concat(loading ? 't-agent-bubble-tile-bubble-loading' : '')
110
- }, (() => {
74
+ }, Header && /*#__PURE__*/React.createElement(Header, slotProps), (() => {
111
75
  return children.map(t => /*#__PURE__*/React.createElement(TileRender, {
112
76
  side: side,
113
77
  tile: t,
@@ -116,22 +80,47 @@ const BubbleTile = props => {
116
80
  isLatestMessage: isLatestMessage,
117
81
  notifyHeightChanged: props.notifyHeightChanged
118
82
  }));
119
- })(), /*#__PURE__*/React.createElement(LoadingIndicator, {
120
- status: status
121
- }), showAbortedMessage && /*#__PURE__*/React.createElement(View, {
83
+ })(), /*#__PURE__*/React.createElement(LoadingIndicator, slotProps), showAbortedMessage && /*#__PURE__*/React.createElement(View, {
122
84
  className: "t-agent-bubble-tile-aborted"
123
- }, t('t-agent.message.bubble.aborted'))), side === 'start' && /*#__PURE__*/React.createElement(ErrorNotice, {
124
- bubbleStatus: bubbleStatus,
125
- showInfo: showInfo
126
- }), longPressBlock, showRollBack && !isLatestMessage && workflowNode && /*#__PURE__*/React.createElement(RollBack, {
127
- nodeId: workflowNode
128
- }));
85
+ }, t('t-agent.message.bubble.aborted')), Footer && /*#__PURE__*/React.createElement(Footer, slotProps)), side === 'start' && /*#__PURE__*/React.createElement(ErrorNotice, slotProps)), longPressBlock);
129
86
  };
130
- const ErrorNotice = /*#__PURE__*/memo(_ref => {
87
+ const DefaultErrorBubble = /*#__PURE__*/memo(_ref => {
131
88
  let {
132
- bubbleStatus,
133
- showInfo
89
+ tile
134
90
  } = _ref;
91
+ const {
92
+ formatErrorMessageAs
93
+ } = useRenderOptions();
94
+ const t = useTranslate();
95
+ const {
96
+ data
97
+ } = tile;
98
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
99
+ className: "t-agent-bubble-tile-error",
100
+ "data-testid": "t-agent-bubble-tile-error"
101
+ }), /*#__PURE__*/React.createElement(View, {
102
+ className: "t-agent-bubble-tile-error-alert-text"
103
+ }, formatErrorMessageAs(data.info, data.code) || t('t-agent.error.unknown-error')));
104
+ });
105
+ const DefaultErrorNotice = /*#__PURE__*/memo(_ref2 => {
106
+ let {
107
+ tile
108
+ } = _ref2;
109
+ const {
110
+ formatErrorMessageAs
111
+ } = useRenderOptions();
112
+ const {
113
+ data
114
+ } = tile;
115
+ const bubbleStatus = data.status || BubbleTileStatus.NORMAL;
116
+ const showInfo = () => {
117
+ if (data.info) {
118
+ ty.showToast({
119
+ title: formatErrorMessageAs(data.info, data.code),
120
+ icon: 'none'
121
+ });
122
+ }
123
+ };
135
124
  if (bubbleStatus === BubbleTileStatus.ERROR) {
136
125
  return /*#__PURE__*/React.createElement(View, {
137
126
  onClick: showInfo,
@@ -148,10 +137,13 @@ const ErrorNotice = /*#__PURE__*/memo(_ref => {
148
137
  }
149
138
  return null;
150
139
  });
151
- const LoadingIndicator = /*#__PURE__*/memo(_ref2 => {
140
+ const DefaultLoadingIndicator = /*#__PURE__*/memo(_ref3 => {
152
141
  let {
142
+ message
143
+ } = _ref3;
144
+ const {
153
145
  status
154
- } = _ref2;
146
+ } = message;
155
147
  if (status === ChatMessageStatus.START) {
156
148
  return /*#__PURE__*/React.createElement(View, {
157
149
  className: "t-agent-bubble-tile-bubble-loader"
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="14.666666984558105" height="11.259817123413086" viewBox="0 0 14.666666984558105 11.259817123413086"><path d="M3.7352133,4.2966166L6,2.4435894L6,8.8162832L3.7352133,6.9632831L1.3333334,6.9632831L1.3333334,4.2966166L3.7352133,4.2966166ZM0.66666669,8.2966156L3.2592599,8.2966156L6.7889338,11.184483C6.8484669,11.233217,6.9230666,11.259817,7,11.259817C7.1840668,11.259817,7.3333335,11.110617,7.3333335,10.926483L7.3333335,0.33334273C7.3333335,0.256396,7.3067336,0.18181595,7.2580004,0.12226264C7.1414003,-0.020217419,6.9314003,-0.041217327,6.7889338,0.075356007L3.2592599,2.9632626L0.66666669,2.9632626C0.29848003,2.9632626,0,3.2617359,0,3.6299293L0,7.6299496C0,7.9981494,0.29848003,8.2966156,0.66666669,8.2966156ZM14.666667,5.6298828C14.666667,7.8245497,13.7026,9.7940826,12.1748,11.138016L11.229667,10.192817C12.5172,9.09235,13.333334,7.4564166,13.333334,5.6298828C13.333334,3.8033233,12.5172,2.1674094,11.229667,1.0669293L12.1748,0.12174273C13.7026,1.4656695,14.666667,3.4351826,14.666667,5.6298828ZM11.333334,5.6298828C11.333334,4.3554163,10.737334,3.2202029,9.8088665,2.4877026L8.8561335,3.440443C9.547533,3.9222496,10,4.7232165,10,5.6298828C10,6.5365496,9.547533,7.3374834,8.8561335,7.8192825L9.8088665,8.7720165C10.737334,8.0395498,11.333334,6.904283,11.333334,5.6298828Z" fill="#427FF7" fill-opacity="1" style="mix-blend-mode:passthrough"/></svg>
@@ -0,0 +1,24 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
2
+ <g fill="#427ff7">
3
+ <rect x="2.4" width="2.4" rx="1.2" y="9" height="6">
4
+ <animate attributeName="height" values="6;18;6" dur="0.9s" begin="0s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
5
+ <animate attributeName="y" values="9;3;9" dur="0.9s" begin="0s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
6
+ </rect>
7
+ <rect x="6.6" width="2.4" rx="1.2" y="6" height="12">
8
+ <animate attributeName="height" values="6;18;6" dur="0.9s" begin="-0.3s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
9
+ <animate attributeName="y" values="9;3;9" dur="0.9s" begin="-0.3s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
10
+ </rect>
11
+ <rect x="10.8" width="2.4" rx="1.2" y="3" height="18">
12
+ <animate attributeName="height" values="6;18;6" dur="0.9s" begin="-0.6s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
13
+ <animate attributeName="y" values="9;3;9" dur="0.9s" begin="-0.6s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
14
+ </rect>
15
+ <rect x="15" width="2.4" rx="1.2" y="6" height="12">
16
+ <animate attributeName="height" values="6;18;6" dur="0.9s" begin="-0.15s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
17
+ <animate attributeName="y" values="9;3;9" dur="0.9s" begin="-0.15s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
18
+ </rect>
19
+ <rect x="19.2" width="2.4" rx="1.2" y="9" height="6">
20
+ <animate attributeName="height" values="6;18;6" dur="0.9s" begin="-0.45s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
21
+ <animate attributeName="y" values="9;3;9" dur="0.9s" begin="-0.45s" repeatCount="indefinite" calcMode="spline" keyTimes="0;0.5;1" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
22
+ </rect>
23
+ </g>
24
+ </svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="16" height="16" viewBox="0 0 16 16"><defs><clipPath id="master_svg0_1631_18176"><rect x="0" y="0" width="16" height="16" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_1631_18176)"><path d="M4.6665335,4.000002576464844L4.6665335,2.0000025664648438C4.6665335,1.6318159064648436,4.9650133,1.3333358764648438,5.3332002,1.3333358764648438L13.3332,1.3333358764648438C13.7014,1.3333358764648438,13.999866,1.6318159064648436,13.999866,2.0000025664648438L13.999866,11.333335876464844C13.999866,11.701535876464844,13.7014,12.000002876464844,13.3332,12.000002876464844L11.3332005,12.000002876464844L11.3332005,13.999402876464844C11.3332005,14.367936876464844,11.033267,14.666669876464844,10.6620007,14.666669876464844L2.6711067,14.666669876464844C2.3003932799999998,14.666669876464844,2,14.370269876464844,2,13.999402876464844L2.0017333031,4.667249476464844C2.0018000603,4.298742776464843,2.30176005,4.000002576464844,2.67294663,4.000002576464844L4.6665335,4.000002576464844ZM3.3349466000000003,5.333335876464844L3.3334599000000003,13.333335876464844L9.9998665,13.333335876464844L9.9998665,5.333335876464844L3.3349466000000003,5.333335876464844ZM5.9998664999999995,4.000002576464844L11.3332005,4.000002576464844L11.3332005,10.666669876464844L12.666533,10.666669876464844L12.666533,2.6666692764648436L5.9998664999999995,2.6666692764648436L5.9998664999999995,4.000002576464844Z" fill="#427FF7" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import './index.less';
3
+ import { TileProps } from '../../types';
4
+ export interface BubbleToolTileData {
5
+ /** 播放所需的音频参数,由 aistream 插件下发时写入 */
6
+ audio?: Record<string, any>;
7
+ [key: string]: any;
8
+ }
9
+ declare const _default: React.MemoExoticComponent<(props: TileProps<BubbleToolTileData>) => React.JSX.Element | null>;
10
+ export default _default;
@@ -0,0 +1,63 @@
1
+ import "core-js/modules/web.dom-collections.iterator.js";
2
+ import React, { useEffect } from 'react';
3
+ import { View } from '@ray-js/components';
4
+ import './index.less';
5
+ import { useAgentSessionValue, useTranslate } from '../../hooks';
6
+ import { getMessageContent } from '../../utils';
7
+ const BubbleToolTile = props => {
8
+ const {
9
+ message,
10
+ isLatestMessage,
11
+ notifyHeightChanged
12
+ } = props;
13
+ // playing 不是 tile 的本地状态,而是从 session 的全局播放状态派生:
14
+ // 真正的播放/停止由 withBuildIn 处理,并把 “是否正在播放 / 正在播放的消息 id”
15
+ // 写入 session,UI 通过 sessionChange 事件感知变化。
16
+ const [audioPlaying] = useAgentSessionValue('AIStream.audioPlaying');
17
+ const [playingMessageId] = useAgentSessionValue('AIStream.playingMessageId');
18
+ const playing = !!audioPlaying && playingMessageId === message.id;
19
+
20
+ // UI 只负责发指令
21
+
22
+ const show = message.role === 'assistant' && isLatestMessage;
23
+ const t = useTranslate();
24
+ useEffect(() => {
25
+ if (!show) {
26
+ notifyHeightChanged();
27
+ }
28
+ }, [show]);
29
+ if (!show) {
30
+ return null;
31
+ }
32
+ return /*#__PURE__*/React.createElement(View, {
33
+ className: "t-agent-bubble-tool-tile"
34
+ }, /*#__PURE__*/React.createElement(View, {
35
+ className: "t-agent-bubble-tool-tile-divider"
36
+ }), /*#__PURE__*/React.createElement(View, {
37
+ className: "t-agent-bubble-tool-tile-actions"
38
+ }, /*#__PURE__*/React.createElement(View, {
39
+ className: "t-agent-bubble-tool-tile-button ".concat(playing ? 't-agent-bubble-tool-tile-play-active' : 't-agent-bubble-tool-tile-play'),
40
+ "data-testid": "t-agent-bubble-tool-tile-play",
41
+ onClick: () => {
42
+ props.emitTileEvent({
43
+ action: 'toggle'
44
+ });
45
+ }
46
+ }), /*#__PURE__*/React.createElement(View, {
47
+ className: "t-agent-bubble-tool-tile-button t-agent-bubble-tool-tile-copy",
48
+ "data-testid": "t-agent-bubble-tool-tile-copy",
49
+ onClick: () => {
50
+ const text = getMessageContent(message);
51
+ ty.setClipboardData({
52
+ data: text,
53
+ success() {
54
+ ty.showToast({
55
+ title: t('t-agent.message.copy.success'),
56
+ icon: 'none'
57
+ });
58
+ }
59
+ });
60
+ }
61
+ })));
62
+ };
63
+ export default /*#__PURE__*/React.memo(BubbleToolTile);
@@ -0,0 +1,46 @@
1
+ .t-agent-bubble-tool-tile {
2
+ }
3
+
4
+ .t-agent-bubble-tool-tile-divider {
5
+ flex: 1;
6
+ height: 1px;
7
+ background-color: var(--app-B3-N1);
8
+ opacity: 0.12;
9
+ margin: 16rpx 0;
10
+ }
11
+
12
+ .t-agent-bubble-tool-tile-actions {
13
+ display: flex;
14
+ }
15
+
16
+ .t-agent-bubble-tool-tile-button {
17
+ flex: 0 0 auto;
18
+ width: 48rpx;
19
+ height: 48rpx;
20
+ border-radius: 8rpx;
21
+ background-color: var(--app-B1);
22
+ background-repeat: no-repeat;
23
+ background-position: center center;
24
+ background-size: 28rpx 28rpx;
25
+ margin-right: 16rpx;
26
+
27
+ :first-child {
28
+ margin-right: 0;
29
+ }
30
+ }
31
+
32
+ .t-agent-bubble-tool-tile-play {
33
+ background-image: url("./audio-play.svg");
34
+ }
35
+
36
+ .t-agent-bubble-tool-tile-play-active {
37
+ background-image: url("./audio-playing.svg");
38
+ }
39
+
40
+ .t-agent-bubble-tool-tile-copy {
41
+ background-image: url("./copy.svg");
42
+ }
43
+
44
+ .t-agent-bubble-tool-tile-play-active {
45
+ opacity: 0.6;
46
+ }
@@ -2,5 +2,5 @@ import React from 'react';
2
2
  import './index.less';
3
3
  import { CardTileData } from '@ray-js/t-agent';
4
4
  import { TileProps } from '../../types';
5
- declare const _default: React.MemoExoticComponent<(props: TileProps<CardTileData, any>) => React.JSX.Element | null>;
5
+ declare const _default: React.MemoExoticComponent<(props: TileProps<CardTileData>) => React.JSX.Element | null>;
6
6
  export default _default;
@@ -4,5 +4,5 @@ import { TileProps } from '../../types';
4
4
  interface DividerTileData {
5
5
  text?: string;
6
6
  }
7
- declare const _default: React.MemoExoticComponent<(props: TileProps<DividerTileData, any>) => React.JSX.Element>;
7
+ declare const _default: React.MemoExoticComponent<(props: TileProps<DividerTileData>) => React.JSX.Element>;
8
8
  export default _default;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import './Expand.less';
3
3
  export declare enum SceneType {
4
- EXECUTE = 1,
4
+ EXECUTE = 1,// 一键执行
5
5
  AUTO = 2
6
6
  }
7
7
  type DeviceInfoItem = any;
@@ -5,5 +5,5 @@ interface TileData {
5
5
  text: string;
6
6
  markdown?: boolean;
7
7
  }
8
- declare const _default: React.MemoExoticComponent<(props: TileProps<TileData, any>) => React.JSX.Element>;
8
+ declare const _default: React.MemoExoticComponent<(props: TileProps<TileData>) => React.JSX.Element>;
9
9
  export default _default;
@@ -1,8 +1,15 @@
1
1
  import "core-js/modules/web.dom-collections.iterator.js";
2
2
  import { View } from '@ray-js/components';
3
3
  import React, { useEffect, useMemo, useState } from 'react';
4
- import dayjs from 'dayjs';
5
4
  import './index.less';
5
+ function formatDate(timestamp) {
6
+ const d = new Date(timestamp);
7
+ return [d.getFullYear(), String(d.getMonth() + 1).padStart(2, '0'), String(d.getDate()).padStart(2, '0')].join('-');
8
+ }
9
+ function formatTime(timestamp) {
10
+ const d = new Date(timestamp);
11
+ return [String(d.getHours()).padStart(2, '0'), String(d.getMinutes()).padStart(2, '0')].join(':');
12
+ }
6
13
  export default function TimeTile(props) {
7
14
  const {
8
15
  tile
@@ -10,25 +17,19 @@ export default function TimeTile(props) {
10
17
  const {
11
18
  timestamp
12
19
  } = tile.data;
13
- const [date, setDate] = useState(() => {
14
- return dayjs(timestamp).format('YYYY-MM-DD');
15
- });
20
+ const [today, setToday] = useState(() => formatDate(Date.now()));
16
21
  useEffect(() => {
17
- // 在当天结束时更新一下
22
+ const now = new Date();
23
+ const nextDay = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
18
24
  const timer = setTimeout(() => {
19
- setDate(dayjs(timestamp).format('YYYY-MM-DD'));
20
- }, dayjs(timestamp).endOf('day').diff(Date.now()));
21
- return () => {
22
- clearTimeout(timer);
23
- };
25
+ setToday(formatDate(Date.now()));
26
+ }, nextDay.getTime() - now.getTime());
27
+ return () => clearTimeout(timer);
24
28
  }, []);
25
29
  const time = useMemo(() => {
26
- // 当天的时间只显示时间,其他显示日期和时间
27
- if (date === dayjs(Date.now()).format('YYYY-MM-DD')) {
28
- return dayjs(timestamp).format('HH:mm');
29
- }
30
- return dayjs(timestamp).format('YYYY-MM-DD HH:mm');
31
- }, [timestamp, date]);
30
+ const tsDate = formatDate(timestamp);
31
+ return tsDate === today ? formatTime(timestamp) : "".concat(tsDate, " ").concat(formatTime(timestamp));
32
+ }, [timestamp, today]);
32
33
  return /*#__PURE__*/React.createElement(View, {
33
34
  className: "t-agent-time-tile"
34
35
  }, time);
@@ -2,5 +2,5 @@ import React from 'react';
2
2
  import './index.less';
3
3
  import { TipTileData } from '@ray-js/t-agent';
4
4
  import { TileProps } from '../../types';
5
- declare const _default: React.MemoExoticComponent<(props: TileProps<TipTileData, any>) => React.JSX.Element>;
5
+ declare const _default: React.MemoExoticComponent<(props: TileProps<TipTileData>) => React.JSX.Element>;
6
6
  export default _default;